Microservices vs Monolith: A Practical Guide for CTOs
An objective look at the choice between monolith and microservices: criteria, DDD as a splitting tool, and total cost of ownership. Case studies, ...Monolith and Microservices: Two Models, Two Philosophies
Monolithic architecture has proven its reliability for decades. A single application, deployed as a whole, is simple to test, easy to deploy, and straightforward to debug. But as the business and team grow, the requirements for architecture change. Microservices promise flexibility, component independence, and scalability, but along with that come increased operational costs. For a CTO, the choice between these models is not a matter of fashion but a strategic decision with a direct impact on budget, delivery speed, and service stability.
Why does the question of microservices even arise?
The growth in user numbers, the shift to continuous delivery, and the desire to release updates without stopping the entire system force us to think about decomposition. Large technology companies have shown that microservices work at scale, but many projects encounter what is called microservices hell: complex infrastructure, distributed transactions, and a non-obvious increase in operational costs. Our experience in cloud development shows that early adoption of microservices without a real need often leads to budget overruns of up to 40% (example).
When the Monolith Remains the Best Choice
Don't fix what isn't broken. The monolith is the optimal solution in a number of situations. Ignoring these scenarios leads to unnecessary complexity and a drop in team productivity.
Startups and MVP at an Early Stage
If the product is still finding its market niche, iteration speed is more important than architectural purity. The monolith allows for quickly testing hypotheses because developers work in a single codebase, and deployment is one command in CI/CD. Splitting into microservices at the stage of uncertain Product-Market Fit will only slow down the feedback loop.
Small Team and Simple Business Processes
A team of up to 15–20 developers handles a well-structured modular monolith just fine. In such an environment, communication overhead is minimal, while distributed systems create additional barriers. If the business logic fits into a small set of cross-cutting processes (for example, a corporate CRM with clearly limited functionality), the monolith is cheaper and simpler to maintain.
Low Requirements for Independent Scaling
When the load is predictable, vertical and horizontal scaling through copying monolith instances fully covers the needs. As long as there are no bottlenecks in specific modules (for example, reporting that paralyzes the interface), the monolith copes with load balancers and caching.
When to Split the Monolith: Signals and Criteria
The decision to move to microservices usually matures from pain, not from technical curiosity. Here are a few clear signals that the monolith has outlived its usefulness.
Team Growth and Conway's Law
When more than 50 developers work on a single codebase, merge conflicts and test environment overload become critical. Teams start blocking each other, and delivery speed drops. The solution is to split into bounded contexts aligned with the organizational structure. This is where Domain-Driven Design comes to the rescue.
Uneven Load Scaling
A classic example: an online store where the product catalog and order processing system require different elasticity. In a monolith, you have to scale the entire application even if the spike is only on search. Microservices allow you to scale 'hot' components precisely, saving resources and increasing fault tolerance.
Difference in Release Cycles of Different Parts of the System
If the backend of a mobile app changes weekly, while the billing module changes once a quarter due to security regulations, their independent delivery is justified. Different life cycles of system parts are one of the most underestimated drivers of decomposition. Our engineers help implement SaaS solution development, where a hybrid approach is especially often in demand.
Fault Tolerance and Failure Independence
Memory leaks in one module of a monolith can crash the entire application. Isolating critical paths into separate microservices improves overall stability: if the recommendations service fails, the core store functionality continues to work.
Domain-Driven Design as a Compass for Decomposition
The most expensive failure in microservice projects is poorly defined boundaries. DDD offers a structured approach through strategic design to avoid this mistake.
Bounded Contexts and Ubiquitous Language
Instead of technical "layered" division (frontend, backend, database), DDD suggests finding boundaries by business meaning. The "Sales" context and the "Fulfillment" context are different worlds with their own models of the "Order" entity. Each such context is a candidate for a separate microservice. The challenge is to avoid excessive fragmentation: if contexts constantly exchange data synchronously, they might belong within the same service.
Relationship Types and Event-Driven Integration
DDD helps define relationships between contexts: partnership, customer-supplier, conformist, anti-corruption layer. For loosely coupled systems, asynchronous communication via events is preferred. This reduces operational orchestration costs but adds observability requirements. Our expertise in web development and cloud infrastructure allows us to build fault-tolerant event-driven pipelines.
How Not to Overdo Microservices: Strategic DDD in Practice
Not every subdomain deserves a microservice. Distinguish between core domain, supporting, and generic domains. It makes sense to implement core subdomains as microservices, while generic ones (e.g., logging, authentication) can be implemented as libraries or use SaaS solutions. This approach reduces the number of standalone services by 30–50% (based on typical projects) without sacrificing benefits.
Operational Overhead: The Hidden Cost of Microservices
Microservice architecture turns capital expenditures into operational costs. Ignoring this has destroyed many business plans.
Infrastructure and Environment Management
If a monolith requires three environments (dev, staging, prod), for 10 microservices you need at least 30. Containerization (Docker, Kubernetes) solves some issues but adds the cost of maintaining the cluster, monitoring, and CI/CD pipelines. ESK's cloud-native development services include building managed infrastructure with TCO (Total Cost of Ownership) calculations, helping avoid unplanned expenses.
Observability and Distributed Tracing
In a monolith, there is a single entry point for logs and profiling. In microservices, tracking a single request requires distributed traces (Jaeger, Zipkin), centralized logging (ELK, Loki), and metrics (Prometheus). Without this, a 200 ms timeout incident turns into a multi-hour investigation. A well-designed observability layer is a mandatory expense.
Testing and Debugging Complexity
End-to-end tests for a microservice system are fragile and slow. You must invest in contract testing (Pact), integration tests with environment setup, and dependency mocking. Initially, test infrastructure costs are invisible, but by the product stabilization phase they can exceed the cost of writing code.
Operational Cost Assessment Checklist
- Evaluate the number of new technologies the team needs to master (orchestration, service mesh, asynchronous communication).
- Calculate the cost of cloud resources for 3–5 environments per microservice (even idle environments consume resources).
- Plan a budget for implementing and maintaining an observability platform.
- Check the readiness of the DevOps/SRE team: without a dedicated operations group, microservices quickly become a "black box."
Transition Strategy: From Monolith to Microservices Without Chaos
Few businesses start from scratch. Most have a working monolith, and the goal is to break it up with minimal business disruption.
Strangler Fig Pattern and Module Prioritization
Gradual feature replacement is the safest path. A new microservice intercepts requests while the monolith continues to operate. The order is determined by business value and technical readiness: start with the least risky yet most independent modules (e.g., notifications or report generation).
Architectural prototyping and evolutionary approach
Before mass decomposition, it's worth creating 1–2 pilot microservices and using them to debug the infrastructure pipeline, CI/CD tools, and monitoring. ESK often applies a pilot approach when developing SaaS products, which reduces risks and gives the team time to learn.
Cultural changes and team autonomy
Without changes in management processes, architectural transformation will fail. Teams must take full ownership of their services—from idea to production monitoring. This requires alignment of motivation, OKRs, and technical competencies. For a CTO, this means investing in mentoring and possibly reshaping engineering culture.
Frequently asked questions
At what team size and codebase size is it definitely time to consider microservices?
There is no magic number, but practice shows that with 20+ developers and 50,000+ lines of poorly structured code, delivery speed starts to suffer. However, much more important than absolute numbers are differences in module lifecycles and organizational structure. Two dozen engineers working closely on a single domain can successfully maintain a monolith, while ten teams with different goals run into integration conflicts.
Can you build microservices without Docker and Kubernetes?
Yes, but the cost of manually managing environments quickly becomes prohibitive. Containerization (Docker) is essential for reproducibility, and orchestration (Kubernetes, Nomad) is essential for operations. That said, for a start you can use PaaS platforms (Heroku, AWS Elastic Beanstalk) that hide some complexity. The key is not the technology but having automated deployment and configuration management.
Which is more expensive: monolith or microservices?
In absolute numbers, a monolith is always cheaper initially. Microservices require investment in infrastructure and processes, but under high load and frequent releases, they can reduce the cost of changes and prevent expensive failures. It's better to compare using the Cost of Delay metric. For example, a monolith with a monthly release cycle that blocks a feature launch can be more expensive than maintaining a dozen microservices. For accurate estimation, our architects perform financial modeling as early as the cloud architecture design stage.
Is DDD mandatory for microservices?
Technically, no. But without DDD methods, the risk of incorrectly defined service boundaries increases sharply, leading to a fragile distributed system. Strategic DDD minimizes code rework and communication overhead. If the project is time-constrained, you can use simplified event storming for initial identification of bounded contexts without diving into full tactical DDD implementation.


