# An architecture that leaves doors open

> “The job of an architect is to build a structure that allows decisions to be delayed as long as possible”: 5 examples illustrating Uncle Bob’s point.

- Author: Mathieu Eveillard
- Published: 2025-01-22
- Updated: 2025-07-11
- Tags: Modularity
- Canonical: https://www.mathieueveillard.com/blog/differer-les-decisions/
- Translation (fr): https://www.mathieueveillard.com/fr/blog/differer-les-decisions.md

![An architecture that leaves doors open](https://www.mathieueveillard.com/blog/2025-01-22-differer-les-decisions/differer-les-decisions.webp)

> The job of an architect is to build a structure that allows decisions to be delayed as long as possible

This aphorism from Uncle Bob probably isn’t a definition of software architecture, but it highlights an essential component: the need to leave doors open and not to constrain the future. Or at least, as little as possible.

Here are five architectural considerations that illustrate this point.

## Bounded contexts

[Contexts](https://www.mathieueveillard.com/blog/bounded-contexts-101), as defined by Domain-Driven Design, are areas of high cohesion that are loosely coupled to one another. Put another way, **the proper boundaries of contexts are those that minimize the need for communication between them**. Contexts are therefore areas of isolation: invoicing can reasonably be considered a distinct entity, almost independent of sales. It’s all in the “almost,” because there is, of course, an exchange of information (a sale triggers the issuance of an invoice). But making a business distinction between these two contexts still allows us to say that we can evolve one while minimizing the impact on the other and on the system as a whole. The doors remain wide open.

## The Modular Monolith

Does it still need an introduction in 2025? The [modular monolith](https://www.mathieueveillard.com/blog/modular-monolith) is the voice of reason: it offers you nearly all the benefits of modularity, starting with the isolation I discussed earlier, without the drawbacks specific to deploying microservices. In practical terms, the various contexts, although functionally isolated, remain interconnected in terms of deployment. They are deployed as a single unit, forming a monolith. A well-organized monolith, and therefore one that can always be evolved into microservices later on, if needed. Once again, we’re leaving the door open; we’re not limiting our future options.

## Hexagonal Architecture

We are now inside a context. As soon as there is even a little business logic, it must be [isolated](https://www.mathieueveillard.com/blog/architecture-hexagonale-trade-off). Not only because this makes testing easier, but also because it is the most stable element over time. **A company’s core business doesn’t change every other day, whereas technologies do**. We’d therefore like to be able to write domain code while abstracting away from the technical details of the outside world (databases, third-party APIs, etc.). Fortunately, Hexagonal Architecture makes this possible, through dependency inversion and a few mappers. This lets us postpone the choice of technologies until later. And when the time comes to store data, we’ll make a much better choice, because we’ll know exactly what queries we need, both read and write.

## The CQRS pattern

The [CQRS](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs) (Command Query Responsibility Segregation) pattern involves separating the write and read models, allowing them to be specialized. In other words, it means having a _very good_ write model and a _very good_ read model rather than an “average” model that does both poorly. One could even have 1 read model and N write models. Put another way, this allows you to leave options open and postpone decisions until later. [Event Sourcing](https://www.mathieueveillard.com/blog/eda-vs-event-sourcing), in particular, is often used as a write model. Its responsibility is to faithfully store all events in a tamper-proof (_append-only_) manner, regardless of how the information will be retrieved later. Accountants are very familiar with this concept.

## SQL

I’ll grant you that SQL isn’t an architecture, it’s a language. But the reasoning holds: among all databases, **SQL databases are unique in that they aren’t specialized for a single type of query**. In principle, they allow for all queries, even if it means optimizing the execution path of a few of them later on. The physical model is designed with the eight [normal forms](https://en.wikipedia.org/wiki/Database_normalization) in mind, and this physical model is modified only marginally to optimize queries. This contrasts with the NoSQL family, where the choice of database depends on a very specific query: to find all third-degree relationships of a person (a typical use case for a social network), it is better to use a graph database, such as Neo4j.

## Conclusion

This insight from Uncle Bob shouldn’t be taken literally: **the goal isn’t to create overly generic, convoluted systems “just in case,” but rather to build simple solutions that will evolve easily**. In other words, don’t introduce complexity today, but allow for it to emerge tomorrow.
