Infrastructure worth keeping — and kept patched.

Build cache eviction: how the size limit works

A self-hosted build cache cannot grow forever. FosterStack Cache has a size cap, and when it is reached it removes the entries used least recently. This page shows exactly what that looks like, from a real 0.2.1 server with a deliberately tiny cap.

Setting the cap

Set FSCACHE_MAX_BYTES, in bytes. The default, 0, means no limit. Real servers use gigabytes; see server sizing for values you can copy. For this test I used 3500 bytes, so that a few small entries fill it:

FSCACHE_MAX_BYTES=3500 ./fscache

What happened

I stored three 1,000-byte entries, read one of them, then stored two more. After each step I looked at /statusz, the status page, and tried to read every key back.

StepStored afterwardsEvicted so farWhich keys could be read
Store k1, k2, k33,000 bytes, 3 entries0all three
Read k1unchanged0k1 is now the most recently used
Store k4 (would go over 3,500)3,000 bytes, 3 entries1k1, k3, k4. k2 is gone.
Store k53,000 bytes, 3 entries2k3, k4, k5. k1 is gone.

The stored size never went above the cap. Each time something new did not fit, the entry that had gone longest without being used was removed.

Reading counts as using. In the last step k1 went too, even though I had read it earlier. That is because my own checks after storing k4 read k1, k3 and k4 in that order, which made k1 the oldest again. A cache hit keeps an entry alive.

An entry bigger than the whole cap

I also tried storing 4,000 bytes against the 3,500 cap. The server refused it with a 413 and stored nothing, and nothing else was evicted to make room. The other limit, FSCACHE_MAX_BODY_BYTES, is separate and defaults to 1 GiB per entry. See the status codes page.

Watching it on a real cache

The same numbers are in /statusz as store_bytes, max_bytes, store_entries and evicted_entries, and in the Prometheus metrics (fscache_evicted_entries_total and fscache_store_bytes). A rising eviction count together with a hit rate that never climbs means the cap is too small for your build. See monitoring.

Try it yourself

FSCACHE_ADDR=127.0.0.1:8080 FSCACHE_DATA_DIR=./data FSCACHE_MAX_BYTES=3500 ./fscache &
until curl -s localhost:8080/healthz >/dev/null; do sleep 0.2; done   # wait until it is up

put() { head -c 1000 /dev/zero | curl -s -o /dev/null -w "PUT $1 %{http_code}\n" -X PUT --data-binary @- localhost:8080/$1; }
get() { curl -s -o /dev/null -w "$1=%{http_code} " localhost:8080/$1; }
put k1; put k2; put k3
get k1; echo
put k4
for k in k1 k2 k3 k4; do get $k; done; echo
curl -s localhost:8080/statusz | grep -E 'store_bytes|evicted'

# the output of the middle line in my run:
# k1=200 k2=404 k3=200 k4=200

Related: how to clear a build cache and Gradle and Maven setup.

Server sizing FosterStack home