skip to content

When would you choose the --profile report over a Build Scan, and what are its limitations?

level: seniorimportance: should knowfreq 35%

answer

  1. offline / no plugin / no account
  2. wall-clock + single build
  3. no cache-miss causality
  4. Scan = shareable, timeline, cache analysis, history
  5. profile first, scan for depth

basics

~20 s

Use --profile when you need a quick, offline, no-setup measurement — e.g. air-gapped CI or no Gradle account. It's coarser than a Build Scan: wall-clock phase breakdown only, single build, no per-task cache-hit insights or sharing.

solid answer

~50 s

Choose `--profile` when constraints rule out a Build Scan: **no network/account** (air-gapped or policy-restricted environments), **zero setup** (no plugin to add), and you just want a phase-level breakdown you can attach to a ticket. Its limitations are real: it's **wall-clock and single-build**, so it shows where time went on one run but not *why* a task missed the cache, no comparison across builds, no shareable URL, and far less detail than a Scan's timeline, dependency insights, and cache-performance views. A **Build Scan** adds a hosted, link-shareable report with per-task timelines, deprecation warnings, dependency resolution detail, and cache-hit analysis — at the cost of a plugin and (usually) publishing data to Develocity or scans.gradle.com. Practical rule: reach for `--profile` first for a fast offline triage; graduate to Build Scans (and Develocity) when you need depth, history, or team-wide sharing.

go deeper

for a junior

Know --profile is offline and zero-setup; a Build Scan is richer but needs a plugin/network.

for a middle

List concrete limitations (wall-clock, single build, no cache causality) and what a Scan adds.

for a senior

Give a decision rule and tie tool choice to environment constraints and the question being answered.

for a principal

Weigh org-level investment: --profile as the floor for restricted contexts vs Develocity/Build Scans for fleet-wide observability, cost, and data-governance trade-offs.

## Two tools, different trade-offs Gradle gives you two built-in-ish ways to see where build time goes. They overlap but are not interchangeable. ### `--profile` (offline HTML report) - **Setup:** none — it's a core flag. - **Where it lives:** `build/reports/profile/profile-<timestamp>.html`, a self-contained file. - **Network:** none. Nothing leaves the machine. - **Granularity:** wall-clock split into Configuration / Dependency Resolution / Task Execution, tasks slowest-first with outcomes. - **Scope:** one build, no cross-run comparison baked in (you eyeball multiple files). ### Build Scan - **Setup:** the Develocity/build-scan plugin (and `--scan` or auto-publish config). - **Where it lives:** a hosted page (scans.gradle.com or your Develocity), shared by URL. - **Network:** publishes build data to the service. - **Granularity:** rich — per-task timeline, dependency resolution insights, deprecation/warnings, performance breakdown, and **cache-hit analysis** (why tasks were/weren't FROM-CACHE), plus comparison and history with Develocity. ## Decision guide ``` Need offline / no account / no plugin / quick triage? -> --profile Need shareable URL, per-task timeline, cache-miss reasons, cross-build history, team dashboards? -> Build Scan / Develocity ``` ## Limitations of --profile to call out 1. **Wall-clock only** — a slow task could be CPU-bound, I/O-bound, or waiting on a lock; the report won't distinguish. 2. **No causality for cache** — it shows `EXECUTED` vs `FROM-CACHE`, but not *why* a task wasn't cached. For that you need `--info`, `-Dorg.gradle.caching.debug=true`, or a Scan. 3. **Single build, manual comparison** — no built-in baseline/diff. 4. **No sharing/history** — it's a local file; tracking trends over time is on you. The pragmatic answer in interviews: `--profile` is the right *first* instrument — cheap, offline, leaves an artifact — and you escalate to Build Scans when you need to understand *why*, share findings, or watch trends.

  • Why can't the profile report tell you why a task missed the cache?
    It only records durations and outcomes (EXECUTED/FROM-CACHE), not input/key comparisons; cache-miss reasoning needs --info, caching debug logging, or a Build Scan.
  • Name an environment where --profile is preferable to a Build Scan.
    An air-gapped or policy-restricted CI/network where publishing build data externally isn't allowed and adding the scan plugin is undesirable.

saying these in an interview costs you the question

  • Saying --profile shows per-task cache-hit reasons — it doesn't
  • Claiming Build Scans are always free/offline
  • Treating the two as identical with different output formats

context