Natty Hatty logo
← Writing

Essay Systems & Design

Complexity Is a Failure of Design

Complexity is usually mistaken for sophistication. It's more often evidence that the system was never finished.

Adit Agrawal
Adit AgrawalCo-Founder & CEO, Natty Hatty8 min read

8 min read

Complexity is usually mistaken for sophistication.

The bigger the company, the more processes it has. The more powerful the software, the more settings it needs. The more advanced the operation, the more people it takes to run.

We've learned to accept this as the price of doing anything serious. I don't think we should. Complexity is more often evidence that we stopped designing the system before we finished.

The measure of a sophisticated system isn't how much it can make you do. It's how much it can do without you.

Complexity accumulates quietly

Most systems don't start complicated. They become complicated one reasonable decision at a time.

A customer has a problem, so we add a feature. A team needs an exception, so we add a rule. Something goes wrong, so we add an approval. Information isn't available, so we add a report. Two systems don't talk to each other, so we put a person between them.

Every individual decision makes sense. Eventually the system as a whole doesn't.

More buttons. More settings. More documentation. More training. More dashboards. More people whose actual job is moving information from one place to another.

The problem isn't that each addition was wrong. The problem is that nobody went back and questioned the system itself.

The measure of a sophisticated system isn't how much it can make you do. It's how much it can do without you.
Adit Agrawal

Sports organizations are where this is easiest to see

I spend my time inside sports operations, and they're a near-perfect case study in accumulated complexity.

Registration lives in one place. Payments in another. Scheduling somewhere else. Teams, documents, commerce, communication — each in its own system, each of them working exactly as designed.

And the organization still runs inefficiently.

Consider what happens when a family registers a child for a fall program. Someone confirms the payment cleared. Someone checks whether the waiver was signed. Someone assigns the athlete to a team. Someone updates the roster the coach is working from. Someone makes sure the facility schedule reflects the new headcount. Someone emails the parent what happens next. When the family later changes a phone number, most of those systems never find out.

Nothing here is difficult. Every step takes a few minutes. Multiply it across a season and an organization has quietly built a full-time job out of copying information between products that should have known about each other from the start.

The real complexity doesn't live inside any of those products. It lives in the space between them.

Inherited processes disguise themselves as requirements

When something becomes complicated, the instinct is to improve what already exists. Make the process faster. Improve the interface. Automate a few steps. Add another integration.

All of that assumes the existing process is fundamentally correct.

First-principles thinking starts somewhere else. Strip the problem down to what must actually be true. What are we trying to accomplish? What is genuinely required? Which constraints are real, and which exist only because of decisions someone made years ago? Which steps would we never create if we were designing this today?

That last question does most of the work, because inherited processes are very good at looking like requirements.

We need this approval. Why? Because finance needs this report. Why? Because they need information from another system. Why isn't that information already available?

Keep going and you usually find that the workflow isn't solving the original problem at all. It's solving problems created by the architecture around the problem.

That's the moment redesign becomes possible.

Some complexity is necessary. Real systems operate under real constraints. But "that's how we've always done it" isn't a constraint. It's history. And history shouldn't get to dictate architecture.

The best workflow is the one that doesn't exist

Imagine a process with twelve steps. You could spend months making every step faster: better interfaces, fewer clicks, automated notifications, AI assistance. Maybe you cut the time in half. That's genuinely valuable.

But there's a better question. Do all twelve steps need to exist?

If eight can be removed entirely, you haven't built a faster workflow. You've built a smaller problem.

This is the principle I keep returning to, and it's the one most often skipped: never optimize something before proving it deserves to exist. Once a process becomes fast, people stop asking why they're doing it.

The same trap sits inside automation. Automation doesn't automatically produce good systems — it can just as easily make a bad system run faster. If five approvals aren't necessary, automating five approvals doesn't fix anything. If employees spend their days moving information between two systems, an integration helps, but the deeper question is why those systems were ever disconnected. If customers need a tutorial to complete a basic action, the interface is wrong.

So before automating anything, I ask three questions in order:

Does this need to happen? If it does, does a person need to make it happen? And if a person does, what's the minimum effort we should require from them?

Only then is automation the right tool. Otherwise we're using technology to preserve complexity instead of removing it.

Every handoff is a coordination tax

Complexity doesn't only live in interfaces. It lives in dependencies.

A customer changes their information. One system knows. Another doesn't. An employee spots the discrepancy and updates the second system. Someone gets an email. A spreadsheet changes. Another department eventually hears about it.

Technically, everything worked. Architecturally, something is wrong.

Every manual handoff is another opportunity for delay, misunderstanding, and failure. I call this the coordination tax. It doesn't appear on any budget line, which is exactly why it goes unexamined for years. It shows up instead as headcount, as slow response times, as the vague sense that everything takes longer than it should.

The clearest sign of poor system design is when people exist primarily to connect processes. Download this file. Upload it there. Copy this number. Email that department. Check whether they replied. Update the spreadsheet. Change the status. Notify the customer.

None of these actions are difficult. That's precisely why they survive. But thousands of tiny actions compound into enormous operational friction, and nobody can point to the moment it became a problem.

Humans are extraordinary at judgment, creativity, relationships, and decisions where the answer isn't obvious. Humans are an extraordinarily expensive way to move structured information from one database to another.

Information should move because the system understands where it belongs, not because someone remembered to move it. People shouldn't compensate for architecture. Architecture should enable people.

Complexity belongs inside the system

Simplicity gets misunderstood. Simple doesn't mean basic. It doesn't mean stripping out powerful capability, and it doesn't mean software that only works for simple businesses.

Some of the best-designed systems in the world are extraordinarily complicated underneath. The difference is that the user never has to manage that complexity.

Think about turning on a light. Behind that switch sits power generation, transmission, distribution, transformers, decades of electrical engineering, and countless safeguards. You think about none of it. You flip a switch.

The complexity didn't disappear. The system absorbed it.

That distinction is fundamental to how I build: complexity belongs inside the system, not on the user. The sophistication should be underneath. The simplicity should be what people experience.

The same principle applies to edge cases. It's tempting to accommodate everything: an option for this, a setting for that, a toggle for the unusual scenario. Eventually most users are navigating complexity built for a small minority of situations. Edge cases matter, but they shouldn't define the experience. The normal path should be obvious, and the system should absorb as much of the exception as it safely can. If a user has to understand the entire architecture to accomplish one task, we've transferred the designer's job to the user.

Scale reveals architecture

There's a common belief that complexity is simply the price of growth. I disagree. Scale usually reveals complexity that was already there.

A process requiring five minutes of manual work doesn't feel broken when it happens twice a week. When it happens twenty thousand times, you suddenly need a department.

The natural response is to hire. Sometimes that's right. But there's a question worth asking first: why does this require a person at all?

If every increase in volume demands a proportional increase in operational effort, the system isn't creating leverage. It's creating a larger operation. Good systems behave differently — volume can rise dramatically without effort rising at the same rate. That's one of the fundamental promises of technology, and most software quietly fails to deliver it.

The system should know more

For decades, software has mostly waited for instructions. Click this. Select that. Enter this. Confirm. Save. Submit. Repeat.

But systems increasingly have context. They know what happened previously. They understand relationships between information. They hold permissions, schedules, transactions, dependencies, and history. For the first time, AI makes it practical for systems to act on that context, not just store it.

That changes what software can be. Instead of only asking what did the user tell the system to do, we can ask what should happen next. If the answer can be determined safely and confidently, the system should handle it.

Go back to that fall registration. A registration shouldn't only create a registration. The system should understand what the registration means. Who registered. What they purchased. What program they're joining. What's owed. What needs signing. Where they need to be. Who needs to know. What happens next.

Those aren't eight unrelated workflows. They're consequences of a single event. The architecture should understand that.

This is why the future of sports technology isn't more software. It's infrastructure — a layer organizations operate on rather than manage.

The ultimate interface may not be a better dashboard. It may be needing the dashboard less often.

Subtraction is harder than addition

Adding something is easy. Removing something requires understanding.

You need to know why it exists. What depends on it. What breaks without it. Whether another part of the system can absorb its responsibility.

That's why simplicity is difficult. It demands going deeper than the interface — you have to understand the architecture well enough to remove complexity without removing capability.

The goal isn't minimalism. The goal is maximum capability with minimum unnecessary effort. That's a much harder standard.

The world isn't becoming less complicated. Businesses aren't getting simpler, sports organizations aren't getting simpler, and the systems underneath all of it will keep getting more sophisticated. That's inevitable. But sophistication and complexity aren't the same thing.

The job of good architecture is to absorb the sophistication and shield people from the complexity. When that happens, organizations don't just get faster. They get easier to run. People spend less time managing systems and more time doing work that actually requires a person. Customers never see the machinery. And growth stops requiring another layer of operational friction.

That's the standard I'm building toward.

Complexity is easy to create. Simplicity has to be designed.

Share this essay

← All essays