skip to content

What is the Gradle Daemon and why does reusing a warm daemon make builds faster?

level: juniorimportance: must knowfreq 70%

answer

  1. long-lived background JVM
  2. client connects to warm daemon
  3. skips startup + classloading + JIT
  4. on by default since 3.0
  5. --no-daemon = cold every time

basics

~10 s

The daemon is a long-lived background JVM that runs your builds. Reusing a warm one skips JVM startup, class loading, and JIT warmup, so subsequent builds start much faster.

solid answer

~50 s

The Gradle Daemon is a background JVM process that stays alive between invocations. When you run `gradle`/`./gradlew`, the client connects to a compatible idle daemon instead of booting a fresh JVM. The first build pays the cold cost: JVM startup, loading Gradle's classes, and JIT compilation of hot paths. A reused daemon has already paid all of that — its classes are loaded and its code is JIT-optimized — so the second and later builds avoid that overhead and feel noticeably snappier. The daemon also keeps caches hot in memory (e.g. the in-memory model). It's enabled by default since Gradle 3.0 (`org.gradle.daemon=true`); turning it off (`--no-daemon`) forces a cold JVM every time, which is why CI sometimes runs slower per-invocation. Reuse is the whole point: keep one warm daemon and let every build land on it.

code

properties · 4 lines
properties
# gradle.properties
org.gradle.daemon=true   # default; reuse a warm JVM
# CLI override to opt out (cold JVM each run):
# ./gradlew build --no-daemon

go deeper

for a junior

Know it's a reusable background JVM and that reuse skips startup so later builds are faster; know it's on by default.

for a middle

Explain the concrete cold costs avoided (JVM start, classloading, JIT) and the client/daemon split.

for a senior

Connect reuse to JIT-optimized hot paths and warm in-memory model; reason about when reuse is and isn't achievable.

for a principal

Frame daemon reuse as a developer-productivity lever across the team; weigh local reuse vs ephemeral CI agents where reuse rarely pays off.

## What the daemon is The **Gradle Daemon** is a long-lived JVM process that does the actual work of a build. The `gradle` / `./gradlew` command you type is a thin **client**: it finds (or starts) a daemon, hands it the build request over a local socket, streams logs back, and exits. The daemon keeps running in the background after the build finishes, idle, waiting for the next request. ## Why a warm daemon is fast Starting a JVM is expensive, and Gradle itself is a large application. A **cold** build pays several one-time costs: - **JVM startup** — spinning up a fresh Java process. - **Class loading** — loading thousands of Gradle, plugin, and dependency classes. - **JIT warmup** — the JIT compiler initially interprets bytecode, then compiles hot methods to native code. Early runs are slow until the hot paths are optimized. - **In-memory caches** — Gradle keeps parts of the project model and other data in memory. A **reused** daemon has already done all of this. Its classes are loaded, its hot code is JIT-compiled to native, and its in-memory caches are populated. So the second and subsequent builds skip the cold tax and start working almost immediately. This is the single biggest reason interactive local builds feel fast after the first one. ## Enabled by default The daemon is **on by default** since Gradle 3.0. The flag is `org.gradle.daemon=true` (in `gradle.properties` or via `-Dorg.gradle.daemon=true`). You can disable it per-invocation with `--no-daemon`, which forces a fresh cold JVM each time and throws away all the warmup benefit. ```properties # gradle.properties — daemon on (default) org.gradle.daemon=true ``` ## The mental model Think of the daemon as a server you keep running: the first request warms it up, every later request rides on that warmth. The goal of daemon tuning for speed is simply **maximize reuse** — keep one compatible daemon alive and make sure every invocation lands on it rather than spawning a new cold one.

  • Why is the very first build after starting a daemon slower than the next ones?
    The first build pays JVM startup, class loading, and JIT warmup. Those are one-time costs the warm daemon has already absorbed, so later builds skip them.
  • Does the daemon survive after a build finishes?
    Yes — it stays alive idle in the background (default idle timeout 3 hours) so the next invocation can reuse it instead of starting cold.

Like a chef who keeps the oven preheated between dishes: the first dish waits for the oven to warm up; every dish after slides straight in.

saying these in an interview costs you the question

  • Saying the daemon caches your build outputs — that's the build cache; the daemon caches JVM warmth and in-memory model, not task outputs.
  • Claiming the daemon must be enabled manually — it's on by default since Gradle 3.0.

context