Skip to content
C.W.K.
Stream
Lesson 04 of 05 · published

Cache the Derivation Forever, and Compost It Without Ceremony

~11 min · caching, cost, data-modeling, derived-data

Level 0Unsorted
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

The Cache Key Is the Whole Design

A derived text — a summary, a translation, a tidied body — is expensive once and free thereafter, but only if you can recognize the request the second time. So the key has to name everything that would change the output: which article, which kind of derivation, and which target language. Miss one dimension and you either return the wrong artifact or pay again for one you already have.

Keying on the article alone is the classic mistake, and it fails in the more embarrassing direction: ask for a summary, then ask for a translation, and the second request finds a cached entry and returns the summary. A composite key costs nothing and makes the wrong answer unrepresentable.

Derive From the Processed Form, Not the Raw One

A derivation should have exactly one input, and it should be the cleaned text rather than the raw extraction. Summarizing raw output means summarizing navigation menus and cookie notices along with the article, which produces a worse result at the same price.

The consequence is a dependency worth making explicit: derivations refuse politely on an article that has not been processed yet, rather than falling back to the raw form. A cached derivation built from the wrong input is worse than no derivation, because nothing downstream can tell which input produced it.

Not Everything Needs a Model

One detail worth borrowing: deciding which language an article is in does not require a turn. Counting characters by script answers it deterministically, instantly, and for free. The rule generalizes — before spending a turn on a classification, ask whether the answer is computable. Language detection, length, whether something is a list, whether a field is empty: all of these get proposed as model tasks and none of them should be.

Composting Is Allowed, and That Is the Point

When the voice specification for derivations changed, the previously cached texts had been generated under the old one. They were deleted rather than migrated, and the next tap re-derived them.

That is only defensible because of what a derivation is: working set, reproducible from an input that still exists. Nothing was lost, because nothing there was ground truth. Being able to say "delete it, it will come back" is the property you get for keeping derived data strictly derived — and the moment a derivation acquires an edit, an annotation, or a manual correction, that property is gone and you have a migration problem forever.

Derived data earns its cache by being disposable. If you cannot delete it and let it regenerate, it is not derived any more — it is a store with an expensive constructor, and every future change to how it is produced becomes a data migration.

Code

A composite cache key, and why this table cascades where articles did not·sql
-- The key names every dimension that changes the output. Keying on
-- article_id alone returns a summary when a translation was asked for,
-- which is the wrong answer rather than merely a slow one.
CREATE TABLE article_texts (
  article_id INTEGER NOT NULL REFERENCES articles(id) ON DELETE CASCADE,
  kind       TEXT    NOT NULL,   -- 'summary' | 'translation'
  lang       TEXT    NOT NULL,   -- target language of THIS artifact
  content    TEXT    NOT NULL,
  created_at TEXT    NOT NULL,
  PRIMARY KEY (article_id, kind, lang)
);

-- CASCADE is correct HERE, and SET NULL was correct on articles.source_id.
-- The difference is what the row means: a derivation of a deleted
-- article is meaningless, while an article whose source was deleted is
-- still an article. Cascade follows meaning, not habit.

External links

Exercise

Find a cache of expensive results in your system and write down every input that affects the output. Compare that list to the cache key. If anything is missing, construct the two requests that collide and check what the second one returns. Then ask the disposability question: could you delete the whole table today and let it refill?
Hint
The dimensions that go missing from a key are usually the ones added later — a new variant, a new language, a new model. The key was written when there was only one, so it did not need to name it, and the second variant arrives without anyone revisiting the primary key.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.