On a Build Scan, what's the difference between UP-TO-DATE, FROM-CACHE, NO-SOURCE, and SUCCESS outcomes, and how does the scan quantify the savings from avoidance?
answer
- SUCCESS = ran
- UP-TO-DATE = local incremental skip
- FROM-CACHE = cross-machine restore
- NO-SOURCE = nothing to do
- avoidance savings estimate
basics
~20 sSUCCESS = the task ran. UP-TO-DATE = incremental check passed, skipped. FROM-CACHE = outputs restored from the build cache. NO-SOURCE = no inputs to act on. The scan tallies avoided tasks and estimates the time saved.
solid answer
~50 sThese are **task outcomes** the scan shows per task and aggregates on the Performance tab: - **SUCCESS** — the task executed its actions and completed. - **UP-TO-DATE** — Gradle's up-to-date check found inputs/outputs unchanged since last run *on this machine*, so it skipped execution (incremental build avoidance). - **FROM-CACHE** — outputs were **restored** from the (local or remote) build cache because a matching cache key existed; the task body did not run. This works across machines, which UP-TO-DATE does not. - **NO-SOURCE** — the task had no input source to process (e.g. `compileJava` with an empty source set), so there was nothing to do. - **SKIPPED** — excluded or disabled. The scan quantifies **avoidance savings** by summing the durations these tasks took on the build(s) where they *did* execute, estimating how much wall-clock you saved by not re-running them. A high FROM-CACHE/UP-TO-DATE ratio on expensive tasks is the signal that caching is paying off.
code
bash · 6 lines# --console=verbose prints the outcome next to each task, mirroring the scan
./gradlew build --console=verbose
# :app:compileJava UP-TO-DATE
# :app:processResources NO-SOURCE
# :app:test FROM-CACHE
# :app:jar SUCCESSgo deeper
Recall what each outcome word means: ran, skipped-incremental, restored, nothing-to-do.
Explain the cross-machine difference between UP-TO-DATE and FROM-CACHE and read the avoidance-savings tally.
Use outcome distributions to spot missing remote-cache reuse and target avoidance at expensive tasks.
Set avoidance-rate targets on expensive tasks and govern remote-cache enablement across the org via Develocity.
## Task outcomes are how Gradle reports what it did (or didn't do) Every task in a build ends with an **outcome** that the Build Scan displays per task and rolls up in aggregate. ### The avoidance outcomes - **UP-TO-DATE** — Gradle records each task's input/output fingerprints. On the next build, if nothing changed, the task is *up-to-date* and skipped. This is **incremental build** avoidance and is **local to one machine's history** — a fresh checkout or CI agent won't benefit. - **FROM-CACHE** — the **build cache** stores task outputs keyed by an input hash. If a matching key is found (locally or in a shared remote cache), Gradle **restores** the outputs instead of running the task. Unlike UP-TO-DATE, this works **across machines and clean checkouts**, which is why remote caching speeds up CI and teammates. - **NO-SOURCE** — the task is configured but has **no input source** (e.g. an empty source directory), so it legitimately does nothing. ### The work outcomes - **SUCCESS** — actions ran to completion (real work, real time). - **FAILED** — ran and errored. - **SKIPPED** — excluded via `-x`, `onlyIf {}`, or disabled. ## How the scan quantifies savings The Performance/cache view counts tasks by outcome and reports **avoidance savings** — an estimate of the wall-clock time you *did not* spend because tasks were UP-TO-DATE or FROM-CACHE rather than executed. Gradle estimates this from the historical/typical execution time of those tasks. The headline metric to watch: **avoidance rate on expensive tasks** — caching a 0.1s task saves nothing; caching a 60s test or compile task is where ROI lives. ```text Outcome counts (Performance tab) SUCCESS 12 (executed — real time spent) FROM-CACHE 34 (restored — cross-machine avoidance) UP-TO-DATE 18 (incremental skip — local avoidance) NO-SOURCE 3 (nothing to do) Estimated avoidance savings: ~3m 40s ``` ## Why distinguishing UP-TO-DATE vs FROM-CACHE matters If clean CI builds show lots of SUCCESS where local builds show UP-TO-DATE, you're not getting cross-machine reuse — the fix is the **remote build cache** so those become FROM-CACHE on CI.
- Why does a fresh CI agent show SUCCESS where your laptop shows UP-TO-DATE for the same task?UP-TO-DATE relies on local incremental-build history the fresh agent doesn't have; without a remote build cache there's nothing to restore, so the task executes (SUCCESS).
- How do you turn those CI SUCCESS outcomes into FROM-CACHE?Enable a shared remote build cache (org.gradle.caching=true plus a remote cache node) so the agent restores outputs by cache key instead of re-running cacheable tasks.
- Is caching a 50ms task worthwhile per the avoidance-savings metric?Generally no — restore/transfer overhead can rival its runtime; focus avoidance on the expensive compile/test/packaging tasks where saved time dwarfs cache overhead.
saying these in an interview costs you the question
- Treating UP-TO-DATE and FROM-CACHE as interchangeable — only FROM-CACHE crosses machines.
- Reading NO-SOURCE as an error rather than 'nothing to process'.
- Optimizing cheap tasks for cache hits where overhead exceeds the savings.