Skip to main content

Slashing CI Times With Smart Caching in GitHub Actions

1 min read

The setup

A TypeScript monorepo with 5 packages, using pnpm workspaces. Every push ran pnpm install (2 min) and pnpm build (8 min) from scratch.

The cache strategy

- name: Cache pnpm store
  uses: actions/cache@v4
  with:
    path: ~/.pnpm-store
    key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
    restore-keys: pnpm-

- name: Cache build output
  uses: actions/cache@v4
  with:
    path: packages/*/dist
    key: build-${{ github.sha }}
    restore-keys: build-

The results

StepBeforeAfter
Install2m 12s8s
Build8m 30s1m 05s
Lint+Test1m 30s1m 30s
Total12m 12s2m 43s

What I learned

The restore-keys fallback is the most important part. If the lockfile changes, you don’t want a full cache miss — you want a partial restore. The difference between 12 minutes and 2 minutes is the difference between “I’ll check back later” and “I’ll wait for green.”