Skip to content
Latchkey

How to Cache DerivedData in GitHub Actions

Pin DerivedData to a known path and cache it so Xcode can reuse module and object files instead of compiling everything from scratch.

Set -derivedDataPath to a stable directory and cache it with actions/cache. Key it on a hash of your sources or lockfiles so the cache invalidates when inputs change.

Steps

  • Build with a fixed -derivedDataPath DerivedData.
  • Cache that directory keyed on source/lockfile hashes plus the Xcode version.
  • Accept that a partial hit still saves time via incremental compilation.

Workflow

.github/workflows/ci.yml
steps:
  - uses: actions/checkout@v4
  - uses: actions/cache@v4
    with:
      path: DerivedData
      key: dd-${{ runner.os }}-${{ hashFiles('**/*.swift', 'Package.resolved') }}
      restore-keys: dd-${{ runner.os }}-
  - run: |
      xcodebuild build \
        -scheme MyApp \
        -destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
        -derivedDataPath DerivedData

Gotchas

  • DerivedData is tied to the toolchain; include the Xcode version in the key or a version bump yields stale-module errors.
  • A huge DerivedData cache can be slower to restore than to rebuild; cache only when builds are genuinely long. Latchkey managed runners add a faster shared cache and auto-retry transient failures.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →