skip to content

Walk me through reading a Build Scan: what do the timeline, performance, and dependencies pages tell you?

level: middleimportance: must knowfreq 48%

answer

  1. Timeline = per-task duration + outcome badge
  2. sort by duration, filter by outcome
  3. Performance = time split by phase
  4. Dependencies = requested vs resolved version
  5. why a version was upgraded/forced

basics

~20 s

The Timeline lists every task with its duration and outcome (executed, up-to-date, from-cache). The Performance page breaks total build time into phases. The Dependencies page shows the resolved dependency graph so you can spot conflicts and where versions came from.

solid answer

~40 s

A scan is a set of pages you read top-down to find slowness. The **Timeline** is the core view: a sortable list of every task with its wall-clock duration and outcome badge — `EXECUTED`, `UP-TO-DATE`, `FROM-CACHE`, `SKIPPED`, `NO-SOURCE`. Sort by duration to find the longest tasks; the outcomes tell you whether incremental/caching is working. The **Performance** page summarizes total build time split across phases (startup, settings/configuration, dependency resolution, task execution) plus environment and `--scan` settings, so you can tell a *configuration*-bound build from an *execution*-bound one. The **Dependencies** page renders the fully resolved graph: declared vs. resolved versions, where a version was forced or upgraded by conflict resolution, and which configuration pulled an artifact in — invaluable for diagnosing a surprise transitive dependency. Together they answer "what was slow" and "what got resolved."

code

bash · 5 lines
bash
# Produce a scan, then open the printed URL and read the pages
./gradlew assemble --scan
# Timeline:    which :module:task took longest, and its outcome
# Performance: configuration time vs execution time vs resolution
# Dependencies: requested -> resolved versions and conflict winners

go deeper

for a junior

Know the Timeline lists tasks with durations and that scans live behind a URL.

for a middle

Explain the three core pages and read outcome badges and requested-vs-resolved versions correctly.

for a senior

Use the phase split to classify a build as configuration- vs execution-bound and trace transitive dependencies via the graph.

for a principal

Standardize a triage workflow across teams and correlate scan data over time (via Develocity) to spot regressions.

## How to read a scan, page by page A Build Scan is organized into navigable pages in the left rail. You normally triage in this order. ### Timeline The **Timeline** is the workhorse. It lists **every task** in the build with: - **Duration** — wall-clock time the task took. - **Outcome badge** — `EXECUTED` (ran), `UP-TO-DATE` (inputs unchanged, skipped), `FROM-CACHE` (output pulled from the build cache), `SKIPPED`, `NO-SOURCE` (no inputs), `FAILED`. - **Path** — the fully qualified `:module:taskName`. You can **sort by duration** to find the longest pole, **filter by outcome** (e.g. show only `EXECUTED` to see what actually did work), and filter by project. A healthy incremental build shows mostly `UP-TO-DATE`/`FROM-CACHE`; lots of unexpected `EXECUTED` tasks points at broken incrementality or cache misses. ### Performance The **Performance** page attributes the **total build time to phases**: - **Startup / initialization** — JVM and daemon warm-up. - **Settings & buildSrc** — evaluating `settings.gradle`, building `buildSrc`/included builds. - **Configuration** — running every project's build script (the *configuration phase*). - **Dependency resolution** — resolving configurations (often shown here and on its own tab). - **Task execution** — actually doing work. This split is the single most useful diagnostic: a build dominated by **configuration** time needs configuration avoidance / config-cache work, while one dominated by **execution** needs caching/parallelism/task optimization. (Note: deep *configuration-vs-execution* analysis and cache-insight drill-down are their own topics; here you just learn to locate and read these tabs.) ### Dependencies The **Dependencies** page shows the **resolved dependency graph** per configuration. For each module you see the **requested** version, the **resolved** (actual) version, and *why* they differ — e.g. `5.3.1 -> 5.3.27` because conflict resolution chose the higher version, or `(forced)`/`(constraint)` annotations. You can search for a coordinate to see every path that brings it in, which is how you track down a surprise transitive dependency or a version you didn't expect. ### Other useful pages - **Console log** — the full captured output, including deprecation warnings. - **Switches / Infrastructure** — the exact flags, JVM args, Gradle/JDK versions, and OS, so you can reproduce. - **Plugins** — every applied plugin and version. ## Why a scan beats the local log The data is **structured and uniform**, so the same questions are answered the same way on every machine — making it trivial to share a URL and compare two builds instead of diffing console text.

  • On the Timeline, what does a `FROM-CACHE` outcome mean and why is it good?
    The task's output was reused from the build cache instead of being executed, because its inputs matched a prior run. It means caching is working and saving wall-clock time.
  • How does the Dependencies page help when you see `1.5.0 -> 2.1.0`?
    It shows Gradle's conflict resolution upgraded the requested `1.5.0` to `2.1.0` (the highest version demanded across the graph). You can expand to find which dependency requested the higher version.
  • If the Performance page shows configuration time dominating, what direction does that point you?
    Toward configuration avoidance — task configuration avoidance APIs and the configuration cache — rather than execution-time fixes like caching or parallelism.

saying these in an interview costs you the question

  • Saying the Timeline only shows tasks that ran — it shows all tasks including UP-TO-DATE/FROM-CACHE, which is the point.
  • Reading the Dependencies page as 'declared versions' only; its value is showing the *resolved* graph and why versions changed.

context