Why Software Architectures Break
Fixing Cognitive Debt with Lateral Thinking
Reading Lateral Thinking, by Edward de Bono, was an epiphany which made me reflect on education and software engineering.
If you, like me, struggled accepting a single point of view, whether it came from school, your parents, or your working environment. If there were times where you thought that the “official” way wasn’t the only way. If you had your alternative ideas quickly dismissed. Then, take a deep breath and feel the relief of knowing that there was nothing wrong with you. You have been in environments that lacked Lateral Thinking.
Traditional education reinforces cognitive biases and patterns which can limit creative thinking and problem solving. Once you get familiar with Lateral Thinking you start wishing for an educational system where different ways of thinking are welcomed.
Understanding how our minds work gives us a clearer view of where and why software engineering fails, and how to deal with it.
Understanding the Pattern-Matching Mind
To understand why your software designs fail, you must first understand how your brain is wired.
The human brain is a self-organizing, pattern-matching system.
Imagine a perfectly smooth surface of warm wax. If you pour a drop of hot water on it, the water runs off, leaving a shallow path. If you pour more water, it naturally finds that existing path and deepens it. Over time, a deep channel forms. From that point on, any water you pour on the surface will instantly run into that same channel, regardless of where you pour it.
This is how the self-organizing, pattern-matching system of your mind works. Every time you experience a situation, learn a concept, or solve a problem, your brain marks a mental path. This allows you to quickly and efficiently recall information when you encounter similar situations.
In the book Thinking, Fast and Slow, by Daniel Kahneman, mind is described as two systems:
- System 1 (The Pattern Engine): is a fast, automatic, and subconscious retrieval system. It runs on minimal energy, instantly matching current events to historical patterns.
- System 2 (The Logical Engine): is a slow, deliberate, step-by-step reasoning circuit.
When designing a system you think that your choices are driven entirely by logic, but in reality your logic is bounded by the patterns in your mind!
If the automatic pattern-matching behavior of your mind defaults to a microservices setup, because it was exposed to it over the last years. Then your logical mind immediately focus on how to build that microservice. Your logical mind never questions whether a microservice is the right fit in the first place. This is the modus operandi of Vertical Thinking which you were trained for.
In Vertical Thinking, you select the best option at each individual step. You follow deductive, rational links to narrow down the scope until you reach a solution. It is highly efficient, but it has a blind spot: it assumes you already have all the necessary information and that your initial starting point is correct.
In Lateral thinking, by contrast, you don’t seek the “correct” next step. You look for a restructuring of the available information, to break out of established patterns.
If vertical thinking is about digging the same hole deeper, lateral thinking is about realizing you need to dig a new hole somewhere else (or no hole at all).
To help break these rigid mental patterns you can use the following tools:
- Challenging Assumptions: ask “why” to create the healthy discomfort of explanation. If you assumed that a system needs a relational database, ask what if we remove that assumption? What alternative designs become possible?
- Reversal: take a standard situation and look at its exact opposite. Instead of pulling data from a server, what if the server pushes the data?
- Generating Alternatives: force yourself to identify three different approaches to a problem, even if the first one seems absolutely perfect.
- Provocation (Random Stimulation): introduce a completely unrelated concept or constraint to trigger a new chain of thoughts. Explore how something is done by a different company in a different industry.
The Real Danger is “Blockage by Adequacy”
One of the most profound concepts that makes you fail silently and unknowingly is Blockage by Adequacy.
This is the state where you already have a perfectly adequate solution to a problem: it works, it passes the tests, and it does the job. Because the solution is adequate, you experience no friction. And because there is no friction, you stop looking for any other way to do it.
The brain is highly optimized to fix things that are visibly broken, but we have almost no natural instincts for reassessing things that are currently working.
In practice there is nothing wrong with adequate solutions. In a fast-moving business, delivering a “good enough” design is often the smartest trade-off you can make. It gets the product to market, validates user demand, and keeps the company alive.
The real danger is that you forget it was a merely adequate solution!
Today you write a synchronous REST endpoint, as a default solution, because it is quick and you are urged to. The solution works. It is adequate. Then you get busy, you move on to new features, and you forget checking on that decision. Later, that temporary “good enough” approach keeps spreading all over the system, until the system becomes unusable: long chains of synchronous calls with response times of seconds. The system fails because you neglect to reassess that the initial compromise.
This is the origin of Cognitive Debt in software development.
Cognitive debt is the accumulation of forgotten assumptions and “temporary” mental models in your codebase. It lies silently and undisturbed until a production outage happens.
Typically Technical Debt, i.e spaghetti code or missing tests, is a symptom of Cognitive debt. When you start spotting technical debt, you should step back and look at the whole system to find the root cause.
Applying Lateral Thinking: Continuous Reassessment
In complex software environments you can’t rely on people remembering to be creative or hoping to find the spare time to question their assumptions. You need to embrace a culture that makes reassessment a natural, continuous, and automated part of the engineering lifecycle.
Get Angelo Buono’s stories in your inbox
Join Medium for free to get updates from this writer.
You should find your way of applying the cognitive concepts of Lateral Thinking to Software Engineering practices, for example:
- Challenging assumptions could done by applying Chaos Engineering: break things deliberately to see how the system behaves when its baseline assumptions are shattered.
- Generating alternatives could be helped with AI Coding Agents: ask LLMs for radically different alternative designs and evaluate trade offs.
- Overcoming blockage could be addressed with Architectural Fitness Functions: turn architectural rules into unit tests (e.g. ArchUnit) to ensure they stay relevant.
Combining the DevOps philosophy, of automation and observability, with the Lateral Thinking purpose, of reshaping information to bring insight, is the key to build Software that doesn’t fail unexpectedly.
Imagine a CI/CD pipeline that actively audits the system’s health across multiple dimensions, such as:
- Maintainability: analyzing code structures, dependency boundaries, and domain isolation to flag where tight coupling is introduced.
- Security: scanning for configuration drifts, and checking dependency vulnerabilities to report wrong assumptions about the attack surface.
- Performance: comparing performance metrics, latency percentiles, and database connections against historical baselines to catch gradual performance decay before it becomes an incident.
- Privacy: scanning logs and data flows to ensure sensitive customer data isn’t leaking into unencrypted storage.
The Declarative Future: Spec-Driven Reconciliation
With AI coding agents speeding up coding, the primary bottleneck in engineering is shifting to conscious design, domain modeling, and continuous governance.
Software engineering is slowly moving towards a paradigm of Spec-Driven Architecture, where specifications and decisions are first class citizens.
Engineering practices need to adapt and build around specifications and decisions, similarly to what DevOps do with Infrastrcture-as-Code.
Think about how GitOps platforms like Kubernetes and ArgoCD operate. You write a Spec — a declarative document that describes your desired state (e.g., “I want three instances of this container running, with this much memory, connected to this network”).
Once you apply that spec, a continuous reconciliation loop takes over. It constantly observes the actual state of the deployment, compares it to the desired state, and triggers automated actions or alerts if there is a drift.
Software Engineering should bring this declarative reconciliation model to software design and development.
Under a Spec-Driven Architecture, your primary job as engineer will be to write and maintain the desired state of your system’s architecture. You will declare design rules, boundaries, and performance expectations in living documentation and automated configurations.
CI/CD pipelines and observability tools act as your continuous reconciliation loop. They constantly probe the actual codebase and runtime environment against those assumptions.
Conclusion
Your mind is beautifully optimized to find patterns and stick to them. While this keeps you efficient, it also leaves you vulnerable to the slow and silent accumulation of cognitive debt. You build “adequate” solutions, get comfortable, and forget to ever look back at them.
By bringing the principles of lateral thinking into your engineering workflows, you can protect yourself from your own cognitive biases. You don’t need to avoid simple, pragmatic designs; you just need to stop neglecting them once they are built.
You can build systems that stay clean, adaptive, and resilient over time by leveraging automated architectural tests, continuous observability, and declarative specs.
Recommended Books
- Lateral Thinking by Edward de Bono
- Thinking Fast and Slow by Daniel Kahneman
- Building Evolutionary Architectures by Neal Ford, Rebecca Parsons, Patrick Kua
- Clean Architecture by Robert C. Martin
I’ve been exploring Clean Architecture principles and best practices in JDKCertsTool, a CLI utility for managing certificates across JDK truststores. Star the repository and try out the tool. Any feedback is welcome.









