Software Architecture Is a Building - A Mental Model for Technical Decisions

Most architecture discussions devolve into abstract debates about microservices, monoliths, and database choices. After years of explaining these concepts to engineers and product leaders, I've found that thinking about software architecture like a physical building cuts through the noise and makes the tradeoffs viscerally clear.

This isn't just a teaching metaphor. It's a decision framework that surfaces why some changes cost weeks and others cost months, why certain tech debt compounds silently while other debt screams at you daily, and how to gauge the right amount of architectural runway to build.

The Building Metaphor

Picture an office building. Your software system maps to its construction layers.

Foundation: Your database structure, message queue infrastructure, and core data models. These are the concrete and rebar that everything else sits on. Get this wrong and you're looking at foundation repair, which is exactly as expensive and disruptive as it sounds.

Support Pillars: Your domain objects and APIs. These structural elements carry the load between your foundation and the usable spaces above. They define what's possible to build efficiently.

Floors and Rooms: Your features and product capabilities. Floors connect different models together. Rooms are what you build on top of that. This is where work actually gets done.

Paint and Finishes: Your UI, user experience, and visual design. This is the coat of paint that users actually see and interact with.

Entry Points and Flow: Your user journeys. How do people enter the building? How do they navigate between rooms? Think of doors as page redirects. A well-designed building lets people come in, find what they need, and exit efficiently. This emulates B2B applications better than B2C (which let's people come in and keeps them there).

Different user types have different entry points. Your front door is your main application flow. Your back door might be an admin interface or an alert that drops someone directly into a monitoring dashboard. Users come in, grab the tool they need for a specific job, and leave. All of these entry points should be built on the same stable foundation.

Building on a Slant

Here's where the metaphor gets useful. What happens when your product evolves in directions your foundation wasn't designed for?

You start building on a slant.

Imagine you have data tables designed for one purpose, but now you need to query them in weird ways to support a new feature. You write complex SQL that joins across tables in ways they weren't optimized for. You build a UI on top of that. You're now constructing rooms that extend out past your foundation's edge.

This is sometimes necessary. Products evolve. Requirements change. You can't anticipate everything. But building on a slant creates two distinct problems, and understanding the difference matters for prioritization. Much of the operational chaos teams fight through stems from these architectural decisions, which is why upstream root cause investigation focuses on the layers beneath the symptoms.

The Gap Under the Overhang: Active Tech Debt

The first problem is the gap under the building you've constructed. You've built something precarious, extending past your foundation with nothing solid below it. This is active tech debt, the kind that causes problems you feel every day.

Performance issues. Operational complexity. Application code doing gymnastics to compensate for a missing foundation. Database CPU spiking because you're running queries against data structures that weren't designed for those access patterns.

The solution most teams reach for is filling in the gap with concrete. They denormalize data into another table or database that's optimized for these queries. They build a pillar up from below to support the overhang. But this is patching, not solving. The application wasn't built for this originally.

The ideal fix is sliding the foundation over to be under what you've built. But that's hard. It means rethinking your data model, migrating data, updating APIs. So teams tend to keep scaffolding, keep patching, and keep incurring operational overhead. The signal to stop patching is when the operational overhead of maintaining workarounds exceeds the cost of doing the foundational work properly.

This tech debt screams at you. Performance alerts fire. Engineers complain about slow queries. Users notice laggy features. You feel this debt daily.

The Gap Above the Foundation: Passive Tech Debt

The second problem is the gap above the foundation that's no longer used. You have solid structural support, maybe even APIs and domain objects, but nothing sits above them anymore. No rooms. No users. No value.

This is passive tech debt. Nobody actively complains about it. No alerts fire. The code just sits there, maintained by inertia.

But it's still debt. You're still holding onto that data. You're still running those services. When you refactor adjacent code, you have to consider whether it touches these unused components. Your test suite runs against them. Your documentation (if you have any) includes them.

Ideally, you'd demolish the unused room. Delete the APIs. Drop the tables. Stop maintaining code that delivers no value. But passive debt rarely gets prioritized because it doesn't hurt. It just weighs you down slowly, like a building with rooms nobody enters but someone still has to clean.

Gauging Architectural Runway

Given that products evolve unpredictably, how do you decide how much foundation to build ahead of where you are today?

Build too close to current needs and you're constantly in construction mode, adding foundation under features as you go. Every new capability requires structural work.

Build too far ahead and you're speculating about future requirements. You might build foundation that turns into passive tech debt because the product took a different direction.

Both approaches carry risk. The skill lies in developing intuition for when to extend your foundation, how much to extend it, and in which direction. The Risk Funnel covers this from a project perspective: teams that address architectural assumptions early eliminate risk before it compounds, while teams that defer uncertainty until late stages face catastrophic rewrites.

This is why architecture decisions can't happen in isolation from product strategy. The right amount of runway depends on where the business is going, not just where the code is today. A feature that's experimental requires less foundation investment than a feature that's core to your growth strategy.

Even recognizing when to have these conversations is valuable. Engineers make implicit architectural decisions constantly. Surfacing them as explicit choices about runway investment changes how teams think about building.

The Cost of Change at Different Layers

The building metaphor also explains why some refactoring is cheap and some is prohibitively expensive.

Changing paint (UI styling, visual design) is relatively easy. You can repaint a room in a weekend.

Changing room layout (user experience flows, page structure) means knocking down drywall. It's more disruptive, but contained to specific areas.

Changing structural support (APIs, domain models) means removing I-beams. You need to shore up everything above while you work, and you risk cascading problems.

Changing foundation (database schemas, core data models) is digging up concrete. Everything above has to be supported somehow while you do the work. It's the most expensive change by far.

When someone asks why a "simple" feature request will take months, they're often asking for foundation work without realizing it. The metaphor makes the cost visible.

Of course, no metaphor is perfect. Software has advantages that buildings don't: you can incrementally replace components piece by piece, and you can run old and new systems in parallel during migrations. These options make foundational changes possible in ways that would terrify any structural engineer.

The Practical Application

Next time you're in an architecture discussion, try mapping the decision to this framework:

What layer are we changing? Foundation, pillars, rooms, or paint?

Are we building on a slant? Is this feature extending past our current foundation's support?

What kind of debt are we creating? Active debt that will hurt daily, or passive debt that will accumulate silently?

How much runway are we building? Are we speculating about future needs, or building just enough for current requirements?

Where's our flexibility? What's coupled tightly and what has room to move?

These questions don't give you answers, but they surface the tradeoffs. And in my experience, most architecture problems aren't about finding the right answer. They're about understanding the tradeoffs clearly enough to make an intentional choice.


Related Content

Next
Next

AI-Assisted Development Changes What Matters in Framework Selection