Magic Cache
Magic Cache swaps the GitHub Actions cache backend for a fast, unlimited S3 cache in your own VPC. Same actions/cache config, nothing leaves your account.
RunsOn Magic Cache transparently switches the GitHub Actions caching backend to a fast, unlimited S3 cache in your own VPC — so you keep using actions/cache (and language-specific cache actions) completely unchanged.
Platform availability#
| Cache backend | Linux | Windows | Flex | Fleet |
|---|---|---|---|---|
Magic Cache for actions/cache | Yes | Yes | Yes | Yes |
Docker Buildx type=gha | Yes | No | Yes | Yes |
Docker Buildx type=s3 | Yes | No | Yes | Yes |
| Ephemeral ECR registry | Yes | No | Yes | Yes |
How it works#
With the Magic Cache enabled, the RunsOn agent starts a sidecar cache backend on the runner and points the caching actions — including the gha backend for Docker Buildx — at it.
The sidecar transparently forwards every request to an S3 cache bucket in your own VPC and streams hits straight back. Same actions/cache config, nothing leaves your account, and there’s no 10 GB cap.
Because only the storage backend changes, the exact same workflow keeps working when you fall back to GitHub-hosted runners — the cache just points at GitHub’s backend instead.
If the sidecar fails to start (5s timeout), the job falls back to GitHub’s standard cache backend and emits a warning annotation — the job is not failed.
Enabling it#
The Magic Cache is opt-in. Flip it on per job (Flex) or bake it into a runner fleet (Fleet):
Flex
Per job: add the extras=s3-cache job label and the runs-on/action@v2 ↗ step. The workflow author decides.
runs-on: - runs-on=${{ github.run_id }} - runner=2cpu-linux-x64 - extras=s3-cachesteps: - uses: runs-on/action@v2Fleet
Per runner: publish cache-enabled runners from Terraform. The platform team decides.
runners = { linux-cache = { cpu = 4 family = ["c8i"] extras = ["s3-cache"] }}| Aspect | Flex | Fleet |
|---|---|---|
| Who chooses | Workflow author, per job | Platform team, in Terraform |
| Where it lives | extras=… label or .github/runs-on.yml | runners.<name>.extras in Terraform |
| Magic Cache (S3) | ✓ | ✓ |
| Docker BuildKit S3 | ✓ | ✓ |
| Ephemeral registry | ✓ | ✓ |
The detailed guides below have copy-paste examples for both models.
Retention#
S3 Lifecycle calculates expiration by adding a fixed lifecycle window (default 10 days) and rounding up to the next midnight UTC. Restoring an object does not extend that window. For Fleet and Flex, the Terraform module provisions the bucket and exposes the window:
cache_expiration_days = 10Use a longer window for slow-changing dependency caches, and a shorter one for high-churn branches or very large artifacts.
Scope and isolation#
By default, Magic Cache keeps the stack-wide access model used by earlier v3 releases. Cache isolation scopes the Magic Cache protocol, but it is not a trust boundary for untrusted job code. Run public or otherwise untrusted repositories in a separate RunsOn stack from trusted workloads.
Isolate GitHub Actions caches#
We recommend cache isolation on every stack. v3.2 adds opt-in, brokered
credentials for Magic Cache. They scope
actions/cache, language setup actions, and the Buildx type=gha backend to
the current repository, and keep GitHub’s restore rules. The scopes come from
the job’s GitHub-signed runtime token: a job reads and writes its own ref, and
can read the default branch (and, for a pull request, its base branch). So
branches and pull requests still fall back to default-branch entries.
| Deployment | Setting |
|---|---|
| Flex CloudFormation | EnableCacheIsolation: "true" |
| Flex Terraform / OpenTofu | enable_cache_isolation = true |
| Fleet Terraform / OpenTofu | enable_cache_isolation = true |
Isolation stores Magic Cache data under scoped-cache/* instead of cache/*.
Expect one cold cache per repository and branch when you enable it. That comes
from the one-time move to the new prefix, not from a change to the fallbacks
above. Existing objects keep their normal retention and expire without
migration.
Fleet capacity-backed runners also get one cold classic Magic Cache after a
v3.2 upgrade, even if isolation remains off. v3.2 corrects their old empty
repository prefix and repopulates the matching cache/v1/<owner>/<repo>/...
namespace automatically.
The separate v3.2 upgrade guide covers a safe rollout and the sticky-disk isolation that removes legacy snapshot permissions.
Detailed guides#
Other ways to cache#
The Magic Cache covers actions/cache and Docker layers. For caches tied to the runner’s disk rather than an S3 backend, see the runner capabilities: