Skip to content
Latchkey

Volta: Cache VOLTA_HOME and Avoid Re-downloads in CI

Volta downloads each pinned toolchain into $VOLTA_HOME the first time a shim runs it, so caching that directory across CI runs removes repeated Node/npm downloads.

Volta is lazy: it fetches a toolchain on first use, not at pin time. In CI that means the first job pays the download cost. Caching $VOLTA_HOME amortizes it.

What it does

Volta stores downloaded toolchains under $VOLTA_HOME (default ~/.volta), in tools/image for the binaries and bin for the shims. Once cached, a shim resolves and runs the pinned version with no network access.

Common usage

.github/workflows/ci.yml
- uses: actions/cache@v4
  with:
    path: ~/.volta
    key: volta-${{ runner.os }}-${{ hashFiles('**/package.json') }}
- run: |
    curl https://get.volta.sh | bash
    export VOLTA_HOME="$HOME/.volta"
    export PATH="$VOLTA_HOME/bin:$PATH"
    node -v   # downloads pinned toolchain only if not cached

Options

ItemWhat it does
VOLTA_HOMERoot of the install and toolchain cache
$VOLTA_HOME/binShim directory that must come first on PATH
$VOLTA_HOME/tools/imageCached node/npm/yarn binaries
volta fetch <tool>@<v>Pre-download a toolchain without running it
VOLTA_LOGLEVEL=debugVerbose output for diagnosing fetches

In CI

Put $VOLTA_HOME/bin ahead of any system Node on PATH or the system binary shadows the shims. Key the cache on package.json so a pin change invalidates it. volta fetch in a setup step warms the cache deterministically instead of relying on lazy first-use download.

Common errors in CI

"Volta error: Could not download node@..." is a transient network/registry failure during lazy fetch; retry or pre-fetch. "permission denied" writing to $VOLTA_HOME on a restored cache means the cache was saved with different ownership; restore under the same user or chown. If the wrong Node runs, the system Node is earlier on PATH than $VOLTA_HOME/bin.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →