I write when something broke in an interesting way, when I changed my mind about something, or when I’ve explained the same thing to three people and would rather send a link.
Writing
Production mistakes, AI product judgment, open source, and the occasional note for students.
If you only read a few
- I Shipped a Race Condition That Oversold Stock (And Other War Stories) Bugs I shipped in a retail system and an AI pipeline, and the unexciting fixes that held. 4 min
- LLMs Can't Save Bad UX Why most AI features that flop were product decisions first. 6 min
- The Best Way to Learn a Codebase Is to Break Someone Else's What maintainers taught me by explaining why my fix was wrong. 4 min
- Agent Middleware: What Kept Obelisk's Agents in Line The control layer that made fifteen-odd agents manageable. 5 min
2026
- The Best Way to Learn a Codebase Is to Break Someone Else's What maintainers of kitty, calibre, libtorrent and Fallow taught me in review threads, usually by explaining why my fix was wrong in a way I hadn't considered.
- TF-IDF in OCaml: When Functional Programming Clicks Building a local code search engine in OCaml turned out to be a good excuse to learn TF-IDF, pure pipelines, and where immutability actually helps.
- Structured Logging for AI Debugging Why one structured event per request makes AI-assisted debugging far more useful than a pile of scattered console logs.
- Scoring Fraud in Legal Intake Calls Coached callers, invented doctors and borrowed photos. How RISQ scores intake calls for mass tort firms, and why the most useful score measures the interviewer, not the caller.
- Most of My Pull Requests Started as an Annoyance Drive-by fixes in qBittorrent, Dokploy and django-hijack: which ones merged, which didn't, and what the rejections taught me about scope.
- LLMs Can't Save Bad UX When an AI feature flops, the model is rarely the problem. Three features I watched fail, what fixed them, and the questions I now ask before anyone writes a prompt.
- I Shipped a Race Condition That Oversold Stock (And Other War Stories) Two cashiers selling the last item, a chain that returned nothing, and a lock that only worked when both requests hit the same process. Bugs I shipped, and the unexciting fixes that held.
- How Pyscn Analyzes Python with Go and tree-sitter How Pyscn uses Go and tree-sitter to analyze Python code quickly for dead code, clone detection, and dependency insight.
- How Fallow Analyzes TypeScript in Under a Second How Fallow gets dead-code and dependency analysis done fast by skipping the TypeScript compiler, flattening graph storage, and leaning on Rust.
- Every Abstraction I Regret A short list of abstractions I added too early, why they got worse over time, and the heuristics I use now to avoid repeating it.
- Agent Middleware: What Kept Obelisk's Agents in Line Obelisk runs more than fifteen specialist agents. The agents were the easy part. Model choice, context, cost, retries and approvals all ended up in a middleware layer, and that layer is what made it work.
- LangChain in Production: What the Tutorials Leave Out Where LangChain earns its place, where it gets in the way, and the handful of habits that kept our AI features from failing quietly: timeouts, validation, real persistence, tracing and pinned versions.
2025
- Free Web Dev Platforms That Are Actually Worth Your Time A practical shortlist of free web development learning platforms and how to use them without getting stuck in tutorials.
- Final Year Project (FYP) Guide for Students A practical final year project guide for choosing scope, building steadily, avoiding weak ideas, and presenting work clearly.
- What I Actually Spend on Running mhassan.dev: $8/year The full cost of running this site, what's free, and the tradeoffs behind each choice.
- The Invoice Page That Took 4 Seconds to Search How preloading product data cut search latency from 4 seconds to instant on a POS invoice page, and when this pattern breaks down.
- When to Extract a Component (and When to Just Copy-Paste) The 3-usage-sites heuristic for component extraction, a premature ConfirmDialog that cost me time, and why copy-paste is sometimes the right call in Vue.
- Polaris Performance Log: The Django Mistakes I Made First Refunds that queried once per line item, stock updated one row at a time, and signals that recalculated ledgers nobody asked about. What I changed in Polaris, and what I'd tell myself earlier.