Full rebuild on every change

A full rebuild recompiles every source file and re-runs every build step from scratch on each invocation, regardless of what changed.

L1 · ASSISTEDWhat this level takes
MUSTNot met, not at this level
  • A build system is in place (default configuration is fine)
  • Builds run on each change
SHOULDExpected in practice, not required
  • Build completes (even if slowly)
  • CI runs builds on a shared queue (even if everyone waits)
EVIDENCEHow you would check
  • Build configuration file with default/untuned settings
  • CI logs showing full rebuild on every PR

What It Is

A full rebuild recompiles every source file and re-runs every build step from scratch on each invocation, regardless of what changed. This happens when build caching is disabled, when the build tool cannot determine what has changed, or when developers habitually run mvn clean install or gradle clean build to guarantee a "fresh" result. The clean step deletes all previously compiled outputs, forcing the entire compilation to start over.

For a developer making 5-10 commits per day, full rebuilds are an annoyance but not a crisis. A 3-minute build means 15-30 minutes of waiting per day - painful but manageable. For an AI agent running 20-40 build cycles per hour to iterate on a bug fix, a 3-minute full rebuild means the agent spends 60-120 minutes waiting for builds in a single hour. The agent is doing almost nothing productive.

The full rebuild problem is compounded by how agents work. An agent fixing a compilation error will make a change, trigger a build, read the output, make another change, and trigger another build. This tight loop is exactly the pattern that exposes full rebuild costs. The agent is not doing expensive reasoning between builds - it's waiting. Every minute of build time is a minute of pure latency in the agent's iteration loop, with no useful work happening.

The root cause is usually a combination of factors: no build cache configured, clean tasks called out of habit, non-deterministic build inputs that force cache invalidation, or monolithic build structures where a change to one file triggers recompilation of thousands of unrelated files because the dependency graph isn't properly expressed.

Why It Matters

  • Agent iteration loops multiply build costs - a single human build 5x per day versus an agent building 30x per hour makes full rebuild costs 36x more expensive per agent session
  • Full rebuilds block parallelism - multiple agents doing full rebuilds simultaneously compete for CPU, disk I/O, and shared cache directories, making each rebuild even slower
  • The problem is invisible until agents arrive - teams rarely measure build time carefully until agents make the cost undeniable; by then the habit of running clean is deeply embedded
  • Clean builds hide flakiness - running clean on every build papers over incremental compilation bugs, making it harder to discover and fix them; fixing those bugs is what enables reliable incremental builds
  • Feedback loop quality degrades - an agent that gets build feedback every 3 minutes versus every 15 seconds will produce qualitatively different results; the tight loop enables a different kind of iteration

Getting Started

  1. Stop using clean by default - Audit your CI configuration and developer documentation. Remove clean from the default build command unless it's explicitly needed (e.g., before a release build). Train developers that clean is for debugging, not normal workflow.
  2. Identify what's forcing full rebuilds - Run ./gradlew build --info and look for "Task X is not up-to-date" messages. Each message tells you why that task couldn't be cached. Common causes: undeclared task inputs, files modified during the build, non-deterministic code generation.
  3. Fix non-deterministic inputs - Build tasks that read timestamps, environment variables, or generate non-deterministic outputs cannot be cached. Identify these tasks and make them deterministic: use fixed timestamps in generated code, exclude volatile environment variables from task inputs.
  4. Enable incremental compilation at the compiler level - For Java: configure the maven-compiler-plugin or Gradle's JavaCompile task with incremental compilation. For TypeScript: use tsc --incremental. For Rust: structure your workspace so that unrelated crates don't trigger each other's recompilation.
  5. Measure incremental vs. clean build ratio - After removing clean and enabling incremental compilation, compare clean build time vs. incremental build time for a one-line change. The ratio should be at least 10:1. If it's less, there are still undeclared dependencies forcing unnecessary recompilation.
  6. Validate in agent context - Set up a test where an agent makes 10 sequential single-file changes in a module. Measure total build time across all 10 iterations. With full rebuilds, this should be 10x the clean build time. With proper incremental builds, it should be 1-2x.
TIP

The fastest way to find tasks that can't be cached is ./gradlew build --build-cache followed by ./gradlew build --build-cache a second time immediately after. Any task that runs in the second build despite no changes has an undeclared input or a caching configuration problem.

Common Pitfalls

Running clean out of habit. Many developers were taught to always run clean install or clean build to avoid "stale artifact" problems. This habit made sense before reliable incremental compilation; it's actively harmful now. Document explicitly that clean should only be used when debugging suspected stale-state issues, never as a normal build step.

Monolithic module structure that forces broad recompilation. A project with one large module where all source files are compiled together means any change to any file can trigger recompilation of all files. Splitting into smaller modules with explicit dependency declarations enables the build system to skip modules that don't depend on what changed. This structural change is necessary for incremental builds to be effective.

Treating incremental compilation as inherently unreliable. Some teams run clean because they've been burned by incorrect incremental compilation outputs. Rather than accepting this, fix the root cause: find which tasks have undeclared inputs, declare them, and then incremental compilation becomes reliable. The work to fix undeclared inputs is a one-time investment that pays off indefinitely.

Not distinguishing local from CI builds. Even if local builds are incremental, CI often runs full clean builds because CI runners start from a fresh checkout with no prior build artifacts. This is correct for release builds but unnecessary for PR validation. CI should use a remote build cache so that the first build on a new runner can still reuse cached task outputs from previous builds.

Ignoring the file-watching alternative. For agent workflows, a build system in watch mode (gradle --continuous, jest --watch, cargo watch) eliminates the explicit rebuild invocation entirely. The build system detects file changes and immediately reruns only the affected tasks. This approach is more efficient than even optimized incremental builds for tight agent iteration loops.

How Different Roles See It

BobHEAD OF ENGINEERING

Bob's team is complaining that AI-assisted development is slower than expected. Agents seem to spend a lot of time waiting. His developers are using agents for iterative debugging - make a change, test it, adjust - exactly the workflow that full rebuilds hurt most. Bob doesn't have visibility into where the time is going.

What Bob should do: Bob should ask his infrastructure team to generate a "build time per agent session" report. If CI logs tag agent-triggered builds (which they should at L2+), this data is already available. The report will show that a large fraction of agent session time is build wait time. Bob should then approve a one-sprint build optimization effort: remove clean from default CI commands, enable incremental compilation for the main modules agents work in, and set a target of sub-90-second incremental builds. This investment has a direct, measurable return on agent productivity that Bob can report upward.

SarahPRODUCTIVITY LEAD

Sarah has been running agent productivity workshops and notices a consistent pattern: developers who run agents for greenfield work report high satisfaction, but developers who use agents for iterative debugging report frustration. The difference is exactly the full rebuild problem - greenfield work involves fewer build cycles, iterative debugging involves many.

What Sarah should do: Sarah should add "agent iteration cycle time" to her DevEx metrics - the median time from agent making a change to getting build feedback. She should set a target of under 60 seconds and identify the current baseline. For most teams with default build configs, the baseline will be 2-5 minutes. Sarah should then drive the removal of clean from agent-facing build commands as a quick win, followed by a structured incremental compilation enablement project. She should communicate the before/after metrics to the team to reinforce that build performance is a first-class productivity investment.

VictorSTAFF ENGINEER - AI CHAMPION

Victor has already eliminated clean from his local builds and set up incremental compilation. But he's hitting a different problem: when he runs 4 parallel agents in git worktrees, each agent is doing independent builds that don't share any compiled outputs, even for code that didn't change between the worktrees.

What Victor should do: Victor should set up a remote build cache that all worktrees share. With a shared remote cache, when agent 1 compiles module A and agent 2 needs to compile the same module A at the same commit, agent 2 gets a cache hit instead of recompiling. This is the configuration that transforms parallel agents from "4x the build cost" to "1x the build cost for shared modules, incremental cost only for changed modules." Victor should measure the cache hit rate across worktrees and target 80%+ hit rates for shared infrastructure modules.

Where does your team actually sit on this?

This guide describes one level of one area. Run the assessment to place your team across all 16 areas, see which gates you have passed, and get a report you can take to your stakeholders.

Start the assessment