Pages
- Posts, newest first, and the feed that follows them
- Gemtext, and the seven line types this site is built from
- How this page works, and why the markers are not really there
- Persistence, a note on P3 amber phosphor
- Impressum, Datenschutz, and how to reach me
Why cache invalidation is hard
A cache is a copy of an answer. That is the whole of its value and the whole of its problem: the copy is faster than the thing it came from, and it has no way of knowing when the original stopped being true. Nothing about holding a value tells you that the value has moved on.
So invalidation is never really a question about the cache. It is a question about everything the cached answer was derived from, and about which of those inputs can change without anyone announcing it — which is knowledge that lives outside the cache, in the shape of the system, and often enough only in somebody's head. You cannot write the rule until you can name every dependency, and naming every dependency is the part nobody finishes.
Both ways of getting it wrong are unpleasant, and they are not symmetrical. Invalidate too eagerly and there is no cache left: you have paid for all of the machinery and kept none of the speed. That failure is at least visible, and it shows up on a graph as work you are doing twice. Invalidate too late and you serve a wrong answer — quickly, confidently, and with nothing to suggest that anything is the matter. A stale cache does not crash. It lies, and it lies in exactly the voice it used when it was right.
That asymmetry is most of the reputation.
There are only two hard things in computer science: cache invalidation and naming things.
Usually attributed to Phil Karlton, and difficult to source with any confidence — which is a small instance of the problem, a claim cached and passed along without its provenance. It reads as a joke about scope. It is also two descriptions of one complaint: in both halves the hard part is not the mechanism, it is knowing what a thing actually depends on.
Why it is a good name for a personal blog
Because writing things down is caching.
A post is a copy of what I understood at the time, kept because reading it back is faster than working it out again. It has every property the caches above have. It was correct when it was written. It is quicker than the thinking that produced it. And it has no idea that anything has changed since.
What it does not have is an invalidation strategy. Nothing tells you which of your old opinions went stale, because the dependencies were never recorded — a post does not note what you believed about the rest of the field on the day you wrote it, so there is no way to notice when one of those beliefs stopped holding. The archive quietly fills up with confident wrong answers, in your own voice, indexed and searchable and dated in a way that makes them look deliberate.
Which is the joke, and also an argument for writing more rather than less. A cache you can read is a cache you can correct.
There is a smaller version of the same problem directly underneath this page. The generator that built it caches every page it renders, and it refuses to consult a clock to decide what is stale: a timestamp records when a file was last touched, not whether what it says is still true, and a fresh checkout rewrites every timestamp in the tree without changing a byte of content. So it hashes the inputs instead, and writes the dependencies down. That works exactly as well as the writing down is honest, which is the only guarantee any of this ever offers.