Writing
The Blog
Load Balancers Terminate Connections: What That Does to Source IPs, Health Checks, and Draining
Every layer in this series so far assumed the connection hitting your security group belongs to the client. It doesn't, not once a load balancer sits in front of the instance. The load balancer ends the client's connection and opens a new one of its own. This is what that actually changes, at the packet level, and why teams debugging intermittent drops keep looking at the wrong layer.
Iptables, Nftables, and Conntrack: What's Actually Enforcing Your Security Group
A security group is a suggestion the moment traffic crosses the network interface. The kernel makes the real decision, packet by packet, through netfilter, iptables or nftables, and a connection tracking table that remembers every flow your server has ever touched. This is that layer, in full.
The Most Expensive Part of Your Agent Stack Is Also the Least Predictable
Routing, model selection, and task assignment are bounded decisions. They don't need a frontier model, they need a policy. Architecture, cost tables, a security layer, a real migration case study, and a model shopping list.
Security Groups Explained: The Firewall Rule That Outlives Every Project
A security group is a stateful firewall attached to your instance's network interface. This is a complete breakdown: what it is, why it works the way it does, how packet evaluation actually happens, real production examples, and the delivery handoff pattern that turns a temporary rule into a breach.
I Gave an AI Direct Write Access to My Codebase. Here's the Architecture.
Most developers use AI as a text generator. I wired Claude directly into my portfolio repo, and it can now read, write, and commit any file without me touching a keyboard. This is how the MCP server works, what broke during the build, and why server.close() was the culprit.
Broadening the Horizon: What Scripts Can Build Beyond the Toolchain
Every post on this site has a unique branded cover generated by a 300-line Node.js script. TF-IDF keyword extraction, Sørensen-Dice fuzzy matching, Iconify icon resolution, deterministic hashing. No AI. No design tool. One command.
Scripts as System Coordination: Managing a Monorepo with Node.js Scripts
A monorepo with four submodules, a shared contracts package, and a generated type chain has coordination problems no single repo has. Here are three scripts that solve them with one command each.
Scripts as Quality Gates: How the Pre-Commit Hook Works
Six pre-commit checks, all running on staged files only, completing in under three seconds. Here's the design behind a quality gate that developers leave enabled instead of bypassing with --no-verify.
Scripts Are Not Shortcuts. They Are Architecture.
npm scripts are not aliases. They are the interface between a developer's intent and a system's behaviour. Here's how a real production monorepo uses over fifty scripts to encode decisions about how it runs, validates itself, and ships, plus what actually happens on the machine when a script runs and how to stop one cleanly.
Where Did the Cost Go? Building a Terminal API Monitor, Part 5
For four parts I claimed Rust gives you memory safety and fearless concurrency at no runtime cost. This is where I prove it, traits, iterators that vanish into loops, zero-cost abstractions, and a release binary measured against Node and Python. The cost was real; it was just paid at compile time. Part 5 of 5.
A Panic Wrecked My Terminal, Then RAII Fixed It Forever: Building a Terminal API Monitor, Part 4
I ran the TUI, it panicked mid-render, and left my terminal in raw mode, no echo, no newlines, a wreck. The fix turned out to be the same RAII mechanism that frees memory in Rust. This is the part about error handling without exceptions, pattern matching, and the Drop trait. Part 4 of 5.
Fearless Concurrency Is Real: Building a Terminal API Monitor, Part 3
Polling one endpoint at a time is slow. Polling them concurrently means sharing state between tasks, and that is exactly where every other language hands you a data race at 3 a.m. This is the part where Rust's ownership rules stop feeling like bureaucracy and start feeling like a superpower. Part 3 of 5.
Borrowed Value Does Not Live Long Enough: Building a Terminal API Monitor, Part 2
Ownership was the warm-up. The error that actually broke my brain was "borrowed value does not live long enough." This is the part where serde, borrowing rules, and lifetimes collide while parsing an API response, and where Rust's reputation for difficulty is earned and then justified. Part 2 of 5.
I Tried to Print a Variable Twice and Rust Refused: Building a Terminal API Monitor, Part 1
I came to Rust from garbage-collected languages and got stopped cold on day one, by trying to use a variable twice. This is the story of building `pulse`, a terminal API monitor, and the afternoon ownership rewired how I think about memory. Part 1 of 5.
Bloom Filters vs Hash Sets: Why the Wrong Choice Costs You Millions of Database Calls
At ten million items, a well-tuned Bloom filter uses ~9MB where a hash set uses ~320MB. Here's the math, the implementation, false positive tuning, and benchmarks across one million, ten million, and one billion items.
Consistent Hashing: The Algorithm That Keeps Million-User Apps From Falling Over
When you add one server and your app goes down, the culprit is almost always naive load distribution. Consistent hashing solves this by moving only K/N keys instead of nearly all of them. Here's the mechanism, the implementation, and benchmarks under real node churn.
HyperLogLog: How Spotify Counts 600 Million Users With 12 Kilobytes of Memory
HyperLogLog estimates the count of distinct elements in a stream using O(log log N) memory. In practice, 12KB and ~1.3% error across cardinalities from 1 to 10 billion. Here's the mechanism, implementation, merge property, and benchmarks.
I Built a Figma Comment Tracker With No Backend Comment Storage. Here's Why.
The standard approach to a tool like this would be to fetch comments, store them in a database, and serve from your own API. I made a different call. No backend comment storage at all. Here is the architecture, the tradeoffs, and the one thing that bit me.
How I Built an Offline-First Event Platform Using BLE Mesh Networking
Most apps assume the internet exists. I built one that doesn't. This is how I architected OurStoryz, a production event platform that works fully offline using BLE mesh networking, Kalman filtering for RSSI-based positioning, and hybrid transport layers.
Junior Devs Are Not Losing Jobs to AI. Mid-Level Devs Are.
The conventional wisdom is wrong. AI is not eating junior developer roles first, it's compressing the mid-level skill premium out of existence. Here's what's actually happening on engineering teams right now.
I Modernized a 20-Year-Old VB.NET System Without Burning the Business Down
Legacy modernization is the most underrated skill in software engineering. This is the Grimm Scientific case study, migrating a VB.NET monolith to Nuxt.js while the business ran uninterrupted, with 95% load time reduction.
Clean Code" Is Killing Your Productivity and Your Team Doesn't Know It
Clean Code by Robert Martin has sold millions of copies. It's also responsible for some of the most over-engineered, slow-to-ship codebases I've ever seen. Here's the case for pragmatic engineering over clean code orthodoxy.
I Built a Multi-Agent AI System That Runs My Business While I Sleep
I run a small incense brand alongside my engineering work. I don't have time to be the operator. So I built agents to do it, a four-agent system on local LLMs with zero cloud AI cost, running on my own hardware.
You Don't Have a Skill Problem. You Have a Visibility Problem.
I've talked to developers with five years of production experience who can't land a remote contract. And I've seen two-year developers charging $150/hour. The difference is not skill. It's visibility.
Offline-First Is Not a Feature. It's an Architecture Decision You Can't Bolt On Later.
We'll add offline support before launch" is the engineering equivalent of "we'll add tests after it's working." It reveals a misunderstanding of what offline-first actually is. Here's what it costs to get this wrong.
Full-Stack Is a Lie. Here's What Actually Matters.
Every startup wants a full-stack developer. Someone who can do the database, the API, the frontend, the CI/CD pipeline, the cloud infrastructure, and review the security audit on weekends. This is not a job description. It's a budget problem.
Stop Using TypeScript Like It's JavaScript With Spellcheck
The 'any' type is a lie you tell TypeScript so it stops asking questions. Every codebase I've walked into that claimed to be "written in TypeScript" has had the same anti-patterns. Here's what TypeScript looks like when used as an architecture tool.
Your Side Project Is Not Failing Because of Execution. It's Failing Because Nobody Wants It.
Every failed side project has the same autopsy, "I just didn't have time to market it." That's almost never true. Here's what's actually happening and how to build something the market actually wants.
The Best Debugging Skill Is Not Reading Stack Traces. It's Building Mental Models.
Two engineers face the same bug. One resolves it in 20 minutes, the other in three hours. Same logs, same debugger, same codebase. The difference is not tooling, it's mental model quality.
AI Coding Tools Don't Make You a Better Engineer. They Make Visible Whether You Already Were One.
GitHub Copilot and Claude do not make all engineers equally capable. They make the gap between good and bad engineers wider and faster to observe. Here's the pattern I've watched play out.
The Freelance Developer Market Is Not Saturated. It's Mis-Positioned.
Freelance dev is dead. Upwork is a race to the bottom." This is partially true and mostly wrong. The race-to-the-bottom market is real, for generic web development. The market for specialists is undersupplied. Here's the difference.