skip to content

At the HTTP level, how does Gradle interact with a remote HttpBuildCache server when reading and storing entries?

level: middleimportance: should knowfreq 35%

answer

  1. key = hash of inputs appended to url
  2. GET = read (200 hit / 404 miss)
  3. PUT = write when push=true
  4. body = gzip tar of outputs + origin metadata
  5. I/O best-effort, never fails the build

basics

~20 s

Gradle appends the cache key to the configured URL. It does a GET to fetch an entry (200 = hit, 404 = miss) and a PUT to store one when push is enabled. The body is the packed task-output archive.

solid answer

~50 s

The HttpBuildCache protocol is intentionally simple, REST-like. Each entry has a key (a hex hash of the task's inputs). Gradle forms the entry URL by appending the key to the base `url` (hence the required trailing slash). To **read**, it issues a `GET url + key`: `200 OK` means a hit and the body is the cached artifact; `404 Not Found` means a miss and Gradle runs the task. To **write** (when `push = true`), it issues a `PUT url + key` with the packed output archive as the body. The artifact body is a gzip-compressed tar of the task's declared outputs plus origin metadata. Because servers are dumb blob stores, expiry/eviction is the server's responsibility, not Gradle's. Read and write failures are non-fatal — Gradle logs and falls back to executing the task locally.

code

bash · 6 lines
bash
# A cache hit fetch, conceptually:
curl -i https://cache.example.com/cache/3f9a...e21   # 200 -> body is gzip tar of outputs

# A store (what Gradle does on push):
curl -X PUT --data-binary @entry.tgz \
     https://cache.example.com/cache/3f9a...e21      # 200/201 stored

go deeper

for a junior

Know it's GET to read and PUT to store, keyed by a hash.

for a middle

Explain 200/404 semantics, the packed-archive body, and best-effort failure handling.

for a senior

Discuss why the protocol is server-agnostic and how local/remote entry formats interoperate.

for a principal

Evaluate server choices (blob store vs Develocity), eviction strategy, and resilience guarantees for the org.

## A deliberately simple protocol The HTTP build cache is essentially a **content-addressed key/value blob store over HTTP**. Gradle never needs server-side logic; any server that can store and serve bytes by URL works (a plain reverse proxy in front of a directory, an S3-backed gateway, the official build-cache-node, or Develocity). ## Keys and URLs A cache **key** is a hex string: the hash Gradle computes from all of a cacheable task's inputs (source files, classpath, task implementation, relevant properties). Gradle forms the per-entry URL by string-appending the key to the configured base `url`. This is exactly why the base URL **must end in `/`** — `https://host/cache/` + `abc123` → `https://host/cache/abc123`. ## Read path (GET) ``` GET /cache/abc123 -> 200 OK (hit: body is the artifact) GET /cache/abc123 -> 404 (miss: Gradle executes the task) ``` On a hit, Gradle unpacks the body into the task's output locations and marks the task `FROM-CACHE`. ## Write path (PUT) When `push = true` and the task ran (a miss), Gradle packs the outputs and issues: ``` PUT /cache/abc123 (body = packed output archive) ``` ## The artifact format The body is a **tar archive, gzip-compressed**, containing the task's declared output files/dirs and a small `origin` metadata file (build id, task path, original duration). The format is identical to the local cache's entries, which is why local and remote caches interoperate. ## Failure semantics Cache I/O is **best-effort**. A failed GET (network error, 5xx) just means a miss → run the task. A failed PUT is logged and ignored. The build does **not** fail because the cache server is down — caching is an optimization, never a correctness dependency. You'll see warnings in `--info` logs. ## Why this matters in interviews Understanding GET/PUT semantics explains observed behavior: 404s are normal (cold cache), a 401 on PUT but 200 on GET means anonymous reads + authenticated writes, and a flaky server slows but never breaks builds.

  • What HTTP status indicates a cache miss, and what does Gradle do then?
    404 Not Found means a miss; Gradle executes the task normally, and if push is enabled and successful, PUTs the resulting outputs back.
  • If the cache server is unreachable mid-build, does the build fail?
    No. Cache I/O is best-effort: a failed GET is treated as a miss and a failed PUT is logged and ignored, so the build still completes by running tasks locally.
  • What's inside the artifact body stored for an entry?
    A gzip-compressed tar of the task's declared outputs plus an origin metadata file (build id, task path, original execution time). It's the same format as local cache entries.

saying these in an interview costs you the question

  • Claiming a cache server outage breaks the build.
  • Thinking the server needs Gradle-specific logic rather than being a dumb blob store.
  • Forgetting the trailing slash is what makes key-appended URLs valid.

context