> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revyl.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Caching

> Speed up remote builds with compilation and configured path caches

Every remote build runs in a clean, single-use VM. Revyl uses two kinds of
caching to make repeat builds faster:

| Cache | Default | Best for |
| - | - | - |
| **Compilation cache** | On | Xcode, Gradle, and native C/C++ compilation |
| **Configured path cache** | Opt-in | Dependencies, generated files, and other project state |

## Automatic compilation caching

Revyl enables the right compilation caches for each platform without changing
your build commands:

| Platform | Caches |
| - | - |
| iOS | Xcode compilation cache |
| Android | Gradle build cache and ccache for native C/C++ |

The first compatible build warms the cache. Later builds on the same toolchain
can reuse its compiler outputs across apps and branches in your organization.

The snippets below focus on cache fields. Keep the selected recipe's runnable
`app_id`, `build_commands`, and `output_path` from your build configuration.

You can turn each cache off independently:

```yaml theme={null}
build:
  framework: react_native
  profiles:
    development:
      ios:
        build_commands: ["./scripts/build-ios"]
        env:
          REVYL_XCODE_COMPILATION_CACHE_ENABLED: "0"
      android:
        build_commands: ["./scripts/build-android"]
        env:
          REVYL_GRADLE_BUILD_CACHE_ENABLED: "0"
          REVYL_CCACHE_ENABLED: "0"
```

Each setting accepts `"0"` (off) or `"1"` (on) and defaults to `"1"`.

<Note>
  Compilation caching is an optimization, not a build dependency. If it is
  unavailable, the build continues normally. It is also skipped when the build
  timeout is longer than 60 minutes.
</Note>

## Configured path caches

Declare defaults under `build.caches` and recipe-specific additions under
`build.profiles.<name>.<platform>.caches`. Each cache has a `key` and a list of
project-relative `paths` stored under it:

```yaml theme={null}
build:
  framework: react_native
  caches:
    - key: javascript-dependencies
      paths:
        - node_modules
  profiles:
    development:
      ios:
        build_commands: ["./scripts/build-ios"]
        caches:
          - key: ios-dependencies
            paths:
              - ios/Pods
      android:
        build_commands: ["./scripts/build-android"]
        caches:
          - key: android-dependencies
            paths:
              - .gradle-home
```

Paths must be project-relative and stay inside the workspace. Absolute paths
and `..` segments are rejected.

### How configured caches work

Build-level and recipe caches merge by key. For a matching key, build-level
paths come first and recipe paths are appended with duplicates removed. Each
effective key maps to one compressed archive that Revyl stores between builds:

1. After checkout, Revyl restores the latest archive directly into the clean build workspace. A new key starts empty.
2. Your commands read and write the configured paths normally, such as `node_modules`, `Pods`, or DerivedData.
3. If the build **succeeds**, Revyl archives those exact paths and saves them for the next build. Failed builds don't update caches, so a broken run can't poison them.

Compressed archives larger than 4 GiB are not saved. The build still succeeds,
and the previous saved archive remains available for later builds.

Cache keys are scoped to your organization and platform. Builds using the same
key share that archive across apps and branches. Concurrent builds work in
private VMs; the last successful upload becomes the next saved state.

## What to cache

| Work | Recommended cache |
| - | - |
| Xcode or Gradle compilation | Automatic compilation cache |
| Android native compilation | Automatic ccache |
| JavaScript dependencies | Configured path cache |
| CocoaPods | Configured path cache |
| Gradle dependency downloads | Configured path cache |
| DerivedData or generated files | Optional path cache; measure first |

Tool caches that normally live in your home directory must be redirected into
the project. For example:

```yaml theme={null}
build:
  framework: android
  profiles:
    release:
      android:
        build_commands:
          - GRADLE_USER_HOME=$PWD/.gradle-home ./gradlew assembleRelease
        caches:
          - key: android-dependencies
            paths:
              - .gradle-home
```

If you cache a build-output directory, keep `output_path` specific enough that
it cannot select a stale artifact.

## Cold builds and clearing caches

```bash theme={null}
# Bypass every cache for one build without deleting anything
revyl build --profile development --platform ios --remote --no-cache

# Inspect and delete configured caches
revyl cache list
revyl cache delete ios-dependencies
```

`revyl cache list` and `delete` manage configured caches only. Compilation
caches are managed automatically and can be bypassed with `--no-cache` or the
individual environment settings above.

## Troubleshooting

* **The second build is still slow:** make sure the first build completed successfully and compare builds using the same toolchain.
* **Dependency installation is still slow:** add its download or install directory to a configured cache.
* **A configured cache looks stale:** try `--no-cache`, then delete the cache if the cold build fixes the problem.
* **Compilation caching is missing:** check the build logs for `compilation-cache` messages and confirm the timeout is 60 minutes or less.

## Related

* [Fingerprinting](/remote-builds/fingerprinting): skip unnecessary native rebuilds for Expo and React Native apps
* [Configuration](/remote-builds/configuration): the full `build:` reference
* [Toolchain Images](/remote-builds/toolchains): what's already installed


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.