The default architecture should be a modular monolith

For most companies building software in 2026, the smartest starting point is not microservices. It is a modular monolith. That may sound less exciting, but engineering decisions should be driven by outcomes.

A modular monolith keeps the application as one deployable system with one database and one delivery pipeline. Inside that system, however, each business area is separated into well-defined modules with clear ownership and strict boundaries. A module exposes its functionality through internal interfaces and manages its own data without allowing direct access from other modules. This creates discipline early, while keeping operations simple.

The biggest advantage is that complexity stays proportional to the business. Every distributed system introduces operational overhead from the first day. You need service discovery, monitoring across multiple services, network communication, deployment orchestration, security between services, and engineers who understand distributed systems. Those costs exist before any business value appears.

Many organizations never reach the scale where those costs are justified.

A modular monolith gives leadership something valuable: optionality. If one business capability eventually needs to scale independently or be managed by its own engineering team, that module can be extracted into its own service later. If that moment never comes, the company avoids years of unnecessary operational expense.

This approach also improves execution speed. Engineers deploy one application instead of coordinating releases across many services. Troubleshooting becomes faster because failures remain inside a single deployment. Infrastructure costs stay lower because there are fewer moving parts to maintain.

From a business perspective, this matters because software architecture is an engineering decision. But it also directly affects hiring, operating costs, product delivery speed, and organizational flexibility. Every additional service requires ownership, monitoring, documentation, security reviews, and long-term maintenance. Those investments should generate measurable business value.

Martin Fowler addressed this directly in his 2015 article “Microservice Premium.” He argued that distributed systems impose an immediate operational cost, and that this cost only becomes worthwhile after an organization reaches sufficient scale and complexity. Before then, microservices often slow development, consume engineering capacity, and require experienced talent that could be focused elsewhere.

David Heinemeier Hansson (DHH), co-founder of Basecamp and creator of Ruby on Rails, reaches a similar conclusion in his writing on “The Majestic Monolith.” He argues that many teams were convinced microservices were the default answer when they were not. Basecamp supports multiple platforms while continuing to run as a modular monolithic application with a relatively small engineering team. The architecture has remained effective because it matches the company’s actual needs instead of anticipated ones.

For executives, this leads to a simple question.

Are you solving today’s business problems, or preparing for problems you may never have?

The answer should determine your architecture.

Adopting microservices requires a structured decision framework

The decision to adopt microservices should never begin with technology. It should begin with measurable business conditions.

Build a practical framework built around five dimensions: team autonomy, deployment independence, scalability requirements, data ownership, and organizational maturity. Together, these provide a clear picture of whether the benefits of microservices outweigh their operational cost.

The first dimension is team autonomy. Microservices work best when multiple engineering teams own different business domains and need to move independently. If only one or two teams build the entire product, separating the application into dozens of services usually creates more coordination instead of less.

The second dimension is deployment independence. Ask a straightforward question: are product releases delayed because different teams must coordinate every deployment? If the answer is yes, independent services may remove that bottleneck. If deployments already happen smoothly, there may be little value in introducing distributed systems.

The third dimension is scalability. Not every part of an application experiences the same demand. A payment system, recommendation engine, or checkout process may require significantly more computing resources than other features. If scaling the whole application to support one heavily used component wastes infrastructure spending, separating that component can become economically attractive.

The fourth dimension is data ownership.

Each service should own its data completely. This is one of the strongest reasons to introduce microservices. Different business domains often have different storage requirements. Financial records may require one type of database, search another, analytics another, and session management yet another. When these differences become operationally important, independent services create flexibility without forcing every workload into the same technology.

The fifth dimension is operational maturity.

This is frequently underestimated.

Microservices assume the organization already operates mature engineering systems. Continuous integration and continuous delivery (CI/CD), monitoring, distributed tracing, incident management, API management, container orchestration, and reliable ownership models should already exist. Microservices do not create operational excellence. They require it.

One of the strongest messages is that companies often evaluate their future instead of their present. Leadership imagines what the organization might look like in three years and builds architecture for that future immediately.

That is usually a mistake.

Architecture should respond to demonstrated business needs. Software evolves far more effectively when complexity is introduced only after it becomes necessary.

The framework reflects this philosophy through three practical outcomes.

If most dimensions receive a “Yes,” specific business domains may justify extraction into independent services. Importantly, only those domains should be extracted.

If most dimensions are “Not Yet,” the recommendation is to remain with a modular monolith while enforcing strong module boundaries. This preserves future flexibility without introducing today’s operational burden.

If most dimensions are “No,” the organization should stay monolithic and invest in its engineering foundation first. Better deployment pipelines, clearer ownership, stronger monitoring, and mature operational practices create far more value than distributing an application prematurely.

For executive teams, this framework changes the conversation.

The question is no longer, “Should we adopt microservices?”

The better question is, “Which specific business capability has earned the additional complexity?”

Only when there is a clear answer should a service be extracted. Everything else should remain where it creates the greatest value: inside a well-structured modular monolith.

Okoone experts
LET'S TALK!

A project in mind?
Schedule a 30-minute meeting with us.

Senior experts helping you move faster across product, engineering, cloud & AI.

Please enter a valid business email address.

Microservices are justified when addressing specific scalability, autonomy, and efficiency issues

Microservices are not valuable because they are modern. They are valuable when they solve a real business constraint.

Too many organizations begin with the architecture instead of the problem. The better approach is to identify where the current system creates measurable friction. If there is no significant friction, introducing distributed services simply increases operational complexity without creating meaningful business value.

One of the strongest reasons to adopt microservices is organizational scale.

As companies grow, engineering teams naturally become more specialized. Different teams begin owning different business capabilities, each with its own roadmap, priorities, and release schedule. When these teams constantly wait for one another before deploying new features, delivery slows down. Independent services allow each team to release changes on its own timeline without affecting unrelated parts of the business.

This is closely connected to Conway’s Law, which states that software architecture tends to reflect the organization’s communication structure. If the organization operates through multiple autonomous teams with clearly defined responsibilities, microservices can reinforce that structure. If those teams do not yet exist, splitting the system usually creates coordination work rather than eliminating it.

Deployment independence is another important signal.

Many organizations experience release bottlenecks because schema changes, shared libraries, or tightly coupled code force multiple teams to coordinate every deployment. Over time, this reduces product velocity and delays customer-facing improvements. Microservices address this problem by allowing qualified business domains to evolve independently, provided the services are genuinely decoupled.

Scalability requirements provide another clear justification.

Applications rarely experience uniform demand across every component. An e-commerce checkout service may experience traffic levels that are ten or even one hundred times higher than catalog browsing during peak events. Scaling the entire application to support one high-demand workload increases infrastructure spending unnecessarily. Separating that workload into its own service allows computing resources to be allocated where they generate the greatest return.

Data ownership is one of the strongest arguments for microservices.

Different business domains often require different persistence technologies. A financial ledger may prioritize consistency and auditability. Search capabilities may rely on Elasticsearch for fast indexing and retrieval. Session management may use Redis because of its speed. Analytical workloads may benefit from ClickHouse, while transactional business data may continue using PostgreSQL.

Microservices allow each domain to choose the technology that best supports its operational requirements instead of forcing every workload into a single database platform.

This flexibility, however, only creates value when the business domains are genuinely independent. If services constantly exchange data, share databases, or require synchronized updates, the architectural benefit largely disappears.

There are several reasons that should never drive a microservices initiative.

Statements such as “microservices are modern,” “our codebase is getting large,” or “Netflix uses microservices” are not business justifications. They describe industry trends or preferences rather than measurable operational problems.

For executives, this distinction matters.

Technology investments should solve identifiable constraints that affect growth, customer experience, engineering productivity, or operating costs. If those constraints do not exist, introducing microservices simply increases long-term complexity without producing proportional business value.

Organizations should only justify a service extraction when at least one qualifying condition exists today or is expected within the next 12 to 18 months. Planning around hypothetical future requirements is not sufficient.

This disciplined approach keeps architecture aligned with business reality instead of industry momentum.

Insufficient scale and operational maturity are barriers to effective microservices implementation

One of the most expensive mistakes organizations make is assuming that adopting microservices will improve engineering maturity.

It does not.

Microservices amplify both strengths and weaknesses. If an organization already operates efficiently, distributed services can increase flexibility. If operational practices are weak, those weaknesses become significantly more visible and much harder to manage.

Every independent service introduces ongoing responsibilities.

Each service needs its own deployment pipeline, monitoring, logging, security controls, testing strategy, documentation, incident response process, and ownership. Engineers must understand their own code and how failures propagate across a distributed environment.

As the number of services grows, so does the operational workload.

For smaller engineering organizations, this becomes a serious challenge. A limited number of engineers may end up supporting multiple services simultaneously while remaining responsible for feature development. Knowledge becomes fragmented, and the departure of a single engineer can leave critical services without sufficient expertise.

The benefits of microservices only appear when organizations can assign dedicated ownership to each service over the long term.

Operational maturity is equally important.

Organizations should already have reliable continuous integration and continuous delivery (CI/CD), comprehensive monitoring, distributed tracing, consistent on-call practices, API management, load balancing, and container orchestration before introducing distributed services.

These capabilities are not optional additions after migration. They are prerequisites.

Without them, diagnosing production issues becomes significantly more difficult because requests move across multiple independent systems instead of remaining inside a single application.

New products usually experience frequent changes in business requirements. Teams continue learning about customers, workflows, pricing models, and product capabilities. As understanding evolves, business boundaries naturally change.

Defining permanent service boundaries too early often results in incorrect decomposition. Once services communicate across network boundaries, changing those boundaries becomes substantially more expensive than reorganizing modules within a single codebase.

This is one reason to begin with a modular monolith. Internal boundaries can evolve as the business learns more, while operational complexity remains manageable.

Only after business domains stabilize should organizations consider extracting independent services.

Sam Newman, author of Building Microservices, reinforced this point during QCon London in 2020, stating that “microservices should not be the default choice.” His position aligns closely with Martin Fowler and David Heinemeier Hansson, despite their different backgrounds and experiences. All three conclude that premature adoption often creates unnecessary cost without delivering corresponding business benefits.

For executives, the strategic lesson is straightforward.

Before funding a major architectural transformation, evaluate whether the organization has developed the operational discipline required to support it. Investments in deployment automation, monitoring, ownership, reliability engineering, and production visibility often produce greater returns than introducing distributed services too early.

Architecture should follow organizational maturity, not attempt to create it.

Poorly implemented microservices can become distributed monoliths

Moving to microservices does not automatically create an independent, scalable system. In many cases, organizations end up with what is known as a distributed monolith. This is one of the least desirable outcomes because it combines the operational cost of distributed systems with the tight coupling of a traditional monolith.

The defining characteristic of a distributed monolith is that services cannot truly operate independently.

One of the strongest warning signs is a shared database. If multiple services read from and write to the same tables, they no longer own their data. Every schema change requires coordination across teams, increasing delivery time and creating unnecessary risk. Independent deployment becomes difficult because a change intended for one service may unexpectedly affect another.

True microservices depend on clear data ownership. Each service should control its own data and expose it through well-defined interfaces. Once services begin sharing databases, that independence quickly disappears.

Another warning sign is coordinated releases.

If deploying Service A requires Services B and C to be deployed in a specific order, the organization has not achieved independent deployment. Teams still move together, but now they also manage network communication, version compatibility, and distributed infrastructure. The expected increase in delivery speed never materializes because coordination remains a constant requirement.

In some implementations, a single customer request triggers a sequence of synchronous calls across multiple services. If one service experiences latency or becomes unavailable, every dependent request is affected. Instead of isolating failures, the architecture spreads them across the system.

This has direct business implications. Customer experience becomes more sensitive to infrastructure issues, and engineering teams spend more time diagnosing failures that cross service boundaries.

Distributed transactions introduce another layer of complexity.

In a monolithic application, a database transaction can often guarantee that either every operation succeeds or none do. Once data is divided across multiple services, those guarantees no longer exist across service boundaries. Organizations must instead manage distributed transactions using techniques such as the Saga pattern, where each local transaction requires compensating actions if part of the overall workflow fails.

While effective, these patterns increase development effort, operational complexity, testing requirements, and the potential for temporary data inconsistency. As additional services participate in a transaction, the complexity grows further.

For business leaders, this is an important consideration because architectural complexity affects more than engineering. It influences delivery speed, reliability, operational costs, and the organization’s ability to respond to changing business priorities.

Instead of continuing to split the system into smaller services, organizations should first consolidate tightly coupled components. The goal is to establish genuine business boundaries before introducing further distribution. Once those boundaries are stable and independent, selective service extraction becomes much easier and significantly less risky.

Microservices create value through independence. If independence is missing, the architecture carries the costs of distribution without delivering its benefits.

Service boundaries should be defined by business capabilities

Once an organization determines that a service should be extracted, the next question becomes far more important than many teams realize.

Where should the boundary be?

This decision should always begin with the business rather than the technology.

Eric Evans, author of Domain-Driven Design, has long advocated defining boundaries around business capabilities instead of technical layers. This approach aligns software ownership with how the organization actually creates value for customers.

A business capability represents a complete business function with a clear purpose and ownership.

For example, a user service that manages registration, authentication, user profiles, and session management represents a coherent business capability. These functions naturally belong together because they support a single business outcome.

By contrast, creating services around technical layers often produces long-term problems. A service responsible only for database access, for example, tends to become a shared dependency for many parts of the application. Over time, this increases coupling rather than reducing it and makes independent evolution much more difficult.

Some technical workloads have operational characteristics that differ significantly from the rest of the application. High-frequency polling endpoints, inbound email gateways, or CPU-intensive image processing may justify running as separate processes because their performance or reliability requirements are unique. These cases are exceptions driven by workload characteristics rather than general architectural principles.

Rather than approving service creation based on engineering enthusiasm alone, leadership can require evidence that a proposed service has a clear business owner, exclusive responsibility, independent deployment capability, and operational resilience.

Correcting poor service boundaries after deployment is one of the most expensive mistakes in a microservices program. Once services are in production, changing boundaries affects APIs, data ownership, deployment processes, operational procedures, and organizational responsibilities.

Investing more time in defining boundaries before extraction typically saves months of rework later. It also creates a software architecture that can evolve alongside the business instead of constantly requiring structural redesign.

The citadel architecture provides a practical hybrid alternative

Architecture decisions do not have to be limited to two choices. There is a third option that many organizations overlook: the Citadel architecture.

Coined by David Heinemeier Hansson (DHH), co-founder of Basecamp and creator of Ruby on Rails, the Citadel approach keeps the core application as a modular monolith while extracting only a small number of specialized services, referred to as “outposts.” These outposts are created only when a particular workload has technical requirements that differ significantly from the rest of the application.

This is an important distinction.

The decision is not based on organizational preference or architectural fashion. It is based on measurable operational needs.

Most business logic remains inside the monolith, where development, deployment, and maintenance remain straightforward. Only workloads with unique performance, availability, or scalability requirements are separated into independent services.

Campfire relied on clients polling the server every three seconds to check for new messages. Most of those requests returned no new information, but they still generated substantial traffic. Processing those requests through the entire Rails application meant every poll consumed resources that were unnecessary for such a simple task.

Instead of distributing the entire application, the engineering team extracted only the polling endpoint into its own service. Because this endpoint handled extremely high request volumes, it was rewritten over time using several programming languages optimized for performance, including C, C++, Go, and Erlang. Meanwhile, the core Basecamp application continued running as a monolithic Ruby on Rails application.

HEY, Basecamp’s email service, is another example.

Incoming email is first handled by Postfix, which receives the messages, stores them safely on disk to improve resilience, and then forwards them via HTTP to Action Mailbox within the main HEY application. This separates a specialized infrastructure workload without requiring the rest of the application to become a distributed system.

For executives, this approach offers a balanced strategy.

Organizations often discover that only a small percentage of their workloads truly require independent infrastructure. Separating only those workloads allows engineering teams to solve targeted operational problems while avoiding the significant complexity that comes with distributing every business capability.

The Citadel architecture also preserves strategic flexibility.

The monolith remains the primary system of record and continues to evolve normally. Outposts are added only when justified by measurable technical requirements. This reduces operational overhead, simplifies governance, and limits the number of distributed components that require ongoing support.

From a financial perspective, this approach can also improve capital efficiency.

Every additional service introduces infrastructure costs, operational monitoring, deployment pipelines, security management, and engineering ownership. By limiting service extraction to workloads that generate clear operational value, organizations concentrate their investments where the return is highest.

Architecture should evolve incrementally. Companies do not need to distribute their entire application simply because one component has exceptional performance requirements. Solving the specific problem while keeping the rest of the system simple often produces a better long-term outcome.

Amazon prime video’s VQA system shows that consolidation can reduce cost and improve scale

The case demonstrates that even organizations recognized for operating large-scale distributed systems do not treat microservices as the default solution. Instead, they continue to evaluate whether an architecture matches the workload it supports.

In March 2023, Marcin Kolny, an engineer at Amazon Prime Video, described how the Video Quality Analysis (VQA) system was redesigned from a distributed serverless architecture into a consolidated monolithic application.

The VQA service continuously analyzes thousands of live video streams to detect quality issues such as video freezing, block corruption, and audio-video synchronization problems. When issues are identified, the system initiates corrective actions in real time.

The original architecture relied on AWS Lambda for compute, AWS Step Functions for orchestration, and Amazon S3 to transfer video frames among separate processing components.

While this architecture provided independent services and elastic scaling, it also introduced significant operational costs at production scale.

AWS Step Functions are billed according to state transitions. Because VQA generated multiple state transitions for every second of video processed, orchestration costs increased rapidly as workload volume grew.

Amazon S3 transfers between processing stages added additional latency and storage operations. Instead of passing data directly in memory, each stage depended on repeated storage and retrieval operations, increasing both execution time and infrastructure expenses.

According to Kolny, these architectural decisions also created scaling limitations. The system reached account-level scaling thresholds at approximately 5% of its projected production capacity.

The engineering team decided to consolidate the media converter, defect detection, and orchestration components into a single application running on Amazon EC2 and Amazon ECS.

Once the services were colocated, intermediate data moved directly through memory instead of repeatedly passing through external storage. Workflow orchestration also became significantly simpler because many operations became direct internal function calls rather than distributed service interactions.

The results were substantial.

According to Kolny, infrastructure costs fell by more than 90%. At the same time, the redesigned system scaled well beyond the limitations of the original architecture.

Instead, it highlights a more important principle.

Technology choices should match workload characteristics.

The original architecture solved problems such as independent function scaling and highly distributed execution, but those capabilities were not the primary constraints of the VQA workload. Meanwhile, the architecture introduced new costs through orchestration overhead, network communication, and storage transfers that directly affected operational efficiency.

For executives, this case reinforces an important investment principle.

Architecture decisions should be evaluated using measurable business outcomes such as operating cost, system performance, engineering productivity, scalability, and customer impact. A technology that performs well in one environment may become unnecessarily expensive in another if the underlying business requirements differ.

Martin Fowler’s concept of the “Microservice Premium” is clearly reflected in this example. Distributed systems provide significant advantages when they solve genuine business problems. When they do not, the operational cost becomes the dominant factor.

The lesson is not to favor monoliths over microservices or vice versa.

The lesson is to select the architecture that creates the greatest business value for the workload you actually have today, while preserving the flexibility to evolve as those requirements change.

Recap

The discussion around microservices has matured. The question is no longer whether microservices are the future. The question is whether they solve the business problem in front of you today.

For executives, architecture is ultimately a business decision. It influences operating costs, hiring strategy, product delivery speed, resilience, and the organization’s ability to adapt as it grows. Every architectural choice carries long-term consequences, so complexity should always earn its place.

A modular monolith gives most organizations the fastest path to delivering value while preserving future flexibility. It keeps engineering focused on building products instead of managing infrastructure. When the business grows, the architecture can grow with it. When it does not, the company avoids carrying operational costs that never produce meaningful returns.

Microservices remain an exceptionally powerful approach, but only when the conditions are right. Autonomous teams, independent deployment needs, clear domain ownership, meaningful scalability differences, and mature operational capabilities are not optional. They are the signals that the organization has reached the point where distributed systems create more value than they consume.

Business leaders should also recognize that architectural decisions are not permanent. They should be revisited as products, teams, and customer demands evolve. The right architecture today may not be the right architecture three years from now. The goal is not to predict every future requirement but to build a foundation that allows change without unnecessary disruption.

The organizations that consistently succeed are rarely the ones using the most fashionable architecture. They are the ones making disciplined decisions based on measurable business outcomes. They introduce complexity only when it delivers a clear advantage, and they continue to challenge assumptions as the business evolves.

That is the real objective. Choose the architecture that fits your current reality, invest in strong engineering fundamentals, and evolve deliberately as your organization grows. When technology decisions remain aligned with business needs, both engineering performance and business performance improve together.

Alexander Procter

August 7, 2026

21 Min

Okoone experts
LET'S TALK!

A project in mind?
Schedule a 30-minute meeting with us.

Senior experts helping you move faster across product, engineering, cloud & AI.

Please enter a valid business email address.