skip to content

How does the local build cache control its size over time, and what are the trade-offs when tuning retention?

level: middleimportance: should knowfreq 35%

answer

  1. last-read time, not last-write
  2. removeUnusedEntriesAfterDays default 7
  3. cleanup periodic, not exact
  4. no hard byte cap
  5. hit-rate vs disk trade-off

basics

~10 s

Gradle periodically cleans the local cache, removing entries not read within removeUnusedEntriesAfterDays (default 7). A longer window keeps more cache hits but uses more disk; a shorter window saves disk but loses older entries.

solid answer

~40 s

The local cache grows as each cacheable task writes a new archive. To bound it, Gradle runs **cache cleanup** periodically and evicts entries whose **last-read** time is older than `removeUnusedEntriesAfterDays` (default 7). Crucially it's last-*access*, not last-*write*, so frequently reused entries stay alive while stale ones age out. Tuning is a hit-rate vs. disk trade-off: - **Longer retention** keeps more historical outputs, so older branches/commits still hit — better hit rate, more disk consumed. - **Shorter retention** caps disk but evicts entries you might still want, costing re-execution. Cleanup is opportunistic (tied to Gradle User Home maintenance), so the directory may temporarily exceed expectations between passes. There's no fixed size cap; you bound it indirectly through the day window and by choosing the `directory` location (e.g. a disk you can size or wipe).

code

kotlin · 6 lines
kotlin
buildCache {
    local {
        // keep entries that were READ within the last 30 days
        removeUnusedEntriesAfterDays = 30
    }
}

go deeper

for a junior

Know that old, unused entries get cleaned up after a number of days (default 7).

for a middle

Explain last-access-based eviction, the default 7-day window, and that cleanup is periodic, not exact.

for a senior

Discuss the hit-rate/disk trade-off, the lack of a byte cap, and relocating directory to manage disk.

for a principal

Define org policy: retention per environment (long on dev, ephemeral on CI), pairing local with a persistent remote cache for governance.

## Why eviction exists Every cacheable task that runs with a new cache key writes a fresh archive into the local cache directory. Without cleanup the directory would grow without bound across months of branch-switching and dependency bumps. So Gradle ages entries out. ## The retention mechanism The knob is `removeUnusedEntriesAfterDays` in the `local { }` block (default `7`). The word *unused* is the key: Gradle tracks each entry's **last access (read)** time and considers an entry removable once that time is older than the configured window. An entry that keeps getting hit on every build is continually 'touched' and survives indefinitely; an entry for an output you no longer build ages out. ```kotlin buildCache { local { removeUnusedEntriesAfterDays = 30 // keep a month of history } } ``` ## When cleanup actually runs Cleanup is **not** a precise timer. Gradle performs cache cleanup periodically as part of Gradle User Home maintenance (historically about once a day, and influenced by the broader Gradle User Home cleanup settings). Practically: - Don't expect a file to vanish the instant it crosses the N-day line. - The directory can temporarily be larger than the retention window would suggest. ## The trade-off | Retention | Hit rate | Disk | |-----------|----------|------| | Longer | Higher (older keys still present) | More | | Shorter | Lower (older keys evicted) | Less | There is **no hard byte-size cap** on the local cache — you tune size *indirectly* via the day window and by choosing where `directory` points (a partition you can size, mount on fast storage, or wipe wholesale). ## Practical guidance - Dev machines with plenty of disk: a longer window (e.g. 14–30 days) maximizes hits across branches. - Constrained CI agents: shorter windows, or treat the cache as ephemeral and rely on a remote cache for persistence. - If disk pressure is acute, relocate `directory` to a partition you control rather than fighting the day window.

  • Does Gradle evict based on when an entry was written or when it was last read?
    Last read/accessed. Frequently reused entries keep getting touched and survive; only entries not read within the window age out.
  • Is there a maximum size you can set on the local cache?
    There's no hard byte-size cap. You bound size indirectly via `removeUnusedEntriesAfterDays` and by choosing the `directory` location.
  • Why might the directory be bigger than the retention window implies?
    Cleanup runs periodically (not as an exact timer), so eligible entries linger until the next cleanup pass.

saying these in an interview costs you the question

  • Saying eviction is by last-write time — it's last-read.
  • Claiming there's a size-based LRU cap by default — retention is time/access based.
  • Expecting deletion exactly at the day boundary.

context