Skip to content
Using runners

Caching

Every job starts on a clean VM, so nothing is cached on the machine itself. Caches live in GitHub's Actions cache, which works the same as on GitHub-hosted runners.

Dependency caches

actions/cache and the built-in cache: inputs of the setup actions work without changes. Keys, restore keys, scopes and the 10 GB per-repository limit are GitHub's.

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-node@v4
    with:
      node-version: 22
      cache: pnpm
  - uses: actions/cache@v4
    with:
      path: ~/.cache/ms-playwright
      key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}

What is not cached

  • Files written outside a cache step. The disk is deleted with the VM.
  • Tool caches from previous runs, such as a warm ~/.cargo, unless you cache them explicitly.

This is deliberate. A cache that survives on the machine is also a way for one job to influence the next, which is what per-job isolation is there to prevent.

Tips for faster restores

  • Cache the package manager's store, not node_modules; it compresses better and restores faster.
  • Split one large cache into a few by purpose, so a lockfile change does not invalidate everything.
  • On larger machines such as runloft-ubuntu-24.04-8cpu, decompression is rarely the bottleneck; the download is.