162 comments

[ 2.6 ms ] story [ 101 ms ] thread
“Everything should be made as simple as possible, but not simpler.”

As someone who has strived for this from early on, the problem the article overlooks is not knowing some of these various technologies everyone is talking about out, because I never felt I needed them. Am I missing something I need, but just ignorant, or is that just needless complexity that a lot of people fall for?

I don’t want to test these things out to learn them in actual projects, as I’d be adding needless complexity to systems for my own selfish ends of learning these things. I worked with someone who did this and it was a nightmare. However, without a real project, I find it’s hard to really learn something well and find the sharp edges.

> Am I missing something I need, but just ignorant, or is that just needless complexity that a lot of people fall for?

Ignorance plays a big role. If you don't perceive, e.g. a race condition happening, then it's much simpler to avoid complicated things like locking and synchronisation.

If you have the belief that your code will never be modified after you commit it, then it's much simpler to not write modifiable code.

If you believe there's no chance of failure, then it's simpler to not catch or think about exceptions.

The simplest thing is global variables, single-letter variable names, string-handling without consideration for escaping, etc.

One of the biggest, evergreen arguments I’ve had in my career revolves around the definition of “works”.

“Just because it works doesn’t mean it isn’t broken.” Is an aphorism that seems to click for people who are also handy in the physical world but many software developers think doesn’t sound right. Every handyman has at some time used a busted tool to make a repair. They know they should get a new one, and many will make an excuse to do so at the next opportunity (hardware store trip, or sale). Maybe 8 out of ten.

In software it’s probably more like 1 out of ten who will do the equivalent effort.

> “Just because it works doesn’t mean it isn’t broken.”

Meanwhile all the people writing agentic LLM systems: “Hold my beer”

On the meta level, the simplest thing that could possibly work is usually paying someone else to do it.

Alas, you do not have infinite money. But you can earn money by becoming this person for other people.

The catch 22 is most people aren't going to hire the guy who bills himself as the guy who does the simplest thing that could possibly work. It turns out the complexities actually are often there for good reason. It's much more valuable to pay someone who has the ability to trade simplicity off for other desirable things.

You know what taught me this the best? Watching Mythbusters.

Time and time again amazingly complex machines and they just fail to perform better than a rubber-band and bubble gum.

This just kicks the can down the road. What is "simple"? What does "works" mean?
Great advice.

I always felt software is like physics: Given a problem domain, you should use the simplest model of your domain that meets your requirements.

As in physics, your model will be wrong, but it should be useful. The smaller it is (in terms of information), the easier it is to expand if and when you need it.

"It’s fun to decouple your service into two pieces so they can be scaled independently (I have seen this happen maybe ten times, and I have seen them actually be usefully scaled independently maybe once)."

Same, or reliability-tiered separately. But in both aspects I more frequently see the resulting system to be more expensive and less reliable.

Dealing with this exact scenario, right now. My company has implemented an unnecessarily complex spiderweb of services and the litany of problems that go along with it, in anticipation of some hypothetical, future requirements. Most of the team is fairly new, but they have been led astray by a mid-level engineer who has been masquerading as a top level engineer. By the time I came along, the damage was already done, and the rest of the team is unaware that they have developed about 60 days worth of software, mostly code debt, in more than 18 months.

The situation is extremely frustrating, because I have to be careful not to insult anyone or create endless arguments, while trying to somehow salvage the project into something workable, or convince a team of junior/mid-level engineers to start over (the code is technically not salvageable, at all). Trying to convince people who don't know what they're doing that the same end result could be reproduced in 45 days and then the next 18 months of effort could be condensed into an additional 45 days is like trying to convince an octopus that there are satellites in orbit around the Earth.

(comment deleted)
Don't bother with SSL, it's adds complexity.

Don't add passwords, just "password" is fine. Password policies add complexity.

For services that require passwords just create a shared spreadsheet for everyone.

/s

One of the ironies of this kind of advice is that it's best for people who already have a lot of experience and have the judgement to apply it. For instance, how do you know what the "simplest thing" is? And how can you be sure that it "could possibly work"?

Yesterday I had a problem with my XLSX importer (which I wrote myself--don't ask why). It turned out that I had neglected to handle XML namespaces properly because Excel always exported files with a default namespace.

Then I got a file that added a namespace to all elements and my importer instantly broke.

For example, Excel always outputs <cell ...> whereas this file has <x:cell ...>.

The "simplest thing that could possibly work" was to remove the namespace prefix and just assume that we don't have conflicting names.

But I didn't feel right about doing that. Yes, it probably would have worked fine, but I worried that I was leaving a landmine for future me.

So instead I spent 4 hours re-writing all the parsing code to handle namespaces correctly.

Whether or not you agree with my choice here, my point is that doing "the simplest thing that could possible work" is not that easy. But it does get easier the more experience you have. Of course, by then, you probably don't need this advice.

The simplest thing would have been not to rely on something as complex as XLST, but that ship had sailed long ago.
I don't think it's ironic: maybe it's not intuitive / not easy to do!

But there's utility in talking about it. If you teach people that good engineers prepare for Google scale, they will lean towards that. If you teach that unnecessary complexity is painful and slows you down, they will lean towards that.

Maybe we need a Rosetta stone of different simple and complex ways to do common engineering stuff!

Advice is useless, learning and experience works
> I spent 4 hours re-writing all the parsing code to handle namespaces correctly.

Wouldn't it have been less effort and simpler to replace the custom code with an existing XML parser? It appears that in your case the simplest thing would have been easy, though the aphorism doesn't promise "easy".

If using a library wasn't possible for you due to NIH-related business requirements and given the wide proliferation of XML libraries under a multitude of licenses, then your pain appears to have been organizationally self-inflicted. That's going to be hard to generalize to others in different organizations.

I think the author would say you did the simplest thing that could work.

Ignoring the namespace creates ongoing complexity that you have to be aware of. Your solution now just works and users can use namespaces if they want.

The author deals with this in the hacks section.

It's a shame he doesn't give the origin of this expression in programming. It comes from Ward Cunningham (inventor of the wiki) in his work with Kent Beck. In an interview a few years back on Dr. Dobb's, he stated that as the two of them were coding together in the late 80s, they would regularly remind each other of the principle. Eventually, it became a staple of their talks and writing.

They were cognizant of the limitations that are touched on in this article. The example they gave was of coming to a closed door. The simplest thing might be to turn the handle. But if the door is locked, then the simplest thing might be to find the key. But if you know the key is lost, the simplest thing might be to break down the door, and so on. Finding the simplest thing is not always simple, as the article states

IIRC, they were aware that this approach would leave a patchwork of technical debt (a term coined by Cunningham), but the priority on getting code working overrode that concern at least in the short term. This article would have done well to at least touch on the technical debt aspect, IMHO.

I came here to say this! Ward taught me this when I paired with him every day when we worked together. It’s his, dare I say, mantra when starting a new feature.
> It's a shame he doesn't give the origin of this expression in programming.

It is possible the OP came to this conclusion without knowing about Ward Cunningham?

This sounds a lot like the apocryphal Einstein quote

> Everything should be made as simple as possible, but not simpler.

And I found a similar quote from Aquinas

> If a thing can be done adequately by means of one, it is superfluous to do it by means of several; for we observe that nature does not employ two instruments where one suffices

(Aquinas, [BW], p. 129).

Just to add I think the same applies in business and in life. So if you’ve got managers who have this vision and cascade it down then things become easier on the ground / the design.
> It's a shame he doesn't give the origin of this expression in programming.

Sometimes better to not assume the worst of people by default. Very easy to not know where something comes from, misremember or come up with something in parallel.

I wholeheartedly agree with this. The challenge is perception though. Many managers will see a simple solution to a complex problem and dock you for not doing real engineering, whereas a huge convoluted mess to solve a simple problem (or non-problem) gets you promoted. And in design interviews, "I'd probably implement a counter in memory" would be the last time you ever heard from that company.
(comment deleted)
Before you write a parser, try a regex. (But some times you really do need a parser.)
Generally speaking, when I hear people say this, it's a huge red flag. Really, any time anyone puts forth any kind of broad proclamation about how software development should be done, my hackles go up. Either they don't know what they're talking about, they're full of shit, or both. The only reasonable thing to conclude after lots of experience with software development is that it's hard and requires care and deliberation. There is no one-size-fits-all advice. What I want to see is people who are open-minded and thoughtful.
Did you read the article? It’s mostly about the nuance of how to apply this philosophy in practice, not a pithy one-size-fits-all statement about all software engineering.
Hard, hard disagree.

First of all, simplicity is the hardest thing there is. You have to first make something complex, and then strip away everything that isn't necessary. You won't even know how to do that properly until you've designed the thing multiple times and found all the flaws and things you actually need.

Second, you will often have wildly different contexts.

- Is this thing controlling nuclear reactors? Okay, so safety is paramount. That means it can be complex, even inefficient, as long as it's safe. It doesn't need to be simple. It would be great if it was, but it's not really necessary.

- Is the thing just a script to loop over some input and send an alert for a non-production thing? Then it doesn't really matter how you do it, just get it done and move on to the next thing.

- Is this a product for customers intended to solve a problem for them, and there's multiple competitors in the space, and they're all kind of bad? Okay, so simplicity might actually be a competitive advantage.

Third, "the simplest thing that could possibly work" leaves a lot of money on the table. Want to make a TV show that is "the simplest thing that could possibly work"? Get an iPhone and record 3 people in an empty room saying lines. Publish a new episode every week. That is technically a TV show - but it would probably not get many views. Critics saying that you have "the simplest show" is probably not gonna put money in your pocket.

You want a grand design principle that always applies? Here's one: "Design for what you need in the near future, get it done on time and under budget, and also if you have the time, try to make it work well."

I think this works in simple domains. After working in big tech for a while, I am still shocked by the required complexity. Even the simplest business problem may take a year to solve, and constantly break due to the astounding number of edge cases and scale.

Anyone proclaiming simplicity just hasnt worked at scale. Even rewrites that have a decade old code base to be inspired from, often fail due to the sheer amount of things to consider.

A classic, Chesterton's Fence:

"There exists in such a case a certain institution or law; let us say, for the sake of simplicity, a fence or gate erected across a road. The more modern type of reformer goes gaily up to it and says, “I don’t see the use of this; let us clear it away.” To which the more intelligent type of reformer will do well to answer: “If you don’t see the use of it, I certainly won’t let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it.”"

> Even the simplest business problem may take a year to solve, and constantly break due to the astounding number of edge cases and scale.

You're doing it wrong. More likely than not.

> Anyone proclaiming simplicity just hasnt worked at scale. Even rewrites that have a decade old code base to be inspired from, often fail due to the sheer amount of things to consider.

Or, you're just used to excusing complexity because your environment rewards complexity and "big things".

Simple is not necessarily easy. Actually simple can be way harder to think of and push for, because people are so used to complexity.

Yes. Massive scale and operations may make things harder but seeking simplicity is still the right choice and "working in big tech" is not a particular hard or rare credential in HN. Try an actual argument instead of an appeal to self authority.

This is where John Gall's Systemantics comes into play, “A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system."

Obviously a bit hyperbolic, but matches my experience.

(comment deleted)
When the domain is complex, it's even MORE important that the individual components be simple with clean interfaces between them. If everything is too intertwined, you lose the ability to make changes or add new functionality without accidentally breaking something else.

As for Chesterton's Fence, you have the causality backwards. You should not build a fence or gate before you have a need for it. However, when you encounter an existing fence or gate, assume there must have been a very good reason for building it in the first place.

> Even rewrites that have a decade old code base to be inspired from, often fail due to the sheer amount of things to consider.

The amount of knowledge required to first generate the codebase, that is now missing for the rewrite, is the elephant in the room for rewrites. That's a decade of decision making, business rules changing, knowledge leaving when people depart etc.

Much like your example, if you think all the information is in the codebase then you should go away and start talking to the business stakeholders until you understand the scope of what you don't currently know.

I have worked at scale - I have found countless examples of people not believing in simple solutions which eventually prevail and replace the big-complex thing.

Complexity is a learned engineering approach - it takes practice to learn to do it another way. So if all you see is complex solutions how would you learn otherwise?

> Even the simplest business problem may take a year to solve, and constantly break due to the astounding number of edge cases and scale.

Is this really because the single problem is inherently difficult, or because you're trying to solve more than one problem (scope creep) due a fear of losing revenue? I think a lot of complexity stems from trying to group disparate problems as if they can have a single solution. If you're willing to live with a smaller customer base, then simple solutions are everywhere.

If you want simple solutions and a large customer base, that probably requires R&D.

I remember reviewing some code of an engineer I was managing at a FAANG. Noticed an edge case. Pointed out I thought if/when that hit, it was going to cause an alarm that would page on-call. He suggested it might be OK to ship because it was "about a one in a million chance of being hit". The service involved did 500,000 TPS. "So, just 30 times a minute, then?"

And you're right about the amount of engineering that goes into solving problems. One service adjacent to my patch was more than a decade old. Was on a low TPS but critical path for a key business problem. Had not been touched in years. Hadn't caused a single page in that decade, just trudged along, really solidly well engineered service. Somebody suggested we re-write it in a modern architecture and language (it was a kind of mini-monolith in a now unfashionable language). Engineering managers and principals all vetoed that, thank goodness - would have been 5+ years of pain for zero upside.

Accidental complexity is a thing, YAGNI is a thing, tech debt caused complexity is a thing, I’m a foo programmer let me write bar code like it’s foo is a thing. I don’t know if its all high quality needed
The key is 'required complexity'.

This is different from adding pointless complexity that doesn't help solve the problem but exists only because it is established 'best practice' or 'because Google does it that way' and I've seen this many more times than complex software where the complexity is actually required. And such needlessly complex software is also usually a source of countless day-to-day problems (if it makes its way out the door in the first place) while the 'simplistic' counterpart usually just hums along in the background without anybody noticing - and if there's a problem it's easy to fix because the codebase is simple and easy to understand by anybody looking into the problem. Of course after 20 years of such changes, the originally simple code base may also grow into a messy hairball, but at least it's still doing its thing.

> Even the simplest business problem may take a year to solve, and constantly break due to the astounding number of edge cases and scale.

edge case (n): Requirement discovered after the requirements gathering phase.

Sometimes, often even, complexity and edge cases are symptoms that the problem is not fully understood and that the solution is not optimal.
> I think this works in simple domains

You're not wrong. So many engineers operating in simple domains, on MVPs that don't have scale yet, on internal tools even. They introduce so much complexity thinking they're making smart moves.

Product people can be similar, in their own way. Spending lots of time making onboarding perfect when the feature could do less, cater for 95% of use cases, and need no onboarding at all.

Consider this, everyone at whichever skill level they're at, benefits from applying simplicity to their designs. Also, everyone at any skill level will have a tendency to think the work they are doing is actually deep enough to require the complexity when it reaches the border of their intelligence.

I dont know if you only have genius friends but I can tell you many stories of things people thought warranted complexity that I thought didn't. So whatever you consider hard enough to warrant complexity, just know there's another smarter guy than you thinking you're spinning your wheels.

Also it's an impossible conversation to have without specific examples. Anyone can come and make a handwavy case about always simplifying and someone can make a case about necessary complexity but without specific example none can be proven wrong.

(comment deleted)
> I think this works in simple domains.

Business incentives are aligned around incremental delivery, not around efficient encoding of the target domain. The latter generally requires deep architectural iteration, meaning multiple complete system overhauls and/or rewrites, which by now are even vilified as a trope.

Mostly, though, I think there is just availability bias here. The simple, solid systems operating at scale and handled by a 3-person team are hard to notice over the noise that naturally arises from a 1,000-person suborganization churning on the same problem. Naturally, more devs will only experience the latter, and due to network effects, funding is also easier to come by.

Yet, many times a lot of that scale and complexity is accidental.

Case in point: when I joined the BBC I was tasked with "fixing" the sports statistics platform. The existing system consisted of several dozen distinct programs instantiated into well over a hundred processes and running on around a dozen machines.

I DTSSTCPW / YAGNIed the heck out of that thing and the result was a single JAR running on a single machine that ran around 100-1000 times faster and was more than 100 times more reliable. Also about an order of magnitude less code while having more features and being easier to maintain expand.

https://link.springer.com/chapter/10.1007/978-1-4614-9299-3_...

And yeah, I was also extremely wary of tearing that thing down, because I couldn't actually understand the existing system. Nobody could. Took me over half a year to overcome that hesitancy.

Eschew Clever Rules -- Joe Condon, Bell Labs (via "Bumper Sticker Computer Science", in Programming Pearls)

https://tildesites.bowdoin.edu/~ltoma/teaching/cs340/spring0...

A very complex domain is medical records. The UK has managed to blow billions on custom systems that didn't work. The simplest thing that could have worked was maybe just to download an open source version of VistA (https://en.wikipedia.org/wiki/VistA). Probably would have worked better.
Wow, Chesterton’s fence parable could apply in so many places (not the least of which, politics).
> Anyone proclaiming simplicity just hasnt worked at scale.

The author of the article is a staff engineer at GitHub.

Okay, I'll bite.

> Anyone proclaiming simplicity just hasnt [sic] worked at scale

I've worked in startups and large tech organizations over decades and indeed, there are definitely some problems in those places that are hard.

That said, in my opinion, the majority of technical solutions were over engineered and mostly waste.

Much simpler, more reliable, more efficient solutions were available, but inappropriately dismissed.

My team was able to demonstrate this by producing a much simpler system, deploying it and delivering it to many millions of people, every day.

Chesterton's fence is great in some contexts, especially politics, but the vast majority of software is so poorly made, it rarely applies IMO.

staying kinda anonymous saying this... oftentimes for most programmers the road is a pretty simple one yet the fence or gate is a tolling station of some private interest, so yeah if possible just quit arguing and try to destroy it.
>Anyone proclaiming simplicity just hasnt worked at scale.

or they haven't worked in fields that are heavily regulated, or internationally.

This is why the DOGE guys were all like hey there are a bunch of people over 100 years old getting social security!! WTF!? Where someone with a wider range of experience would think, hmm, I bet there is some reason we need to figure out why they just jumped right to "this must be fraud!!"

For a lot of problems it’s a good idea to talk to customers and stakeholders, and make the complexity very transparent.

Maybe some of the edge cases only apply to 2% of the customers? Could these customers move to a standard process? And what’s the cost of implementing, testing, integrating and maintaining these customer-specific solutions?

This has actually been the best solution for me to reduce complexity in my software, by talking to customers and business analysts… and making the complexity very transparent by assigning figures to it.

You're not wrong, but I'm also constantly surprised at places where devs will inject complexity.

A former project that had a codec system for serializing objects that involved scala implicits comes to mind. It involved a significant amount of internal machinery, just to avoid writing 5 toString methods. And made it so that changing imports could break significant parts of the project in crazy ways.

It's possible nobody at the beginning of the project knew they would only have 5 of these objects (if they had 5 at the beginning, how many would they have later?), but I think that comes back to the article's point. There are often significantly simpler solutions that have fewer layers of indirection, and will work better. You shouldn't reach for complexity until you need it.

The classic comeback - every time I mention simplicity to a particular team member of mine, this is what he says. Complexity is unavoidable. Yes. But if you don't fight it tooth and nail, spend more time than you want trying to simplify the solution, getting second opinions (more minds on difficult problems are better!), then you will increase complexity more than you needed to. This is just a different form a technical debt: you will pay the price in maintenance later.
There is a lot of sentiment in these comments about needing to scale still. I wonder how many need to do this in a pre-PMF stage vs growth stage? The trade off is faster growth if your PMF bet wins and loss of time if your bet goes south.
Those who’ve worked at scale know simplicity is brutally hard — but those who stop pushing for it altogether have failed their responsibility.
As someone who has built 0-1 systems at multiple startups (Seed to Series C), I’ve settled on one principle above all else:

“Simple is robust”

It’s easy to over-design a system up front, and even easier to over-design improvements to said system.

Customer requirements are continually evolving, and you can never really predict what the future requirements will be (even if it feels like you can).

Breaking down the principle, it’s not just that a simple system is less error prone, it’s just as important that a simple architecture is easier to change in the future.

Should you plan for X, Y, and Z?

Yes, but counterintuitively, by keeping doors open for future and building “the simplest thing that could possibly work.”

Complexity adds constraints, these limitations make the stack more brittle over time, even when planned with the best intentions.

IMO, the most important thing about this sort of advice (and maybe most advice) is to treat it as a "generally useful heuristic, subject to refinement based on judgment" and not as an "ironclad, immutable law of the kingdom, any transgression from which, will be severely punished".

Sure, try to keep things simple. Unless it doesn't make sense. Then make them less simple. Will you get it wrong sometimes? Yes. Does it matter? Not really. You'll be wrong sometimes no matter what you do, unless you are, in fact, the Flying Spaghetti Monster. You're not, so just accept some failures from time to time and - most importantly - reflect on them, try to learn from them, and expect to be better next time.

Very much agree for the type of software I've worked on my whole career. I've seen way more time and energy wasted by people trying to predict the future than fixing bugs. In practice I think it's common to realize something didn't "possibly work" until after it's already deployed, but keeping things simple makes it easy to fix. So this advice also ends up basically being "move fast break things".
I agree with the spirit of the article, but I think the definition of "simple" has been inverted by modern cloud infrastructure. The examples create a false choice between a "simple but unscalable" system and a "complex but scalable" one. That is rarely the trade-off today.

The in-memory rate-limiting example is a perfect case study. An in-memory solution is only simple for a single server. The moment you scale to two, the logic breaks and your effective rate limit becomes N × limit. You've accidentally created a distributed state problem, which is a much harder issue to solve. That isn't simple.

Compare that to using a managed service like DynamoDB or ElastiCache. It provides a single source of truth that works correctly for one node or a thousand. By the author's own definition that "simple systems are stable" and require less ongoing work, the managed service is the fundamentally simpler choice. It eliminates problems like data loss on restart and the need to reason about distributed state.

Perhaps the definition of "the simplest thing" has just evolved. In 2025, it's often not about avoiding external dependencies. You will often save time by leveraging battle-tested managed services that handle complexity and scale on your behalf.

"When in doubt, use brute force." --Ken Thompson