Engineering

What we learned running our own build cache for two years

SM

Sam Mercer

17 August 2026 · 9 min read

We built the cache because the alternative cost more than an engineer. Two years on, it has paid for itself twice — and taught us three things we would rather have known on day one.

The cold start problem is a people problem

A cold cache is not slow because of the network. It is slow because nobody agrees on what a cache key should contain, so every team quietly adds one more variable until the hit rate collapses.

We fixed it by making the key a reviewed artefact: one file, one owner, and a test that fails when the key changes without a note explaining why.

A cache with a 40% hit rate is not a cache. It is a tax with extra steps.

Eviction beats capacity

For a year we answered every slowdown by adding storage. The fix was the opposite: evict aggressively, keep the index small enough to stay in memory, and accept a few extra misses on old branches.

cache.evict({ olderThan: "14d", keep: "main,release/*" })

Measure misses, not hits

Hit rate is a vanity metric — it goes up when builds repeat, which is exactly when nobody is waiting. What matters is the time a miss costs on the critical path, per branch, at the moment somebody is watching the pipeline.

Was it worth building?

For us, yes — but only because the cache is boring now. If you are still tuning yours every month, the honest answer is that you are running a small distributed systems project on the side of your actual work.

">

The prompt

Build a long-form article layout with Tailwind CSS. Pin a 2px reading-progress bar to the very top of the viewport with a dark fill that starts at zero width. Below a header block (category pill, headline, byline row with avatar, date and reading time), lay out two columns from lg up: the article itself and a sticky sidebar at top-24 holding an "On this page" label, an empty list for generated links, and a small bordered share card with three quiet buttons. The article body uses generous vertical rhythm — lead paragraph in larger grey type, h2 section headings with scroll-mt-24 and ids, body paragraphs, one pull-quote with a left border, and a code-ish callout box. Then add JavaScript that reads every h2 in the article, builds the contents list from their text, scrolls smoothly to a section when a link is clicked, highlights whichever heading is currently nearest the top of the viewport as you scroll, and updates the progress bar from how far the article has been scrolled through rather than the whole document.

Paste it into Claude, Cursor, v0 or any AI coding tool. Prefer the finished markup? .