The Tar We Swim In
Before we solve complexity, we have to see it.
It’s not always crashes or outages. More often, it’s the subtle drag. The extra time to onboard. The bug you sort of fix, but don’t fully understand. That slow dread when a task should be easy — but never is.
“Out of the Tar Pit” names what many of us felt but couldn’t pin down: complexity is everywhere, and most of it didn’t need to be. It’s not always legacy. It’s often us. Our choices. Our habits.

Ambient complexity isn’t always visible — but it drags on every decision.
We build clever things that are hard to change. We move fast but struggle to remember why a thing was done a certain way. And when someone leaves, their knowledge evaporates — but the complexity stays.
The tar isn’t just technical. It’s psychological. Cultural. Invisible. That’s what makes it dangerous.
And that’s where this paper starts: with a warning — and a map.
A Quiet Revolution in Thinking
No fanfare. No product launch. Just a PDF floating around obscure forums.
But for some of us, Out of the Tar Pit hit like a truth bomb.
It questioned what counted as “hard.” It poked at our mental models. It said out loud what a lot of us had whispered: we’ve made this harder than it needs to be.
This was 2006 — pre-microservices, pre-cloud-native, peak enterprise Java. Systems were fat. Abstractions were bloated. The industry was still recovering from the false comfort of UML and the design-pattern industrial complex.
flowchart LR OO["Object-Oriented Boom<br/>(1980s–1990s)"] SOA["Service-Oriented Architecture<br/>(early 2000s)"] TARPIT["📝 Out of the Tar Pit<br/>(2006)"] MICROSERVICES["Microservices Rise<br/>(2010s)"] OO --> SOA --> TARPIT --> MICROSERVICES classDef paper fill:#fff3cd,stroke:#f0ad4e,stroke-width:2px class TARPIT paper
Out of the Tar Pit lands in 2006 — not another architectural trend, but a critique of all of them.
But the ideas weren’t angry or loud. They were clear. Which made them even harder to ignore. The authors weren’t selling anything. They were trying to understand something. And that made the paper stick.
It didn’t chase fashion. It chased sense.
What We Talk About When We Talk About Complexity
The core move the paper makes — and it’s a big one — is splitting complexity into two camps:
- Essential complexity: the real-world mess you can’t avoid.
- Accidental complexity: the extra mess you chose to add.
It’s a brutal distinction. And once you see it, you can’t unsee it.
Why does this API take 40 lines to call? Why do I need to understand a build tool to write a test? Why is the same data in four different places?
Complexity Type | Definition | Example |
---|---|---|
Essential | Inherent to the domain | User authentication |
Accidental | Introduced by tools/design | Boilerplate from a leaky abstraction |
Most of the pain isn’t in the problem. It’s in how we chose to model it.
The paper doesn’t scream about it. It just… opens a door. And quietly points to the mud we tracked in ourselves.
State, Control, Volume: The System’s Shadow
This is the paper’s most enduring frame: state, control, and volume — the “Unholy Trinity” of accidental complexity.
Most systems don’t fall apart because the logic is wrong. They fall apart because no one can hold the whole thing in their head anymore. State leaks. Control jumps. Volume obscures.
- State makes systems hard to predict.
- Control flow makes them hard to trace.
- Volume makes them hard to see.
Each one compounds the others. You add a flag. Then you add a check for that flag. Then another flag for the special case. Soon, the logic isn’t complex. It’s fragile.
This lens doesn’t just explain complexity. It predicts it.
Decomposition as Discipline, Not Convenience
We love the word “modular.” But most of the time, we confuse cutting things up with cleaning them up.
Tar Pit shifts the conversation. It says: don’t just break things into parts — break them at the right seams. Don’t just isolate functionality. Isolate effect.
That’s harder than it sounds. It means understanding what changes. What mutates. What triggers what. It means reasoning before writing.
Think of how a kitchen works. You don’t just dump all tools into one drawer. You group by use, by cleanliness, by safety. Systems need the same care.
flowchart LR subgraph Entangled["Entangled System"] direction TB EA["Component A"] EB["Component B"] EC["Component C"] EState["Shared State"] EA --> EB EB --> EC EC --> EA EA -->|state| EState EB -->|control| EState EC -->|data| EState end subgraph Clean["Isolated Components"] direction TB Input["Input"] SA["State Handler"] SB["Control Logic"] SC["Data Transform"] Output["Output"] Input --> SA --> SB --> SC --> Output end Entangled --Decomposition--> Clean
Side-by-side systems: one overwhelmed by cross-cutting concerns, the other built on isolated, single-responsibility components.
Decomposition is a discipline. And it’s the key to building systems that don’t rot under their own weight.
Functional–Relational Thinking: Clarity by Constraint
The technical heart of the paper is this combo: pure functions + relational data.
It sounds modest. But together, they change how a system feels to use, debug, and trust.
Pure functions don’t lie. They’re predictable. You give them the same inputs, they give you the same outputs. That’s not just good engineering — it’s a gift to your future self.
Relational models? They let you query, not crawl. You don’t need to write imperative loops to “find the thing.” You just ask for what you want.
Ingredient | Why It Matters |
---|---|
Pure Functions | Testable, composable, no surprises |
Relational Data Model | Declarative, transparent |
Immutable State | Fewer hidden dependencies |
This isn’t about academic purity. It’s about aligning your system with how humans think. It’s about making errors obvious, not buried.
And when things are obvious, you fix them faster. You onboard faster. You trust your system more.
That’s what functional–relational thinking buys you: not dogma — clarity.
Why Simplicity Scares Us
You’d think we’d want simplicity. But we run from it.
Not because we love pain — but because simplicity feels risky. Like it won’t scale. Like it’s not “enterprise-ready.” Like it won’t impress the next job interviewer.
We’ve been taught to equate complexity with capability. More knobs must mean more power. More code must mean more flexibility.
But simple isn’t fragile. It’s focused. And focus takes guts.

When clarity feels suspicious — and complexity looks more realistic.
Out of the Tar Pit doesn’t sell simplicity as a virtue. It frames it as an act of courage. To be clear. To be boring. To make fewer things possible — but make those things understandable.
Simplicity doesn’t fail silently. Complexity does.
The Cultural Inertia of Complexity
Even when we can build simple systems, we often don’t. Why?
Because complexity is rewarded. Not explicitly, but through the back door.
You get praise for fixing the hard bug, not avoiding the design that caused it. You get promoted for rescuing a broken deploy, not for writing a system that doesn’t need rescuing.
Tar Pit quietly calls that out. It says: the problem isn’t just code. It’s culture.
flowchart TD Incentives["🏆 Incentives<br/>(Deadlines, Promotions, KPIs)"] Design["⚙️ Design Choices<br/>(Speed over Clarity)"] Complexity["🧩 Accidental Complexity"] Hero["🦸 Hero Culture<br/>(Reward firefighting)"] Incentives --> Design --> Complexity --> Hero --> Incentives
How short-term incentives drive long-term mess — and reward the people who clean it up instead of the ones who prevent it.
Teams optimise for the wrong thing — velocity, generality, short-term reuse. And so the software ends up reflecting not the problem, but the org chart, the politics, the KPIs.
Changing that takes more than refactoring. It takes leadership. Taste. Patience.
The System as a Story
Here’s the real magic: systems that make sense feel like stories.
There’s an entry point. A path. A logic. A conclusion. You don’t get lost because the structure leads you somewhere.
The best software is narratable. You can explain what happens and why — without resorting to tribal knowledge or, “Yeah it’s weird but it works.”
flowchart TD Input["📥 Input Arrives"] Transform["🔧 Transformation Happens"] Output["📤 Output is Logged"] Explain["🧠 A Human Can Explain the Flow"] Input --> Transform --> Output --> Explain
From input to insight — systems that tell a story are easier to trust, debug, and evolve.
Out of the Tar Pit doesn’t teach storytelling. But it forces you to value it. Because if your system can’t be explained clearly, it’s already in trouble.
Code is written once. It’s read a hundred times. It needs to make sense — to others, to you next week, and to someone new five years from now.
Simplicity isn’t just kindness. It’s future-proofing.
Building Systems That Don’t Fight You
If your system still surprises you — it’s not done.
If juniors are scared to touch a part of the codebase — it’s not done.
Out of the Tar Pit doesn’t offer a checklist. It offers a mindset. One that treats clarity as a constraint. One that assumes your future self — or your future teammate — matters just as much as the one shipping the feature today.

Friendly systems guide you through the flow. Hostile ones make you guess.
The real question it leaves us with is simple:
Are we building systems that help people think — or systems that punish them for trying?
The answer won’t come from a new tool. It’ll come from taste. From caring. From small choices, made with big intent.
Epilogue: Respect Attention, Support Change, Earn Trust
We don’t escape complexity by avoiding work. We escape it by doing the right kind of work.
Design that respects human limits. Interfaces that reward curiosity. Code that doesn’t lie.
This paper didn’t just critique our systems — it offered us a way out. Not easy. But clear.
“Software complexity is an enormous problem — perhaps the problem in the software industry.”
— Moseley & Marks, 2006
Thanks to Ben Moseley and Peter Marks for the map.
Let’s keep walking.