self-host →

Magic Cache for GitHub Actions

How to enable RunsOn Magic Cache for actions/cache and language setup actions — unlimited, S3-backed caching with no per-step changes.

The Magic Cache accelerates actions/cache and every language-specific cache action (actions/setup-node, ruby/setup-ruby, …) by swapping their storage backend to a fast, unlimited S3 bucket in your VPC — with no changes to your cache steps.

See how the Magic Cache works for the request path; this page is the practical how-to for GitHub Actions caches.

Usage

Flex

Enable the S3-backed cache sidecar from the job label, then keep using the normal GitHub cache action:

jobs:
build:
runs-on: runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/extras=s3-cache
steps:
- uses: runs-on/action@v2
- uses: actions/cache@v5
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}

Fleet

For Fleet, publish runners with Magic Cache enabled from Terraform:

runners = {
linux-cache = {
cpu = 4
ram = 8
family = ["c8i"]
image = "ubuntu24-full-x64"
extras = ["s3-cache"]
}
}

Workflow jobs can then keep using actions/cache on that runner fleet.

How to use

Using the Magic Cache is simple:

  1. Set an additional job label: extras=s3-cache.
  2. Add the runs-on/action@v2 action to your job.
  3. Use the normal caching actions as before.

Note that when running on official GitHub Actions runners, the runs-on/action@v2 action is a no-op, so it’s fine to keep in your workflows even if you mix official and RunsOn runners.

It also transparently accelerates the type=gha Buildx exporter when building Docker images — see Caching for Docker.

Accelerate actions/cache

As an example, the workflow below compares the speed of the Magic Cache vs official runners for multiple cache sizes by generating a random file, saving it to the cache, and then restoring it. It uses the official actions/cache action, but it should also work with any language-specific caching action (e.g. actions/setup-node, ruby/setup-ruby, etc.).

jobs:
test-magic-cache-speeds:
strategy:
fail-fast: false
matrix:
runner:
- runs-on=${{github.run_id}}/runner=2cpu-linux-x64/extras=s3-cache
- ubuntu-latest
blocks:
- 4096 # 4GB
- 2048 # 2GB
- 512 # 512MB
- 64 # 64MB
runs-on: ${{ matrix.runner }}
env:
FILENAME: random-file
steps:
- uses: runs-on/action@v2
- name: Generate file
run: |
echo "Generating ${{ matrix.blocks }}MiB random file..."
dd if=/dev/urandom of=${{ env.FILENAME }} bs=1M count=${{ matrix.blocks }}
ls -lh ${{ env.FILENAME }}
- name: Save to cache (actions/cache)
uses: actions/cache/save@v4
with:
path: ${{ env.FILENAME }}
key: github-${{github.run_id}}-actions-cache-${{strategy.job-index}}-${{ matrix.blocks }}MiB-${{ env.FILENAME }}
- name: Restore from cache (actions/cache)
uses: actions/cache/restore@v4
with:
path: ${{ env.FILENAME }}
key: github-${{github.run_id}}-actions-cache-${{strategy.job-index}}-${{ matrix.blocks }}MiB-${{ env.FILENAME }}
- name: Restore from cache (actions/cache, restoreKeys)
uses: actions/cache/restore@v4
with:
path: ${{ env.FILENAME }}
key: github-${{github.run_id}}-actions-cache-${{strategy.job-index}}-unknown
restore-keys: |
github-${{github.run_id}}-actions-cache-${{strategy.job-index}}-${{ matrix.blocks }}MiB-

FAQ

Availability

The Magic Cache is available on all RunsOn runners, including Windows runners.

Speed

Speed depends on file size and instance type, but the larger the files and the larger the instance type, the faster (up to 5x compared to official runners) it is for saving and restoring.

Size

The cache is UNLIMITED; items are evicted based on the cache eviction policy defined in your RunsOn stack (default: 10 days).

Cost

The cache mechanism is free, and the bandwidth (ingress/egress) is also free, since everything stays within your VPC, and the VPC has a (free) S3 gateway attached. You only pay for S3 storage.

Limitations

  • Currently, the EC2 instance role assigned to the runners has full access to the entire cache bucket, so make sure you are fine with the lack of isolation across repositories handled by RunsOn. While this might be a desirable feature for certain use cases, future versions will restrict cache access to only the current repository.
  • The Magic Cache is opt-in only, and you need to add the runs-on/action@v2 action to your jobs.

Common issues

actions/upload-artifact compatibility

If you have enabled the s3-cache extra and you are using actions/upload-artifact@v4, you must also include the runs-on/action@v2 action in your jobs. Otherwise you might see an error like:

Attempt 1 of 5 failed with error: Unexpected token 'O', "Original A"... is not valid JSON. Retrying request in 3000 ms...

Alternate: the runs-on/cache action

The runs-on/cache action is a more general way to send caches to an S3 bucket — it works with or without RunsOn, including from GitHub-hosted or other providers’ runners. It’s a drop-in replacement for actions/cache that changes only the storage backend (300–500 MB/s throughput, no 10 GB limit, automatic fallback to GitHub’s cache when run outside RunsOn).

See the runs-on/cache repository for setup (configuring AWS credentials, pointing at your bucket, and the unset-current-credentials option when credentials from a previous step take precedence).