skip to content

What happens if you set org.gradle.daemon.idletimeout to 0 (or a very small value)? Is that the same as disabling the daemon?

level: seniorimportance: nice to knowfreq 22%

answer

  1. 0 ≠ disabled
  2. daemon still forks, then exits immediately
  3. loses warm reuse, keeps overhead
  4. disable = no fork at all
  5. use a sane non-zero value instead

basics

~20 s

Setting idletimeout to 0 (or tiny) means the daemon shuts down almost as soon as it goes idle — so you lose warm reuse between builds. It is NOT the same as disabling the daemon: a daemon still forks, runs your build, then exits.

solid answer

~40 s

`idletimeout=0` doesn't mean "no daemon" — it means "shut down the instant you become idle." A daemon process still forks, runs the build inside that JVM, and then, finding itself immediately idle, exits. So you keep all the daemon *machinery* (an extra fork, daemon protocol) but throw away the *benefit* (warm-JVM reuse across builds), because the next build can't find a live daemon and must cold-start a new one. That's strictly worse than disabling: disabling (`org.gradle.daemon=false` / `--no-daemon`) runs the build in the foreground JVM with no fork at all. So tiny idletimeout = pay daemon overhead, get no reuse; `--no-daemon` = no daemon overhead, no reuse. If your goal is "don't keep warm JVMs around," disabling is the cleaner tool than `idletimeout=0`.

code

toml · 3 lines
toml
# Misleading: this does NOT disable the daemon
org.gradle.daemon.idletimeout=0   # daemon forks, runs, then exits instantly -> no reuse
# To actually skip the daemon, that's a different knob (org.gradle.daemon=false)

go deeper

for a junior

Know that 0 makes the daemon exit right after each build and is not the same as turning it off.

for a middle

Explain that you still pay fork/cold-start overhead with 0, losing reuse.

for a senior

Contrast idletimeout=0 vs --no-daemon precisely and recommend the right tool for the intent.

for a principal

Steer teams away from the 0 footgun in shared config and codify when to disable vs set a sane timeout.

## The misconception People reach for `idletimeout=0` thinking it disables the daemon. It does not. `idletimeout` only controls **how long an idle daemon waits before shutting itself down** — zero just makes that wait essentially nothing. ## What actually happens with a tiny/zero value 1. A build runs → Gradle still **forks a daemon** (or reuses one if, improbably, a compatible live one exists). 2. The build executes inside that daemon JVM. 3. The build finishes → the daemon is now **idle** → with a ~0 timeout it **shuts down almost immediately**. 4. The **next** build finds no live daemon → it **cold-starts a fresh one** (JVM boot, class loading, JIT warm-up). Net effect: you pay the daemon's fork + protocol overhead **and** the cold-start cost every build — the worst of both worlds for throughput. You keep none of the warm-reuse benefit the daemon exists to provide. ## Compared with disabling the daemon | Approach | Daemon process? | Warm reuse? | Overhead | |---|---|---|---| | `idletimeout=0` | Yes, then exits immediately | No | Fork + protocol + cold start | | Disable (`--no-daemon`) | No (runs in foreground JVM) | No | No daemon fork at all | So if the *intent* is "don't leave warm JVMs lying around," **disabling** is the right tool (that knob lives in a sibling topic). A near-zero `idletimeout` is almost never what you actually want — it's a footgun that adds overhead without giving you the cleanliness of true disabling. ## Legitimate small values A *small-but-nonzero* timeout (e.g. a minute or two) is reasonable on memory-tight machines where you still want reuse for back-to-back builds but quick cleanup afterward. The pathological case is `0` (or single-digit-ms), which destroys reuse entirely. ```properties # Footgun — do NOT do this expecting 'no daemon': org.gradle.daemon.idletimeout=0 # Reasonable instead, if memory is tight but you still want some reuse: org.gradle.daemon.idletimeout=120000 ``` ## Takeaway idletimeout tunes *idle lifespan*, not *existence*. To eliminate the daemon, disable it; to tune memory-vs-reuse, pick a sane non-zero window.

  • If both idletimeout=0 and --no-daemon avoid keeping warm daemons, which is better for that goal and why?
    --no-daemon, because it skips forking a daemon entirely and runs in the foreground JVM, whereas idletimeout=0 still pays the daemon fork/protocol cost only to exit immediately.
  • Is there any legitimate use for a small idletimeout?
    Yes — a non-zero value like 1–2 minutes on a memory-constrained machine keeps reuse for rapid back-to-back builds while reclaiming memory soon after a quiet period.

saying these in an interview costs you the question

  • Asserting idletimeout=0 disables the daemon.
  • Claiming idletimeout=0 is the most efficient setting (it's the least efficient for reuse).
  • Confusing idle lifespan with whether a daemon exists at all.

context