Archives
All the articles I've archived.
Your LLM can't hallucinate a number it was never given
3 min readPreventing invented facts in the code that builds the prompt rather than in its instructions: no raw numbers, no empty fields, and opaque references instead of names.
Cache the prompt, not the inputs
2 min readAn LLM cache keyed on a hand-picked list of inputs fell behind the prompt it protected. Hashing the rendered prompt fixed it, and the choice of hash turned out to be a security decision.
Fire-and-forget doesn't survive on Cloudflare Workers
3 min readA view counter returned 204 on every call and never moved. Workers can cancel work still pending after the response unless it is passed to waitUntil.
What a non-extractable key actually protects
4 min readKeeping a signing key in the browser under a WebCrypto key that cannot be exported: what that stops, what it does not, and where the real protection comes from.
We moved our page cache to R2, then deleted it
4 min readR2 charges 12.5 times more for a write than a read. Rendered HTML that revalidates on a timer is the worst workload for that pricing, and images are the best.
Your error handler is inside the cache
3 min readA thirty-second backend restart became an hour of 404s, because a try/catch inside a "use cache" function cached the failure as a value.
Keep the model call off the request path
3 min readA per-instance throttle limited nothing and blocked the job meant to recover from quota exhaustion. Removing the request path's ability to generate fixed both.
Idempotent writes don't make side effects idempotent
4 min readMaking an offline-first upsert safe to replay took an afternoon. The streak, points, awards and celebration it triggers each needed their own guard.
Math.floor is not a floor
4 min readFlooring a decimal for an API that wants strings: the obvious version drops a step, the clever one rounds up past the input, and neither throws.