skip to content

What does org.gradle.caching enable, and how is the build cache different from the up-to-date (incremental) check?

level: middleimportance: must knowfreq 68%

answer

  1. caching = reuse outputs by hash key
  2. up-to-date = same dir, survives only until clean
  3. cache survives clean / crosses machines
  4. @CacheableTask opt-in
  5. --build-cache / --no-build-cache

basics

~20 s

org.gradle.caching=true turns on the build cache, so Gradle can reuse task outputs by a hash key instead of re-running tasks — even across clean builds or different machines via a remote cache. The CLI flag is --build-cache.

solid answer

~40 s

`org.gradle.caching=true` enables the **build cache**: for each cacheable task, Gradle computes a hash key from its inputs (input files, properties, classpath, task implementation) and, on a hit, restores the task's outputs from the cache instead of executing it. This differs from the **up-to-date check** (incremental build), which only avoids re-running a task whose outputs already exist *in the same build directory* and whose inputs are unchanged. The build cache works even after `clean`, and a **remote cache** lets CI agents and developers share results. Only tasks marked `@CacheableTask` (with correctly declared inputs/outputs and path-sensitivity) participate. Enable persistently in `gradle.properties`, or per build with `--build-cache` / `--no-build-cache`.

code

properties · 1 line
properties
org.gradle.caching=true

go deeper

for a junior

Know caching=true reuses task outputs and that --build-cache is the CLI form.

for a middle

Distinguish build cache from up-to-date check; explain cache keys and @CacheableTask; know clean still allows cache hits.

for a senior

Discuss local vs remote cache, relocatability, path sensitivity, and CI push/read gating.

for a principal

Design org cache infrastructure: shared remote cache, hit-rate monitoring, governance on which tasks are cacheable, and correctness guarantees.

## Up-to-date check vs build cache Gradle has two layers of avoidance: 1. **Up-to-date / incremental** (always on): before running a task, Gradle compares the task's declared inputs and outputs against the previous run *in the same project directory*. If nothing changed and outputs still exist, the task is `UP-TO-DATE` and skipped. Running `clean` destroys outputs, so the next build re-executes. 2. **Build cache** (`org.gradle.caching=true`): Gradle computes a **cache key** — a hash of the task's inputs (file contents, input properties, the task's own implementation classpath) — and looks up a stored copy of the **outputs**. A hit restores outputs without executing, *even after clean* and *even on a machine that never ran the task* (via a shared remote cache). ## Cache key inputs The key includes input file contents (with path sensitivity controlling whether file paths matter), input properties, the task class and its classpath, and output property names. Any change flips the key, so correctness depends on tasks declaring all inputs/outputs accurately. ## Cacheable tasks A task only participates if it is annotated `@CacheableTask` (most built-in compile/test/jar tasks are). The annotation is a promise that the task's inputs are fully declared and its outputs are relocatable. Custom tasks must opt in deliberately. ## Local vs remote cache - **Local cache** lives under the Gradle user home and speeds up repeated builds on one machine. - **Remote cache** (configured in `settings.gradle(.kts)` via `buildCache { remote(...) }`) is shared, typically populated by CI and read by everyone — the biggest win for teams. ```kotlin // settings.gradle.kts buildCache { local { isEnabled = true } remote<HttpBuildCache> { url = uri("https://cache.example.com/cache/") isPush = System.getenv("CI") != null // only CI writes } } ``` ## Enabling - Persistent: `org.gradle.caching=true` in `gradle.properties`. - Per build: `--build-cache` to enable, `--no-build-cache` to disable. ## Pitfalls Non-relocatable outputs (absolute paths baked into files) or under-declared inputs cause cache misses or, worse, stale results. Path-sensitivity annotations (`@PathSensitive`) on inputs are how you tell Gradle which path differences matter.

  • Why does a build cache hit work after running clean, but an up-to-date check does not?
    Clean deletes the output files, so the up-to-date check sees missing outputs and re-runs. The build cache stores outputs separately keyed by an input hash, so it can restore them regardless of the build directory state.
  • What makes a custom task eligible for the build cache?
    Annotating it @CacheableTask, with all inputs/outputs declared and appropriate @PathSensitive annotations so outputs are relocatable and the key is correct.
  • Where do you configure a remote cache and who should push to it?
    In settings.gradle(.kts) under buildCache { remote(...) }. Typically only CI pushes (isPush gated on CI) while developers read, to avoid polluting the shared cache.

saying these in an interview costs you the question

  • Conflating the build cache with the incremental up-to-date check.
  • Assuming every task is cacheable by default — only @CacheableTask ones are.
  • Letting every developer push to the remote cache, risking poisoned entries.

context