A Badge That Was Missing From Exactly One Shelf
Cleaned articles carry a small badge — a mark meaning this one has been pre-processed and will open instantly. It appeared everywhere except the personalized shelf. Not intermittently; never. And on that same shelf, the payload was enormous: a five-row window shipping over nine thousand characters of article body the client had no use for.
One cause, two symptoms. Every other shelf built its rows through a shared shaping helper — the function that decides which columns leave the database, derives the booleans the client needs, and drops the heavy text fields. The personalized shelf did not. It selected the article rows directly and returned them.
Two Failure Directions From One Omission
This is what makes the bug worth a lesson rather than a footnote. Skipping the shaping helper failed in both directions at once, and the two look nothing alike.
Things that should have been added were missing: the badge's boolean is derived from a timestamp column, and nothing derived it. Things that should have been removed were present: the full extracted body is stored on the row and every other path strips it. A reviewer looking for the missing badge would find the derivation and add it — and never notice the payload, because a payload being too big produces no error anywhere. It is slower, and slower is not a symptom anyone reports.
Name the Door
The fix is not "remember to call the helper." It is to make the helper the only way rows can leave, and to name it so that its absence is legible in review. A function called _rows reads like an implementation detail and invites a caller to write their own; the same function called card_rows — the door article rows leave through — makes a hand-rolled query next to it look like what it is.
The general shape: when a payload has invariants, those invariants belong to a single serialization boundary, not to each endpoint's good intentions. Endpoints choose which rows; the door decides what a row looks like.
Test the Property, Not the Endpoint
This survived a large test suite because every test asserted the behavior of one shelf. Each shelf had tests; the personalized one had tests too, and they passed, because they checked that it returned the right articles in the right order — which it did. Nobody had written the test that says every endpoint returning article rows returns them in the card shape. That test is one loop over the routes, and it would have caught this on the day it was introduced.