skip to content

On a memory-constrained or shared CI agent, how would you tune the daemon idle timeout, and what trade-off are you making?

level: middleimportance: should knowfreq 40%

answer

  1. short idletimeout frees heap fast
  2. per-JVM-arg daemon multiplication
  3. footprint vs cold-start latency
  4. user-level gradle.properties = machine-wide
  5. verify with --status

basics

~10 s

Lower org.gradle.daemon.idletimeout (e.g. to 1–5 minutes) so idle daemons exit fast and release their heap. The trade-off: more cold starts, so slightly slower first builds.

solid answer

~40 s

On a shared or low-RAM machine, idle daemons each hold a sizeable heap, and Gradle keeps a *separate* daemon per distinct JVM-arg/JDK combo — so several fat idle JVMs can pile up. I'd set a short `org.gradle.daemon.idletimeout` (say `120000`–`300000`, 2–5 minutes) in the **user-level** `~/.gradle/gradle.properties` so it applies to every project on the agent. The trade-off is warm-reuse versus footprint: a short timeout reclaims memory promptly but means more builds pay JVM/JIT cold-start cost. For ephemeral CI containers the cleanest answer is often to disable the daemon entirely rather than tune the timeout — but on a *persistent* shared agent, a short idletimeout is the right knob. I'd verify the effect with `gradle --status` to see daemons aging out.

code

toml · 2 lines
toml
# ~/.gradle/gradle.properties (applies to all projects on this agent)
org.gradle.daemon.idletimeout=180000   # 3 min: reclaim idle-daemon heap quickly

go deeper

for a junior

Know lowering the timeout frees memory sooner at the cost of slower first builds.

for a middle

Pick a concrete value, place it in user-level gradle.properties, and articulate footprint-vs-latency.

for a senior

Reason about per-JVM-arg daemon multiplication and when disabling beats tuning on ephemeral agents.

for a principal

Standardize the build-environment baseline across agents and choose policy (timeout vs disable) per agent lifecycle class.

## The problem on shared / constrained machines Each warm daemon holds a JVM heap that can be hundreds of MB. Two things make this worse: 1. **Daemon multiplication.** Gradle starts a distinct daemon for each unique combination of JDK + JVM args. A machine building several projects with different `org.gradle.jvmargs` or JDKs accumulates multiple idle daemons. 2. **A 3-hour default.** By default each of those sits warm for three hours, so memory isn't reclaimed for a long time. ## The fix: shorten the idle window ```properties # ~/.gradle/gradle.properties on the shared agent org.gradle.daemon.idletimeout=180000 # 3 minutes ``` Putting it in the **user-level** file (`~/.gradle/gradle.properties`) makes it machine-wide, so every project's daemon respects it without editing each repo. ## The trade-off - **Short timeout →** fast memory reclaim, but more cold starts (JVM boot + class load + JIT warm-up), so the *first* build after an idle gap is slower. - **Long timeout →** maximal warm reuse and fast incremental builds, but memory is tied up longer. You're balancing **footprint vs. latency**. ## CI nuance (kept inside this topic's scope) For a *persistent* shared agent that runs back-to-back builds, a short idletimeout is the right lever — warm reuse within a session, quick cleanup after. For a *throwaway* container that's destroyed after one build, the daemon never gets reused anyway, so disabling it outright is usually preferred over tuning the timeout (the disabling knob itself is a sibling topic). ## Verifying Run `gradle --status` to list live daemons and their state; watch idle ones disappear after your shortened window to confirm the setting took effect.

  • Why might multiple idle daemons exist even though you only build one project at a time?
    Gradle keeps a separate daemon per unique JDK + JVM-args combination. Switching JDK versions or jvmargs between builds, or building several projects, spawns additional daemons that each idle independently.
  • Why is a short idletimeout not always the right CI answer?
    On an ephemeral container destroyed after one build, the daemon is never reused, so the warm-JVM benefit is moot; disabling the daemon entirely is cleaner than tuning the timeout there.

saying these in an interview costs you the question

  • Recommending idletimeout=0 thinking it means 'no daemon' (it just means shut down immediately when idle).
  • Forgetting that many idle daemons can coexist due to per-JVM-arg multiplication.
  • Ignoring that a short timeout costs cold-start latency.

context