skip to content

Continuous Build and File Watching

Continuous build with --continuous, which re-runs tasks whenever their declared inputs change, backed by file-system watching. Interviewers ask because it only works for tasks whose inputs are declared correctly.

on this pageshow

questions

5

What is Gradle's continuous build (-t/--continuous), and how does it differ from running a task once?

level: juniorimportance: must knowfreq 55%

answer

  1. -t / --continuous
  2. Waiting for changes to input files
  3. watches declared task INPUTS only
  4. Ctrl-D to exit
  5. re-runs same task graph

basics

~10 s

Continuous build runs gradle -t <task> (or --continuous). Gradle stays alive, watches the task inputs, and automatically re-runs the requested tasks whenever a relevant input file changes, instead of exiting after one run.

solid answer

~40 s

Continuous build is enabled with `-t` or `--continuous`. Instead of executing the requested tasks once and exiting, Gradle keeps running, monitors the files declared as **inputs** of the executed task graph, and re-triggers the same build whenever one of those inputs changes. It is ideal for tight feedback loops — e.g. `gradle -t test` re-runs tests on every source edit. Only changes to files that are actual declared task inputs cause a rebuild; unrelated files are ignored. Between runs Gradle prints "Waiting for changes to input files..." and you exit with Ctrl-D (or Ctrl-C). It relies on file-system watching to detect changes efficiently, and pairs naturally with incremental tasks and the build cache so each re-run does minimal work.

code

bash · 5 lines
bash
# Re-run tests automatically on every source change
gradle -t test

# Equivalent long form
gradle --continuous test

go deeper

for a junior

Know the flag (-t/--continuous), that Gradle stays alive and re-runs on input changes, and how to exit.

for a middle

Explain that only declared task inputs trigger a rebuild and tie that to correct @Input.../inputs declarations.

for a senior

Discuss pairing with incremental tasks, the daemon, and the build cache for fast iteration, and continuous build's limits with long-running tasks.

for a principal

Frame it within team feedback-loop strategy vs. external watchers/CI, and the implications of input-correctness on whether continuous mode is trustworthy.

## What continuous build is Normally `gradle build` executes the requested task graph **once** and the JVM process exits. **Continuous build** — `gradle -t <tasks>` or the long form `gradle --continuous <tasks>` — changes that: after the first execution Gradle does **not** exit. It prints `Waiting for changes to input files...` and parks, watching the files that fed the build. When a watched file changes, Gradle re-executes the **same** task graph automatically. You stop it with Ctrl-D (graceful) or Ctrl-C. ## Why only *inputs* trigger a rebuild Every task declares its inputs via `@InputFile`, `@InputFiles`, `@InputDirectory`, `@Classpath`, etc. (or the runtime `inputs.file(...)` API). Continuous build computes the **union of all declared inputs** of the tasks that actually executed, and watches exactly those paths. A change to a file that is *not* a declared input of any executed task is ignored — this is why correct input declarations matter: an under-declared task will silently fail to rebuild when its real input changes. ## Typical uses ```bash gradle -t test # re-run tests on every source/test edit gradle -t :app:run # (with appropriate setup) restart on change gradle --continuous build # full build loop ``` ## Relationship to incrementality Continuous build does **not** make a single task faster — each re-run is a normal build. Its speed comes from pairing with **incremental tasks**, **up-to-date checking**, and the **build cache**: most tasks will be `UP-TO-DATE` or `FROM-CACHE`, so only the genuinely affected work re-runs. Combined with the always-on **Gradle daemon**, configuration and JVM warm-up are reused across iterations. ## Limits - It re-runs the build; it does **not** hot-reload a running application by itself. - Tasks that themselves block forever (a long-running server) hold the loop until they finish, so continuous build is most natural for finite tasks like `compileJava`, `test`, codegen. - Build-logic / `build.gradle(.kts)` changes are not reliably picked up the same way source changes are — you generally restart for build-script edits.

  • If you edit a file and the continuous build does NOT re-run, what is the most likely cause?
    That file is not a declared input of any task that executed, so Gradle is not watching it — usually an under-declared task input. Add the proper @Input.../inputs.file(...) declaration.
  • How do you exit a continuous build cleanly?
    Press Ctrl-D for a graceful shutdown (or Ctrl-C to interrupt).

saying these in an interview costs you the question

  • Saying continuous build watches the whole project tree — it watches only declared task inputs.
  • Claiming it hot-reloads a running app automatically; it re-runs the build, not the live process.

context

open as a page

In a continuous build, a teammate edits a config file consumed by a custom task but the build does not re-run. Diagnose the cause and explain how task input declarations govern continuous build triggering.

level: seniorimportance: must knowfreq 30%

basics

~20 s

Continuous build only watches files declared as task inputs. If the custom task reads the config file without declaring it via @InputFile/inputs.file(...), Gradle doesn't watch it, so editing it triggers nothing. Add the input declaration to fix it.

open as a page

What are the practical limitations of continuous build, and which kinds of tasks is it well- or poorly-suited for?

level: middleimportance: should knowfreq 26%

basics

~20 s

Continuous build re-runs the build, it does not hot-reload a running app. It suits finite tasks (compile, test, codegen) for fast feedback. It is poor for tasks that block forever (servers) and does not reliably react to build-script edits.

open as a page

How does Gradle's file-system watching (org.gradle.vfs.watch) work, and what role does it play in continuous build and normal incremental builds?

level: middleimportance: should knowfreq 38%

basics

~20 s

Gradle keeps an in-memory virtual file system (VFS) of file hashes/metadata. With org.gradle.vfs.watch=true (default), the OS notifies the daemon of changes between builds so Gradle reuses the VFS instead of re-hashing everything. Continuous build uses these notifications to detect input changes.

open as a page

How does Gradle continuous build compare with external file watchers or CI re-triggering for a team's fast-feedback loop, and when would you choose each?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

Continuous build is built into Gradle and reuses the warm daemon, VFS, and build cache for cheap re-runs locally. External watchers (entr, IDE, nodemon-style) or CI re-triggers are more flexible but pay full startup each time. Use -t for the local inner loop; use CI for shared verification.

open as a page