Documentation

Search Composal documentation

Search public documentation, commands, and release notes.

Browse documentation

CI

Caching

Configure dependency archives, inspect restores, and measure whether caches save work.

On this page

Use caches alongside selection

Selection and caching save different work. Selection avoids scheduling unrelated workflows. Dependency archives and compiler caches reduce setup or compilation inside workflows that do run. A cache hit supplies reusable files or compilation outputs; it does not prove that tests passed.

Configure a dependency archive

Place actions/cache@v4 before the steps that consume its cached paths. Composal restores those paths when the cache step runs, including on a fresh system runner. An exact match reports cache-hit=true. A restore-keys prefix match restores files but reports cache-hit=false, so the job can update dependencies and save its new exact key after success. Keep the install or rebuild path valid for misses and partial matches. Self-hosted runners need CLI 1.17.16 or later for this step-boundary restore behavior.

For dependency caches with long filenames (including Cargo registry packages and pnpm content hashes), use CLI 1.17.17 or later on self-hosted runners. This version preserves complete paths and uses a new archive format version. Your first run after upgrading starts cold and fills the new cache automatically; no workflow key change is required.

Keep cache keys sensitive to the inputs that affect their contents, such as dependency lockfiles, toolchain versions, operating system, and architecture. Let the workflow install or rebuild on a miss. A cold cache must still produce a correct result.

Understand archive scopes

Each candidate saves into its own archive scope. Composal tries that scope's exact key and then your restore-keys prefixes first. For organizations enabled for published-target archive reuse, a miss can then restore a matching archive produced by successful checks behind a confirmed native queue publication. The source must be in the validated target's JJ history, in the same organization and repository. Passing review CI or matching a branch name is insufficient. Singleton and grouped queue publications can provide archive sources; writers remain isolated.

An exact published-target match still reports cache-hit=true; a prefix match reports cache-hit=false. Selected tests continue running. Composal checks current queue policy, the active runner lease, target state, archive size and checksum before returning these bytes. Disabled reuse, expired or invalid evidence, unavailable history or storage, and changed targets produce a normal miss.

Keep archives small

Keep individual dependency archives small. Published-target fallback accepts archives up to 128 MiB and uses bounded recent history and nonblocking read capacity. Split large monorepo caches by component, dependency family and toolchain instead of caching an entire build tree. Use compiler caching for reusable compilation outputs. Larger archives can still use their original candidate scope; a cache in another scope is never guaranteed to restore. This archive feature is separate from workflow selection and from queue-to-trunk test-result reuse.

For example, give Cargo registry metadata (.cargo-home/registry/index and .cargo-home/git/db) a separate cache step and key prefix from crate downloads (.cargo-home/registry/cache). Keep the dependency installation step after both caches so either family can miss independently. Measure each family after lockfile changes; splitting an archive does not guarantee it will remain below the limit.

Archives are optional and expire after 30 days without a restore. A missing archive or temporary storage outage is a cache miss: keep the install or rebuild step working independently of the cache. Only a completed upload becomes eligible for restore.

Inspect cache responses

Open a job’s details and look for Cache archive responses to see exact or prefix archive responses, published-target responses, misses, bytes prepared, archive preparation time, and the source run when available. This history records what the server prepared; use the cache step log to confirm the runner restored the files. It does not mean the job’s tests were reused. Older jobs without observations show no history.

The history keeps up to 32 responses within a 48 KiB budget and reports how many further responses were omitted. Cache keys and archive contents are excluded. Source links can become unavailable when their run history is removed.

Measure whether caching helps

Measure cache restore time, install/compile time, and test time separately. Compare a run without cache actions, a cold run that populates the cache, and a fresh runner with a populated cache. Use the same lockfile, toolchain and install command. Include archive transfer and extraction before installation, and cache uploads after the job, in your cost comparison. Confirm the restored files are usable; a hit counter alone is not enough.

A large archive can cost more to restore than it saves, especially when the package registry already serves downloads quickly. Keep a cache family only when repeated measurements show a benefit. If direct dependency downloads are faster, omit that archive step and keep compiler caching where it helps. This also avoids creating and uploading dependency archives after each cold run. Compiler hits may leave test execution as the dominant cost. There is no cross-candidate passing-test cache enabled by this feature: selected tests still execute even when their dependencies restore successfully.

Next: measure CI performance. To reuse passing tests after landing, see queue-to-trunk result reuse.