The Law of Leaky Abstractions & the Unexpected Slowdown – AB's Reflections

Software development can be viewed as a steady climb toward higher levels of abstraction. Over time, programming has evolved from low-level assembly code to high-level languages, then to low-code and no-code platforms, and now to systems where developers can generate software through natural language prompts with AI.

The goal behind this progression has been clear: make software creation faster, easier, and accessible to more people. Businesses want shorter development cycles, and organizations need a broader workforce capable of building digital systems.

But this convenience comes with a hidden cost.

The Problem With Abstractions

Programmer Joel Spolsky famously described the Law of Leaky Abstractions. The idea is simple: whenever a system hides complexity behind a simplified interface, that complexity eventually leaks through.

No abstraction is perfect. At some point, developers must deal with the underlying details that the abstraction tried to hide.

However, focusing only on the technical limitations misses something important—the human impact of abstraction.

What Is Cognitive Leakage?

When tools hide complexity, developers no longer need to fully understand the systems they’re working with. This creates what could be called cognitive leakage.

Cognitive leakage occurs when abstraction removes the need to engage deeply with technical details. As a result, developers may complete tasks without truly understanding how the system works.

In the short term, this may seem efficient. But over time, it reduces what we might call cognitive sovereignty—the ability to understand and control the technology we rely on.

Without that understanding, both individuals and teams can struggle when systems become more complex or start to fail.

The Problem of Undigested Complexity

The consequences of cognitive leakage often appear in large software systems.

Take technical debt, for example. It’s rarely just a matter of outdated technology that needs updating. More often, the real issue is accumulated complexity that developers no longer fully understand.

As systems grow and new layers of abstraction are added, hidden details start leaking out. Developers then face a difficult challenge: figuring out how the system actually works.

In many cases, the hardest part isn’t making changes—it’s understanding what’s already there.

Two Ways Teams Handle Complexity

When building or maintaining software, teams typically take one of two approaches.

Cognitive shift left

This approach tackles complexity early in development. Developers invest time in writing clear code, creating tests, and modeling systems carefully.

It requires more effort upfront but builds deeper understanding within the team.

Cognitive shift right

Here, teams rely heavily on encapsulated tools or black-box systems that hide complexity. Development appears faster, and early costs are lower.

However, the complexity hasn’t disappeared—it’s simply postponed.

Over time, this hidden complexity accumulates in the system.

When Complexity Finally Surfaces

Undigested complexity eventually reveals itself in various ways:

  • Persistent bugs during testing

  • Unexpected production failures

  • Systems so complicated that no one wants to modify them

Eventually, the software becomes what developers often call a “ball of mud” architecture—a tangled system that’s difficult to understand and risky to change.

At this stage, the organization faces a major problem: the cost of understanding the system has become extremely high.

Why Refactoring or Rewriting Often Fails

When teams encounter messy systems, they usually debate two options:

  • Refactoring the existing code

  • Rewriting the system from scratch

Yet many organizations struggle with both approaches. Refactoring efforts stall, while rewritten systems sometimes devolve into the same chaotic structure.

One reason is system entropy—software naturally becomes more complex over time. But cognitive leakage accelerates this process.

As abstraction increases and understanding decreases, teams lose the knowledge needed to maintain or evolve the system properly.

Organizational Challenges

As software systems grow, organizations often respond with quick fixes:

  • Hiring more developers

  • Introducing new performance metrics or KPIs

Unfortunately, these strategies can make the problem worse.

Adding new developers increases communication overhead and introduces people who lack deep knowledge of the system. Even experienced engineers need time to build mental models of complex architectures.

Similarly, new KPIs may encourage superficial productivity while discouraging the deeper analysis required to address architectural problems.

Over time, this leads to organizational memory loss—teams forget why the system was built the way it was.

The Hidden Cost of Convenience

Eventually, teams must confront the accumulated complexity through refactoring or rewriting.

But the challenge is greater than simply writing new code. Developers must rediscover lost logic, requirements, and design decisions.

In other words, they must repay the cost of cognitive leakage.

This process includes:

  • Rebuilding test coverage that disappeared over time

  • Restoring system understanding

  • Reconstructing missing documentation and architecture knowledge

Only then can teams regain control of the system.

Are Abstractions Always Bad?

Not at all. Modern software would be impossible without abstraction.

High-level languages such as C++ and Java hide hardware details while still requiring developers to understand system behavior.

Abstractions become problematic when they completely remove the need for critical thinking.

This risk is particularly visible with:

  • No-code platforms

  • Highly automated development tools

  • AI-generated code

In these cases, developers may produce working systems without engaging deeply with the underlying problems.

Software Inflation and “Zombie Systems”

When complexity accumulates faster than understanding, systems enter a dangerous state.

Developers can no longer easily break down problems or modify the architecture. The software still runs, but no one truly understands it.

These are sometimes referred to as “zombie systems”—software that continues to exist but is nearly impossible to evolve safely.

Protecting Cognitive Sovereignty

The solution isn’t rejecting abstraction altogether. Instead, teams must balance convenience with understanding.

Some practical strategies include:

  • Enforcing thorough code reviews, especially for AI-generated code

  • Maintaining strong testing practices

  • Ensuring low-code tools remain within the team’s ability to understand

  • Encouraging developers to examine underlying system behavior

These practices help maintain cognitive alignment across teams and prevent complexity from slipping out of control.

A Final Thought: Always Ask the Cost

Every time you use a black-box tool, copy and paste code, or rely on automation, it’s worth asking a simple question:

What is the cost of this convenience?

Sometimes the answer will be minimal, and the abstraction will be worth it. But sometimes that convenience quietly accumulates technical and cognitive debt.

In a world increasingly shaped by AI-assisted development and layered abstractions, maintaining cognitive sovereignty—the ability to understand the systems we build—may be one of the most valuable skills developers can keep.