Why Software Architecture Isn't About Patterns (And What Actually Works)
The Pattern Trap
Let's be honest: if you've been in software development for more than a few years, you've probably sat through an architecture review where someone pulled out a pattern catalog like a waiter presenting a menu. "We could use a Factory here. Maybe a Strategy pattern there. Have you considered CQRS?"
This isn't architecture. This is pattern-matching masquerading as engineering.
A thought that keeps surfacing in developer communities captures this perfectly: great software architecture emerges from modelling the problem itself, rather than trying to shoehorn the problem into a predefined set of patterns. The best developers learn how to use their tools, understand their materials, and then follow their vision—rather than reaching for cookie cutters that obscure the obvious solution sitting right in front of them.
Why Are Web Dev Resources Everywhere, But Systems Programming Architecture Is Hard to Find?
If you want to learn about microservices, container orchestration, or distributed systems in the web context, congratulations—you're drowning in resources. But what if you're building a compiler, an embedded system, a game engine, or a database?
The landscape changes dramatically.
Most "software architecture" content today focuses on the concerns of web-scale applications: horizontal scaling, service discovery, eventual consistency, and the organizational challenges that come with large engineering teams. These are legitimate problems, but they're not universal problems.
For systems programmers and non-web developers, the vocabulary shifts. You're thinking about:
- Memory layout and access patterns
- Latency guarantees and real-time constraints
- Resource-constrained environments
- Formal verification when correctness is critical
- Building for decades of maintenance, not just the next sprint
The challenge is that good resources for this world are scattered, often academic, and rarely frame themselves as "architecture" even when they absolutely are.
What Actually Helps: Mental Models Over Patterns
Rather than another pattern catalog, here are the mental frameworks that have proven most valuable for building robust systems, regardless of whether you're writing embedded C or enterprise Java:
1. Constraints First
Every system exists within constraints: budget, time, team size, performance requirements, regulatory environment. The architecture that emerges from deeply understanding your constraints will always outperform the "correct" architecture that ignores them.
2. Data Flow as the Foundation
Before you think about classes, modules, or services, understand how data enters your system, transforms, and exits. Architecture often becomes obvious once you map this clearly. Weird abstractions fall away; necessary ones become clear.
3. Dependency Ownership
Who owns this data? Who can modify this state? Clear answers to these questions prevent most architectural messes. The confusion around ownership—data ownership, in particular—is where most systems start to rot.
4. The Cost of Indirection
Every abstraction has a cost. Every layer of indirection makes debugging harder and performance harder to reason about. The question isn't "should I abstract this?" but "what am I buying with this abstraction, and is it worth the price?"
5. Locality of Behavior
Code that's easy to understand in isolation, that doesn't require you to hold three files in your head simultaneously, is code that will survive the next five years of maintenance. Architecture that creates cognitive overhead will eventually be simplified—often by someone who doesn't understand why it was built that way.
Recommended Resources (The Non-Web Kind)
If you're looking to deepen your architecture thinking without falling into the web-scale pattern rabbit hole, consider:
"A Philosophy of Software Design" by John Ousterhout — This remains one of the clearest thinking on complexity management in software systems. It's language-agnostic and deeply practical.
Papers on operating systems and distributed systems from the academic literature, particularly those predating the microservices era. Papers on file system design, for instance, contain architectural wisdom applicable far beyond file systems.
Reading the source code of well-designed systems — This sounds obvious, but most developers don't do it systematically. Understanding how databases, compilers, and well-engineered open-source projects solve hard problems will teach you more than any pattern book.
The Art Behind the Science
Here's the uncomfortable truth: software architecture is more art than science, and that's not changing.
We can talk about principles and heuristics. We can measure coupling and cohesion. We can create models and diagrams. But ultimately, architecture reflects the judgment of the people building the system—their ability to see the problem clearly, their experience with what tends to go wrong, and their skill at making trade-offs that serve real-world needs rather than theoretical ideals.
The developers who build the best systems tend to share a common trait: they're deeply curious about the problem domain, not just the technology. They ask "why is this hard?" before asking "what pattern should I use?"
Start there. Understand your problem deeply. Let the solution emerge. And when someone tries to sell you a pattern as architecture, ask them what problem it solves—and whether that problem actually exists in your system.