Dependency cache live
Each Actions job restores node_modules from the repository's last snapshot
into memory, so installs start from a full tree instead of the registry.
How you get it
Most workflows get it with no change to the file.
| Your workflow has | What Gitstalk does |
|---|---|
actions/setup-node with cache: npm,
pnpm or
yarn
|
Automatic. cache-dependency-path names the directory if the
lockfile is not at the root.
|
actions/cache where every path is
node_modules or a package-manager store
|
Automatic. The step keeps its id, and cache-hit is
true on an exact hit.
|
| Neither | Add the opt-in step below. |
- uses: actions/checkout@v4
- uses: gitstalk/deps-cache@v1
with:
working-directory: ./web # only if the lockfile is not at the root
- run: npm ci
gitstalk/deps-cache@v1 was beanstalk/deps-cache@v1 before the
rename. The old name still works.
Turn it off or resize it
Maintainers and the owner change these in the repository's Settings, under Actions, Jobs.
Rules
- Only stalk runs save snapshots. Dispatch and schedule runs read them and never write, so a change that has not landed cannot alter what a later stalk run installs. (Pre-land workflow runs do not start yet; they will read only.)
- A snapshot belongs to one repository and is never shared. Deleting the repository deletes its snapshots.
-
node_moduleslives in memory (a tmpfs), never on the container disk. - The snapshot key is the lockfile plus the install directory, platform, Node and package-manager versions and the install flags. Another lockfile restores the closest snapshot, and the install brings it up to date.
-
With
npm ci, an exact hit is exactly the treenpm ciwould build, so it is kept and only your package's own install scripts run. After a lockfile changenpm ciruns as usual and the save uploads only the chunks that changed.pnpm install,yarn installandnpm installupdate a restored tree in place.
Measured results
A fastify job with 146 MB of dependencies and an unchanged lockfile, on the hosted service, in the same push:
- The first run and a lockfile change are slower than without the cache, by the time it takes to save the new snapshot at the end of the job. That was about 9 s for fastify.
-
On a test stack with
npm ci --no-audit, the restore took 1 to 3 s against 6 to 14 s from the registry, on fastify and on a Next.js-class app (533 MB). - These are our own measurements on one repository shape. Yours will differ. The runs are in the design write-up.
npm audit in installs
Jobs run npm with NPM_CONFIG_AUDIT=false and
NPM_CONFIG_FUND=false, so npm ci and
npm install skip the audit npm runs inside every install. It never changes
what is installed, but it is slow: for fastify's lockfile it took about 90 s of a 97 s
npm ci, against about 10 s without it.
To keep the audit, do one of these:
-
Tick Run npm's audit during installs above, which sets
GITSTALK_NPM_AUDIT=on. -
Set
NPM_CONFIG_AUDITin the workflow'senv:. Your ownenv:wins. - Run
npm auditas its own step. An explicit audit always runs.
Variables
| Variable | Effect |
|---|---|
GITSTALK_DEPS_CACHE |
off (also false, 0, no,
disabled) turns the cache off. Anything else leaves it on.
|
GITSTALK_DEPS_SNAPSHOT_MAX |
Largest snapshot, such as 2GiB or 500MB. Empty keeps
the default.
|
GITSTALK_NPM_AUDIT |
on (or true) keeps npm's audit. |
Set them as repository or org variables, or use the form
above. A variable still named BEANSTALK_*, from before the rename, is read
when the GITSTALK_* one is absent. Saving the form moves it over.
Limits
| Limit | Value |
|---|---|
| One snapshot, compressed | 4 GiB, a repository or org setting |
| All snapshots of a repository | 10 GB; the least recently restored are evicted |
| Snapshot unused for | 7 days, then deleted |
Memory for node_modules |
6 GiB per job |
A self-hoster changes all of these. See Limits and plans and Self-hosting.
Sources
- docs/claude-opus/27-ci-dependency-cache.md (design, spike and measured runs)