11 January 2026

It’s All a Matter of Style 

By now, there is a wide variety of software architecture styles, and new ones continue to emerge. However, some of them are encountered far more frequently than others, mainly because they are particularly well suited to specific use cases. In the following text, I would like to introduce a few fundamental architecture styles and patterns. Additional ones may be covered in future articles, but for now we will focus on the most well-known approaches and a few of their more specific variations. 

The Good Old Monolith 

This relatively simple architectural style has fallen somewhat out of favor in recent years—often unjustly, in my opinion—because it still offers several advantages, particularly in terms of performance and database consistency. But let’s take things step by step. First, it’s important to clarify what we are talking about. 

As the name already suggests, a monolith consists of a single, unified piece. In concrete terms, this means that the entire codebase of an application, with all its functionality, is delivered to the user as one unit. Typically, there is a single project with a shared codebase, and everyone involved in the project works on that same codebase. At first glance, this doesn’t sound too bad—especially when only a small number of people, ideally just one team, are involved in development. 

Problems usually begin as soon as multiple teams start working on the same source code simultaneously without proper coordination, alignment, or a shared architectural vision. In extreme cases, when there is no common plan and very little coordination, this can result in what is often referred to as a “Big Ball of Mud”: a large, poorly maintainable system that developers are extremely reluctant to extend. You can usually recognize this situation by a common tendency among developers to rebuild something complex from scratch rather than building on existing code. The fear of touching legacy code can become so strong that people are willing to accept additional work just to avoid any interaction with it. 

How Does This Relate to Team Structure and Size? 

This is where Conway’s Law comes into play. The law states that the architecture of a software system reflects the communication structures of the organization that builds it. In practice, this means that a project whose development team is divided into isolated or poorly communicating units—such as separate frontend, backend, and database teams, or multiple distributed teams—is likely to produce a software architecture that mirrors these separations. The result is often inefficient interfaces or, once again, a “Big Ball of Mud”–like structure. 

Conversely, a deliberately designed organizational structure that supports the desired software architecture—such as independent teams aligned with microservices—can be used to improve communication and encourage the intended technical structure. Ignoring this relationship risks creating software that is difficult to maintain, hard to scale, and inefficient to develop due to organizational friction. And believe me, this law holds true—I have experienced its effects multiple times in practice, both positively and negatively. 

How Can We Design a Monolith to Be Future-Proof? 

First and foremost, it is crucial to think carefully about how to slice the internal layers of a monolith. In most cases, it is desirable to have at least two, and often three, clearly separated layers for presentation, business logic, and database access, connected through well-defined interfaces. Since this is often implemented using separate modules, the term “modulith” has become established for this approach. 

This clean structuring and clear separation of responsibilities within individual layers—excluding so-called cross-cutting concerns such as logging or error handling, which are required across all layers—usually leads to a noticeable improvement in the maintainability and comprehensibility of the codebase. In addition to horizontal slicing into layers, modules within a modulith can also be created through vertical partitioning into so-called domains or business areas. 

Topics such as bounded contexts and other aspects of Domain-Driven Design will be covered in a separate article. For now, it is enough to say that with a monolithic architecture and thoughtful application of Domain-Driven Design, it is possible to prepare for a service-based architectural style that can be considered future-proof. 

What Defines a Service-Based Architecture? 

A service-based architecture is a hybrid architectural style that incorporates elements of microservices while being less complex and less costly. Typically, it consists of a separately deployed user interface, several coarse-grained domain services, and a shared monolithic database. 

If you already have a monolith with several well-separated domain modules, these modules can be relatively easily extracted and operated as independent services within a service-based architecture, while still sharing a common database. If the shared database objects used across all services are then extracted into a separate library, nothing stands in the way of deploying these services independently. Different versions of these services can be provided to customers at any time; only changes to the shared library require new versions of all dependent services that use it. 

At that point, the architecture is not far removed from a microservices approach. This illustrates that it is entirely possible to evolve step by step from a monolith toward a microservices architecture. 

The Microservices Architecture Style 

Sometimes it feels as though microservices are seen by some people as the solution to all architectural problems. A small spoiler: they are not. However, especially in cloud environments—and particularly in cloud-native contexts—they are absolutely justified and are not without reason the currently dominant architectural style. 

Microservices align perfectly with core cloud principles such as scalability and automation. By breaking an application into small, independent services, teams can develop individual components independently, which—as we have already learned—can be critically important. In addition, microservices enable more efficient use of cloud resources, since each service receives exactly the infrastructure it needs, resulting in greater efficiency and flexibility. 

As always, however, where there is light, there is also shadow. These advantages come at the cost of increased complexity and usually a significant initial overhead during project setup and infrastructure provisioning. 

So Which Style Should You Choose? 

As is often the case, the answer depends on the circumstances. For operation in cloud-native environments, a microservices architecture is usually the preferred option. However, the CAP theorem should always be kept in mind. It describes a fundamental dilemma in distributed systems: it is impossible to fully guarantee consistency, availability, and partition tolerance at the same time. 

Consistency means that all nodes in the system always see the same data. Availability ensures that every request receives a response, regardless of the system’s state. Partition tolerance means that the system continues to function even in the presence of network failures. Since network partitions are unavoidable in distributed systems, in practice one must choose between consistency and availability, depending on whether up-to-date data or constant accessibility is more important. 

If you want both, you are once again left with the good old monolith—provided it runs on reliable infrastructure. And even that is not the whole truth, as there are, of course, many other architectural patterns that are more or less suitable for a wide range of conceivable use cases. But that is a topic for another time.