/writing
Writing on building things that hold.
Long-form thinking on architecture, distributed systems, and the discipline behind production software. What I share when I sit down to write rather than ship.
/tags
/writing
Long-form thinking on architecture, distributed systems, and the discipline behind production software. What I share when I sit down to write rather than ship.
/tags
Your contact form takes a name, an email, and a message. Three fields. Two of them can take over your mail server if you let them. A short tour of an attack that's older than I am, and how I found it in code I'd just shipped.
Click 'pay' twice when the page hangs and you shouldn't get charged twice. Here's how to make that promise — with one Redis key, a TTL, and a small race-condition guard.
Content Security Policy is the spam filter for your HTML — it tells the browser which scripts are allowed to run. The default examples don't work with Tailwind, Next.js, or third-party scripts. Here's the configuration that does.
A classroom is fine until the teacher tries to hear thirty questions at once. Scaling a real-time edtech platform from a small cohort to many thousands of concurrent learners taught me which decisions to make on day one — and which mistakes I made on day fifty.
What if the form just called your function — no fetch, no JSON, no route file? After six months of shipping server actions in production, here's where they win, where they don't, and how I decide which to use.
If you wouldn't pour the foundation after the roof, why do we keep building UIs before we know what data lives behind them? A case for designing the schema first — not because backend matters more, but because it's the part that can't be undone.