Tech
Tech · ◉ Evergreen

Every abstraction leaks. The skill is choosing which leaks you'll live with.

by Shreyansh Ojha·6 min·Working Theory

There’s a phrase, coined by Joel Spolsky back in 2002, that has quietly organized how I think about tools ever since: all non-trivial abstractions, to some degree, are leaky. It sounds like a complaint. It’s closer to a law of nature, and once you’ve internalized it you make different decisions about what to build on.

Start with what an abstraction is for. It’s a promise that you can use something without understanding what’s underneath. TCP promises reliable, ordered delivery so you don’t have to think about the internet’s actual behavior — packets that vanish, arrive twice, or show up out of order. An ORM promises you can work with objects and never write SQL. A file promises a simple stream of bytes and hides the spinning platter or the flash controller. Each one lets you not-know something, and that not-knowing is the entire productivity dividend of modern software. Nobody could build anything if they had to hold the whole stack, from transistors up, in their head at once.

The catch is in Spolsky’s word: leaky. The abstraction hides the underneath right up until the underneath does something the abstraction didn’t paper over — and then the reality you were promised you could ignore comes flooding up through the seams, usually at the worst possible moment.

your code — "just objects" the ORM — "no SQL needed" SQL — "just declare the result" disk, indexes, query planner the clean promise reality leaks up
Each layer promises you can ignore the one below it. The N+1 query, the deadlock, the mysterious slow page — that's the bottom of the stack leaking up through abstractions that were supposed to hold. Original diagram · Working Theory

The examples are everywhere once you look. The ORM lets you ignore SQL until one innocent-looking loop over a list of objects quietly fires a thousand separate database queries, and suddenly you must understand SQL, indexes, and the query planner to explain why the page takes nine seconds. TCP hides packet loss until you’re on a flaky connection and the “reliable” stream stalls in a way you can only diagnose by understanding the network it swore you’d never have to think about. A remote procedure call is dressed up to look exactly like a local function call — same syntax, same shape — which is precisely the leak, because a local call doesn’t fail because a cable was unplugged. That last one is enshrined in the old “fallacies of distributed computing”: the network is not reliable, latency is not zero, bandwidth is not infinite — every one a place where the “it’s just a function call” abstraction leaks the physics of a real network into your code.

Here’s the part that matters for building, because “everything leaks, despair” is not a useful conclusion. The leaky-abstraction law doesn’t tell you to abandon abstractions — you can’t, they’re the only reason you can build at all. It tells you to choose them with your eyes open, on two axes.

First: how good is the abstraction when it holds, and how bad is the leak when it fails? A great abstraction holds almost always and leaks gently — when it breaks, the reality underneath is learnable and the failure is legible. A bad one holds most of the time and then leaks catastrophically into a layer you have no tools to inspect. Prefer tools whose failures you can actually diagnose over tools that are marginally more convenient on the happy path but opaque when they crack.

Second, and this is the one experience teaches slowly: you don’t get to skip learning the layer beneath the one you work in — you only get to defer it. The abstraction buys you time, not permanent ignorance. The senior engineer isn’t the one who memorized more layers; it’s the one who accepted that the ORM will eventually make them read SQL, that the framework will eventually make them read its source, and who treats the layer below as something they’ll need someday rather than something they’ve been freed from forever. So when you pick what to build on, quietly ask: when this leaks — not if — is the thing underneath something I can come to understand, or a black box I’ll be stuck praying to? That question, more than raw convenience, is what separates a tool you’ll be glad you chose from one you’ll be trapped inside.

The science, to look up: Joel Spolsky's 'The Law of Leaky Abstractions' (2002); the fallacies of distributed computing (attributed to L. Peter Deutsch and colleagues at Sun, mid-1990s); and, more broadly, the engineering aim of 'separation of concerns' that abstractions are meant to serve. These are craft principles and observations rather than formal experimental results — durable because they keep coming true, not because they were measured in a lab.

Liked this? Get the next one in Working Theory.

Going weekly in August (it's in beta now). One genuinely interesting read on building, the brain, and the science most people missed.

Got a reaction, a counter-example, or something I missed? Reply by email — I read everything.
◉ join in

Where have you hit this — in a product you use, or one you're building?

Threads open here soon. For now, the conversation lives two clicks away — discuss on GitHub, or just reply by email. I read and answer everything.