When you run a Gradle command, how does Gradle decide whether to reuse an existing daemon or start a new one?
answer
- thin client + long-lived daemon JVM
- registry under ~/.gradle/daemon/<version>
- need IDLE and COMPATIBLE
- reuse = warm JIT + caches
- no match -> fork new daemon
basics
~10 sThe Gradle client looks for an idle, compatible daemon already running. If it finds one, it reuses it; otherwise it spawns a fresh daemon process and connects to that.
solid answer
~40 sEvery Gradle invocation is split into a thin **client** and a long-lived **daemon** JVM. The client scans the registry of daemons under `~/.gradle/daemon/<version>/` for one that is **idle** (not running another build) and **compatible** with the request. Compatibility means the daemon's JVM and startup parameters match what this build needs. If a compatible idle daemon exists, the client hands the build to it and reuses its warm JIT and caches. If none qualifies — all are busy, or their parameters differ — the client forks a brand-new daemon JVM with the required settings and connects to it. This reuse is why second builds are faster: the daemon survives between invocations.
code
bash · 4 lines# Watch discovery vs spawn
./gradlew help # first call: 'Starting a Gradle Daemon...'
./gradlew help # second call: reuses the idle daemon, no startup line
ls ~/.gradle/daemon/ # one sub-dir per Gradle version, each with a registrygo deeper
Know that Gradle reuses an idle daemon if one fits, else starts a new one, and that reuse makes builds faster.
Explain the client/daemon split, the per-version registry, and the IDLE + COMPATIBLE conditions.
Discuss why parameter changes force new daemons and how that affects CI cold-start vs local warm-build performance.
Frame daemon reuse as a fleet/resource concern: controlling JVM/identity drift to avoid daemon proliferation across a team or CI agents.
## The client / daemon split Every time you type `gradle build` or `./gradlew build`, you actually start a small **client** process. The client does almost no build work itself. Its job is to locate a **daemon** — a separate, long-running JVM that holds the warmed-up Gradle runtime, the configured project model, and caches — and hand the build off to it. The daemon stays alive after the build finishes (idle), ready for the next invocation. ## Discovery: the daemon registry Running daemons advertise themselves in a **registry** file kept per Gradle version, e.g. `~/.gradle/daemon/8.7/registry.bin`. Each entry records the daemon's address, its **PID**, its current **state** (IDLE / BUSY / etc.), and the **identity parameters** it was started with (JVM home, JVM arguments, Gradle version). On each invocation the client reads this registry. ## The decision The client tries to find a daemon that is both: - **IDLE** — not currently executing another build, and - **COMPATIBLE** — its identity parameters match what the current request requires (same Gradle version, same JVM / `JAVA_HOME`, compatible JVM args). If one matches, the client **reuses** it — this is the fast path, because that daemon already has a hot JIT, loaded classes, and populated in-memory caches. If no daemon matches (all busy, or none with the right parameters), the client **spawns** a new daemon JVM configured for the request, registers it, and connects. ```bash # First run: no compatible daemon -> Gradle forks one (slower, cold JVM) ./gradlew build # 'Starting a Gradle Daemon (subsequent builds will be faster)' # Second run: idle + compatible daemon found -> reused (fast) ./gradlew build ``` ## Why it matters Daemon reuse is the single biggest reason repeated local builds are fast. Anything that changes the daemon's identity (different `JAVA_HOME`, new JVM args) forces a *new* daemon and a cold start, so understanding the find-or-spawn rule explains both speedups and surprise slowdowns.
- What two conditions must a running daemon satisfy to be reused?It must be IDLE (not running another build) and COMPATIBLE with the request's JVM and startup parameters.
- Why is the second build usually faster than the first?The first invocation may fork a cold daemon; the second reuses an idle daemon that already has a warm JIT, loaded classes, and populated caches.
Like a taxi rank: the client (passenger) takes the first idle cab whose destination/route matches; if none fits, a new cab is dispatched.
saying these in an interview costs you the question
- Claiming each Gradle command runs entirely in the process you launched (ignoring the client/daemon split).
- Saying Gradle always starts a new daemon per build.