Skip to content
LatchkeyLatchkey home

Dependency Caching Strategies for Faster CI

The biggest, cheapest CI speedup is not re-downloading the same dependencies on every run. Cache the package store, key it on the lockfile, and most installs become near-instant.

Dependency installation dominates many CI jobs. A good caching strategy restores the package store from a previous run so the installer only fetches what actually changed - turning minutes into seconds.

Cache the store, not the project

Prefer caching the package manager’s global store or download cache (npm cache, ~/.m2, pip wheel cache, Cargo registry) over a project directory like node_modules. The store is portable and lets the installer do a fast, validated install rather than blindly trusting copied files.

Key on the lockfile

The cache key should change exactly when dependencies change - a hash of the lockfile (package-lock.json, poetry.lock, Cargo.lock). Same lockfile → same cache → full hit. Changed lockfile → new cache entry, and a restore-key fallback recovers most of the previous store.

Lockfile-keyed cache
key: deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
  deps-${{ runner.os }}-

Common pitfalls

  • Keying on a value that always changes → 0% hit rate.
  • Caching node_modules directly, hiding lockfile drift.
  • Not including the OS/arch in the key → restoring incompatible binaries.
  • Caching faster than you invalidate, serving stale transitive deps.

Measure the payoff

Compare install time on a cache hit vs a cold run; if they are similar, the cache is not hitting. A healthy dependency cache should turn a multi-minute install into seconds, and the hit rate should be high on branches that do not touch the lockfile.

Key takeaways

  • Cache the package store/download cache, not the resolved project dir.
  • Key on a lockfile hash; use restore-keys for near-miss fallback.
  • Include OS/arch so you do not restore incompatible binaries.
  • Verify by comparing hit vs cold install time - similar means it is not hitting.

Frequently asked questions

What is Dependency caching strategies for faster CI?
Dependency installation dominates many CI jobs. A good caching strategy restores the package store from a previous run so the installer only fetches what actually changed - turning minutes into seconds.
Cache the store, not the project?
Prefer caching the package manager’s global store or download cache (npm cache, ~/.m2, pip wheel cache, Cargo registry) over a project directory like node_modules. The store is portable and lets the installer do a fast, validated install rather than blindly trusting copied files.
Key on the lockfile?
The cache key should change exactly when dependencies change - a hash of the lockfile (package-lock.json, poetry.lock, Cargo.lock). Same lockfile → same cache → full hit. Changed lockfile → new cache entry, and a restore-key fallback recovers most of the previous store.
Measure the payoff?
Compare install time on a cache hit vs a cold run; if they are similar, the cache is not hitting. A healthy dependency cache should turn a multi-minute install into seconds, and the hit rate should be high on branches that do not touch the lockfile.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card