Recent posts

The cost of dependencies

Adding a dependency takes one line in a manifest, and someone else’s hard problem is solved. With that line we also take on their bugs, their security holes, their release schedule, and their own dependencies, for as long as our code lives. The cost is small while we write the code and grows once the system is in production and users ask for changes. I have watched teams take whatever was available to keep moving, some on principle, and pay for it in maintenance. So a dependency should be chosen on purpose, after an evaluation. Let’s look at what it costs, and then at how to evaluate one.

Duff’s device, part 2: copying within an array

Duff’s device in JavaScript raced hand-written loops that copy one array into another. A reader asked the follow-up: how do they compare with Array#copyWithin, the built-in that copies a range inside a single array? That is a different workload, so it needs its own measurement. The short answer: on every Node and Deno we can install today, the built-in runs 47 to 84 times slower than the loop.

“Premature” optimization

1 Sep, 2026 - 15 minutes

“Premature optimization is the root of all evil” — our field’s favorite half-sentence, quoted far more often than the sentence it was cut from. Usually it serves as permission: build it fast, profile later, fix a thing or two, done. Let’s put the sentence back together and ask what it licenses: when is optimization premature, and when is “premature” the excuse?

Death by a thousand reasonable decisions

25 Aug, 2026 - 11 minutes

When I read consistent, cohesive code, I have a feel for its author. I may disagree with the ideas, but I can feel where the author is driving it. Other times the feel is split-brain — the code’s “energy” is fractured, the work of unaligned hands each solving its own small problem, none with an idea where the whole is going. Immediately I feel it should be rewritten or refactored holistically.

Here is the paradox. Most of us are dedicated professionals with years of experience, and bad code is everywhere. Programmers I respect produce it; my own code is far from perfect. Why?

Fast enough

28 Jul, 2026 - 17 minutes

Efficient resource utilization was at the forefront of computing from the very beginning. Over time we traded some of that efficiency for developer experience, and preserved the rest by harnessing better hardware and new paradigms: multithreading and multiprocessing, stream processing, asynchronous programming… Languages are how we reason about problems, encode algorithms, and organize programs — the vector runs from high-level languages through structured programming, OOP, functional and logic programming. Note what that vector does not include: how the runtime is structured, compiled or interpreted — either way we write some text and hand it to the system. Each step looks logical in hindsight. Yet some things don’t look logical at all.

Back-of-the-envelope estimates

Most of the numbers that decide an architecture can be settled on the back of a napkin, before a line of the prototype is written. A handful of formulas and a latency ladder you can recite from memory rule out bad designs a profiler could only catch after they’re built. The same numbers expose the quieter traps — like a redundant trio of replicas that one dead node takes down whole. Let’s do the arithmetic.

TDD as religion

Tests are a cornerstone of modern development, and somewhere along the way we started treating a green suite as proof. It isn’t: it tells you the cases you thought of still pass, not the ones you didn’t. That confusion was always with us — and it matters more now that an AI agent might be the one chasing the green.

200ms ± 500ms

I once needed the SLA for an endpoint my dashboard leaned on, so I asked the team that owned it. Their lead came back with 200ms ± 500ms. Read that literally and the fastest responses arrive 300ms before the request is even sent. The number wasn’t malicious — it came straight out of the standard formulas. The formulas were wrong for the data, and that mistake is everywhere.

Logical optimizations

The second article in the series. The first was about control flow; this one stays with the same tactic — reshaping code — one layer down, at the condition. Here: merging ifs, factoring shared decisions, and dropping checks that earn nothing. The Boolean algebra of conditions — De Morgan and friends — is a different lever, and gets its own installment next time.

Code is cheap

2 Jun, 2026 - 6 minutes

The first time I said “code is cheap” out loud in a meeting, a manager waved at the budget — headcount, salaries, the tooling line — and asked which part of that looked cheap. He wasn’t wrong about the number — he was wrong about what it was buying.

Code linearization

26 May, 2026 - 8 minutes

You can find plenty of articles about design — where and how to use SQL, NoSQL, message queues, Redis, VMs, and so on. Almost nobody writes about tactics: the actual coding. It borders on style, but it isn’t just style. This is the first article in a series on tactics I use day to day. Highly opinionated — I don’t expect you to follow it. Look, chuckle, think about it, and use what you like.