Writing
3 min read
Your LLM can't hallucinate a number it was never given
Preventing 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.
2 min read
Cache the prompt, not the inputs
An 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.
3 min read
Fire-and-forget doesn't survive on Cloudflare Workers
A 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.
4 min read
What a non-extractable key actually protects
Keeping 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.
4 min read
We moved our page cache to R2, then deleted it
R2 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.
3 min read
Your error handler is inside the cache
A thirty-second backend restart became an hour of 404s, because a try/catch inside a "use cache" function cached the failure as a value.
3 min read
Keep the model call off the request path
A 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.
4 min read
Idempotent writes don't make side effects idempotent
Making an offline-first upsert safe to replay took an afternoon. The streak, points, awards and celebration it triggers each needed their own guard.
4 min read
Math.floor is not a floor
Flooring 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.