thefullstackciso.com
Security, shipped
Vol. I — No. 7Falls Church, Va.Thursday, July 16, 2026Price: free, always

The Full Stack CISOIncidentPage A1June 27, 2026
Incident

The free-tier trap: the cache that almost DoS'd my own app

I added a cache to save money. It nearly took the app down, and the alert looked like an attack. A postmortem on reading the fine print.

We spent a weekend making a free, public app cheaper to run, and by Monday it was briefly unusable. Not because of an attacker. Because of me, an incremental cache, and a free-tier limit I never read to the end of.

This is the postmortem I wish someone had published before I shipped it.

The setup

The app is a nonprofit audio library: roughly fifteen hundred pages, all public, all cacheable. Rendering each page hit the database, so the obvious win was an incremental cache in front. The platform offered a key-value store on a generous free tier, and “generous” is exactly the word that got me.

I wired the cache to write a rendered entry on every miss. Deploy, smoke test, walk away.

A free tier is a budget, not a guarantee. The numbers are the spec.

The incident

A search crawler discovered the sitemap that night and walked all fifteen hundred pages in a few minutes. Every one was a cache miss. Every miss was a write.

The key-value store’s free tier allows one thousand writes per day. The crawl blew through that before it finished the letter B. Writes started failing, the render path treated a failed cache write as a hard error, and pages began returning fives. The platform’s “daily limit exceeded” email landed in my inbox at 2 a.m. and read, for all the world, like the first sign of an attack.

It was not an attack. It was arithmetic.

What actually went wrong

Three mistakes stacked:

1. wrong backend  — KV is built for read-heavy, write-rare config,
                    not for caching a 1,500-page catalog.
2. wrong failure  — a failed cache WRITE should never fail the READ.
3. wrong mental model — "free" read as "unlimited," never as "1,000/day."

The fix was not a bigger plan. It was moving the cache to object storage, whose free tier measures writes in the millions per month, and making the write fire-and-forget so a throttled cache can never again take down a page it was supposed to speed up.

The lesson worth the outage

The failure that scared me was not the outage. It was how convincingly a self-inflicted cost problem impersonated a security event. If I had reflexively started blocking traffic, I would have been fighting my own crawler.

Read the limit before you optimize against it. And when a cache fails, it should get quieter, never louder.

letters to the editor

Loading the letters…

sign in with your email · your CertScore shows on your letter