BlogCI/CD

Speed up GitHub Actions with dependency caching

Cache node_modules, pip wheels, and Go modules keyed on your lockfile hash, and warm the cache on main to cut minutes off every GitHub Actions run.

May 12, 2026·4 min readBeginner·By the SecOpsLog team · command-tested

Every push that runs npm ci from a cold cache is paying for the same download twice — once in wall-clock time, once in billed minutes. GitHub Actions caching stores directories like ~/.npm, pip wheels, or Go module caches keyed on your lockfile hash and restores them on the next run. A one-line cache: npm on setup-node often cuts dependency install from minutes to seconds without changing what your pipeline actually installs.

You will key caches on lockfiles (not commit SHA alone), use restore-keys for partial hits, prefer caching download dirs over node_modules, and understand why a cache written on a feature branch can be restored by pull request jobs. The same discipline applies in GitLab cache keys — patterns covered in Software supply chain security alongside scanning and signing gates.

How a warm dependency cache shortens a job

The cache key decides reuse. Change the lockfile and you get a miss — which is exactly what you want when dependencies actually changed.

1Pushworkflow triggers2Restore cachehash lockfile key3Hit or missrestore-keys fallback4Real installnpm ci from cache dir5Test + buildsame as cold run6Save cachepost-job upload7Next push12s not 1m48s

Key the cache on your lockfile

The actions/cache key should change when dependencies change and stay stable when only application code changes. Hash package-lock.json, poetry.lock, or go.sum — not the entire repo. Add restore-keys with a prefix so a near-miss still restores most of the tree while the exact key repopulates on save.

.github/workflows/ci.yml
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-

The setup actions already do this

For Node, Python, Go, and Rust the official setup-* actions can restore and save caches automatically when you pass cache: npm (or pip, go, cargo). You still run a real install step — postinstall scripts and platform-specific binaries stay correct because you are not blindly copying a whole node_modules directory from another runner.

.github/workflows/ci.yml
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
bash — cold vs warm on the same workflowlive
first run (cache miss):
npm ci ............ 1m48s
second run (cache hit):
npm ci ............ 12s
grep hashFiles .github/workflows/ci.yml
key changes only when package-lock.json changes

Warm main so feature branches start fast

A brand-new branch always misses until someone pushes a lockfile change on that branch. Run a scheduled workflow on main that restores and saves caches so the first PR from a fork or feature branch gets a restore-keys partial hit instead of a full cold download. Keep cache paths scoped to dependency stores — never cache build outputs you treat as trusted artifacts.

What to cache
Cache these
~/.npm, pip cache, go/pkg/mod
Keyed on lockfile hash
Download dirs, not node_modules
Warm on main on schedule
Do not cache these
Secrets or .env files
Compiled binaries you deploy
Docker layer tarballs blindly
Whole repo keyed on SHA only
Caches are scoped and untrusted
A cache written on a branch can be restored by PR jobs from that branch. Treat restored contents as untrusted input — never cache credentials, signed artifacts you skip re-verifying, or directories another job could poison. Masking in logs does not make cache blobs safe.

Where this goes next

Faster installs free minutes for the gates that matter: SAST, secret scanning, SBOM generation, and Cosign signing. Wire those into the same workflow template and pin action SHAs so speed never trades away supply-chain hygiene. Software supply chain security walks from commit to admitted artifact — caching is the efficiency layer that keeps those gates affordable at scale.

Go deeper in a courseSoftware supply chain securityPipeline efficiency, scanning, SBOMs, signing, and org-wide secure defaults.View course

Related posts