Decision records
ADR-0024: Disk tier of the response cache
- Status: Accepted (2026-10-06)
Context
The memory cache (ADR-0012) drops entries when memory is full, cannot hold responses
above max_entry_size, and is empty after every restart.
Decision
- Optional
server.cache.disk: {path, size, max_entry_size}(default entry limit: 64 MiB orsize, whichever is smaller). When configured but unusable, the server does not start. - The disk tier receives entries evicted from memory for lack of space (moka eviction
listener, cause
Size) and entries larger than the memory entry limit; the store path buffers bodies up to the larger of the two limits. - One file per variant: magic, JSON metadata (key, status, headers, stored time as Unix
seconds, initial
Age, TTL, stale-while-revalidate,Varyvalues, tags), body. Written to a temporary file and renamed. Writes go through one writer thread with a bounded queue (256); a full queue drops the write — the request path never waits for the disk. - Lookups: memory first; on a miss the in-memory index (key → variants,
Varyvalues, expiry, size, LRU counter) selects a file, read withspawn_blocking; freshness is recomputed from wall-clock time; hits that fit are promoted to memory. - At start the directory is indexed; expired and partial files are deleted. The tier is
bounded by
size(least recently used files go first, ordered by an access counter). - Invalidation (unsafe requests) and purge (key, prefix, tag, all) apply to both tiers.
- Metrics:
scalws_cache_disk_entries,scalws_cache_disk_bytes.
Consequences
- An entry is findable on disk only after its asynchronous write; a lookup in between is a miss (acceptable for a cache).
- Cache files contain response headers and bodies; the directory must be private to the
service user (systemd
StateDirectoryor similar).