Simplicity Is a Place You Stand

What operating at altitude at Amazon, and a year of building alongside agents, taught me about the word "simple."

Where are you standing? The same design, three honest answers: at the valley floor it is simple, at the whole system it is five systems to run, and six months out it is simple only if you can predict it without reading it.

Ask three good engineers whether a design is simple and you'll get three different answers, and the strange part is that all three can be right at the same time. Simplicity turns out to be a property of where you're standing when you look at the thing, which took me an embarrassingly long time to notice.

I learned it at Amazon in the 2010s, in a building in South Lake Union called Fiona, which held every cloud and content service behind Kindle and the early Fire tablets. The devices themselves, the hardware and the firmware, were designed at Lab126 down in Cupertino, and I flew down there every week for two days. By then I'd been a Senior Principal for years and this was not my first rodeo, and my days went like this: walk into a room with a team I hadn't had a conversation with in weeks, sometimes months, whose code I had never read and was never going to, and go deep on whatever was on fire. One day it was interactions with the retail systems, the next it was the seam between the device and the cloud. How the firmware should retry when a download died halfway. What it actually cost to hold a keep-alive connection open across a cellular network, and who was paying for it. The cloud engineers in Fiona could draw their half. The hardware and firmware engineers at Lab126 could draw theirs, and both groups were excellent and both were sure the problem was on the other end of the connection. Nobody could draw the whole thing, and the bug lived in the part nobody could draw.

Repeat that across fifty-some teams and there was no way to know the specific code. I couldn't have read it even if I'd wanted to. Hundreds of engineers, dozens of services, and I was in any one room for an hour or two, max. So the job was never reading. It was getting Fiona and Lab126, each of whom had optimized their half perfectly, to agree on how the thing between them behaved, well enough that someone would sign off on a launch. You develop a reflex after enough of those rooms. You stop asking "is this code clean" and start asking "can I tell how this behaves without seeing inside it." Those are different questions, and most of the expensive mistakes I saw lived in the gap between them.

The view from the valley floor

From the bottom, almost everything looks simple.

Down at the level of a single file, a single endpoint, a single pull request, the simplest-looking option is usually "call the API directly." Fewer lines. Less indirection. You can hold the whole thing in your head and ship it before lunch. Every instinct you have, sharpened by years of being told to avoid premature abstraction, points the same direction. Just use the official SDK. Just hit the endpoint. Why are we even discussing this.

And sometimes that instinct is exactly right, which is what makes it so dangerous the rest of the time.

The problem is that the valley floor is the one place the real complexity can't be seen from. It's still there. It's standing in the on-call rotation six months out, or in the third platform you'll integrate next quarter, or in the forced upgrade that lands on a calendar you don't control (this one has bitten me twice, both times with a payments provider). The bottom-up view doesn't reduce any of that. It just hasn't met it yet.

So when someone tells me a design is simple, my first question is never "how do you know." It's "where are you standing."

Five systems, or one

Watch it happen in a real decision, the one half the industry has spent the last couple of years re-litigating. You're building the plumbing under a growing product. You need event streaming, so you reach for Kafka. You need a cache, so you add Redis. You need search, so you stand up Elasticsearch. You need a nine-step onboarding saga to survive a deploy and retry cleanly, so you bring in Temporal. Each of those choices is correct from the vantage you make it at. Kafka really is the right tool for streaming. Redis really is the right cache. Looking at one need at a time, you've made four clean, defensible decisions, and I would have waved every one of them through in review.

Now climb up and look at what you actually built. You operate five data systems instead of one. Five sets of failure modes, five on-call runbooks, five scaling stories, five upgrade treadmills, and the genuinely hard problem living in the seams between them, which is keeping five stores consistent when one is behind, or down, or quietly lying. Nobody chose that. It assembled itself one reasonable decision at a time, and you can only see the whole of it from somewhere none of those decisions were made.

Then there's the move that looks dumb from the floor and turns out to be the simple one: run all of it on Postgres. The queue, the cache, the search, the scheduled jobs, the workflow state. One boring database doing five jobs adequately, as long as vacuum keeps up, instead of five specialized systems doing them perfectly. A reviewer flinches. You're using a relational database as a queue? From inside any one of those needs, yes, it's the worse tool. But from the altitude of the whole system, the thing a human or an agent actually has to operate, reason about, back up, and evolve for years, it is dramatically simpler. This is roughly why "just use Postgres" went from a contrarian take to a vendor headline in about two years, and why Gunnar Morling felt he had to write the "considered harmful" rebuttal. Both camps are right about what they can see.

But there's an altitude above that one, and from there "number of systems" turns out to be the wrong unit too. What you're actually counting is the number of invariants your team has to personally own. Kafka packages replay, durability, and backpressure so you never write them. Temporal packages the retry semantics and the state machine you would otherwise smear across six services. One Postgres instance holding five homemade subsystems has less operational surface and more semantic ownership than five managed products, and which of those costs you more depends on where you're standing and when. We ran SageOx on one Postgres for about a year, and it was the right call the whole time. Last week we added a shared cache and split the catalog service into readers and a single writer, because the invariants we were hand-rolling inside Postgres had started to cost more than the systems that package them. Nobody reversed a decision. We were standing somewhere new when we looked again. This spring Nango wrote up pulling Temporal out for a Postgres scheduler and FireHydrant wrote up moving onto it from Sidekiq, in the same month, and I think both were right. I'm less sure the invariants framing holds at forty engineers. It has held at eight.

What you actually reason about

When you can't read the code, you find out very quickly what you were actually relying on to make decisions, and it turns out it was never the code. It was the conceptual model. The shape of the API surface. The interaction model: what calls what, what waits on what, what happens when a thing fails. If those three things are legible from the outside you can make big multi-team decisions in an afternoon. If the only way to know how a system behaves is to read how it's implemented, you can't make any of them, and you'll spend the afternoon reading instead.

The best teams I worked with had this property and didn't always know it. You could sit in a room, draw their system on a whiteboard from memory, and they'd nod, because the system actually behaved the way its contract said it did. The worst situations weren't bad code. They were systems where the contract and the behavior had quietly diverged, so the only source of truth was the implementation, and the only people who could reason about it were the two engineers who'd written it. That system was simple to exactly two people, both of whom eventually left.

A system you can only understand by reading the code or a long design doc is not simple.

It has externalized its complexity onto every future decision. The inverse is the trap, though. A system whose interface is easy to reason about isn't necessarily simple either. Put a key, get a value: an exquisitely simple interface sitting on top of a distributed database with enormously consequential semantics underneath. A clean contract can conceal complexity instead of removing it. So the test I actually use is predictive power, not encapsulation. Can someone holding the conceptual model predict the behavior that matters, including how it fails, without reading the implementation? Where they can, the system is simple from where they stand. Where they can't, the clean interface is a curtain, and I've been fooled by a few.

The ladder is a set of vantage points

We usually describe the climb from Senior to Staff to Principal to Distinguished in terms of scope, or blast radius, or impact. Those are real, but they're the symptoms. What actually changes as engineers grow into those later stages is the number of vantage points they can hold, and more importantly, their fluency in moving between them. Holding several is table stakes. The rare thing is moving between them fast without losing the thread.

Early on, getting better mostly means accumulating technical knowledge. You learn the language, the runtime, the failure modes, the war stories. That never stops being valuable. Deep knowledge is exactly what lets you reason accurately from any vantage instead of hand-waving from a great height. The mistake is thinking knowledge alone keeps moving you up, when at some point the job quietly starts asking for a second skill on top of it, which is the ability to see the same problem from more than one place. I've watched brilliant engineers stall right there, not because they stopped learning, but because learning more was the only tool they'd ever sharpened.

Because the later you get, the less the work is about solving the problem in front of you and the more it's about choosing which problem you're actually solving, which is a question you can only answer by looking from somewhere other than the valley floor. The actual skill is deciding which vantage the decision should be made from this time, and standing there on purpose. Every plateau I've watched, including a couple of my own, came down to solving every problem from whichever altitude the person happened to be most comfortable standing at.

The thing that changed

For most of my career this was a Principal engineer's problem. Most engineers spent most of their time at the valley floor, in the implementation, and that was fine, because that's where the work was.

That's over. The altitude is now the default place everyone builds from.

The reason is blunt: writing code stopped being the expensive part. DHH put a date on it at Rails World last week, when he told the room that 37signals is done writing code by hand, and then went further:

Writing code by hand is no longer an economically productive enterprise for the vast majority of programmers working at the vast majority of companies. That's today.

DHH, Rails World 2026 opening keynote, September 24

Be precise about what got cheap, though. Agents made producing a plausible implementation cheap. They did not make correct code cheap to the same degree, and they did nothing for the migration that follows a wrong one, the incident at three in the morning, the security hole nobody reviewed, or the architectural entropy that accumulates when a hundred plausible changes land in a week. Once a fleet of agents can produce something that looks right faster than you can tell whether it is, the constraint moves off the implementation and onto your comprehension. The bottleneck is no longer "can we build it." It's "can we understand, trust, verify, and steer it," and all four are paid in human attention, which does not get cheaper when the agents do. Galex, one of my cofounders, put it more bluntly than I would: "I don't read code anymore." He isn't bragging. He means that if he has to read it to know how it behaves, every decision drags him back to the valley floor, and decisions made at reading speed are made at the speed of one human, which is the one thing in the building that doesn't scale.

Agents made plausible code cheap. They made knowing it's right precious.

Attention is the real budget

I stopped optimizing for lines of code long ago. In the last six months the rest of the industry caught up, and reviewing code line by line is going out with it. What I optimize for is human attention over time. Not attention today. Over time, meaning the whole stretch of operating and steering a system across however many months or years it actually lives, which is always longer than the sprint that built it.

A design that's tidy today but drags you back into its guts every time the ground shifts is not cheap. It's a recurring withdrawal from the scarcest account you have. A design you can hand to a team, human or agent, and genuinely forget, because you can predict it from the outside, is the cheapest thing in the building even if it took more code to stand up. Cheap-to-evolve beats cheap-to-write, and it isn't close.

The old way to buy that was a stable internal contract with the churny machinery hidden behind it, and it's exactly the thing the last twenty years taught us to distrust, because every contract you froze was a bet on a future you couldn't see. We don't freeze internal contracts anymore. An agent can rewrite an interface and every caller of it in one session, so the internal API that used to feel permanent is now just another thing that gets reshaped as the system moves. What we hold stable instead is cheaper: each piece stays describable. A boundary you can state in a paragraph, tests that say what it promises, and a recorded reason it exists. That's enough for a human to predict it without reading it and for an agent to regenerate it without asking. Ajit has a rule for this that I've stolen: if the boundary costs three hours, draw it; if it costs three days, don't, because by the time you need it an agent will redraw it for less. The contract was never the point. Being able to predict the thing from outside was.

Which changes the test. Not "can I hide this behind a stable contract?" Almost anything can be. The question is whether drawing a boundary here reduces total future reasoning by more than the boundary costs to keep legible. A boundary that lets a hundred future decisions skip the code-dive pays for itself in the first month. A boundary around something nobody will ever need to swap or re-understand is just more system to reason about. The contracts that still lock are the ones that cross the edge to someone who isn't you: the API a customer codes against, the schema with a billion rows in it, the promise another team already built on. That's where the old rigor belongs. It can relax almost everywhere else.

Where the old advice still holds

We spent twenty years rightly warning each other against over-engineering, against abstraction nobody asked for, against the seam built for a future that never arrives. When code was expensive, "more code" was a real cost and minimizing it was real discipline. Now that an agent fleet can write and even maintain the code underneath a contract, "more code" is mostly a non-argument, and the real cost has migrated to comprehension and trust. The discipline didn't disappear. It moved. The new over-engineering is a system nobody can reason about without reading it, no matter how few lines it has.

And sometimes the valley-floor answer is just correct. Think of a payment SDK called directly. One platform, the data is already theirs, nothing to hand back, no foreign runtime. Bottom-up and top-down agree, and a seam there would cost more reasoning than it ever saved. The skill is knowing where you're standing and choosing it, instead of defaulting to the valley floor because that's where your feet already are.

Standing somewhere on purpose

Before you decide anything is simple, climb to wherever the complexity actually lives, which is usually a level or two above wherever you're standing, and look at the option from there. Ask whether you'll be able to predict its behavior from the outside six months from now, when the person holding it is a teammate you've never met, or an agent whose whole picture is the contract plus the recorded conversation where you drew it. At SageOx we keep those conversations for exactly that reason. Ask what it costs in attention over its whole life, not what it costs to generate. And then, having actually looked, sometimes choose the one-liner, because from altitude it really was the simplest thing, and you can prove it instead of assuming it.

The engineers who'll matter most over the next decade are the ones who can change altitude fast without losing coherence. Customer to system to service to trace to commit to the decision that caused it, and back to the customer, in one sitting. Agents made every one of those climbs nearly free. The rung they can't traverse on their own is the decision, because it lived in a conversation, and the code an agent can query. The argument behind it, it can only replay if someone kept it.

Holding several vantage points at once was always the Principal engineer's job. Moving between them fast, without losing the thread, is now everyone's.

Share