Skip to main content
AG·SORA
Technology

Monolith or Microservices: Choosing the Right Business Application Architecture

Published 9 min readWritten by agsora.tech
AG·SORA / BLOGAG·SORATechnologyMonolith or Microservices:Choosing the Right BusinessApplication Architectureagsora.tech
In this article

A logistics startup decided to build its app as twenty microservices from day one, because that is what the big technology companies do. Eight months later the six person team spent more time managing the network between services, deployments, and monitoring than building features. A competitor that started with one simple application had already shipped three versions and had paying customers.

The question of "monolith or microservices" is often discussed as if there were one correct modern answer. Yet architecture is about trade offs: every choice eases one thing and adds burden elsewhere. The right choice depends on your team size, business stage, growth pattern, and operational ability, not on trends at technology conferences.

This article explains the difference between the two approaches in language that business owners and product managers can follow, including the hidden costs, signs that a single application is starting to hold you back, the middle path of a modular monolith, and how to split a system gradually without stopping the business. The aim is for you to be able to question your technical team or vendor more critically.

Summary

  • A monolith is one application deployed as a single unit; simple and fast to start
  • Microservices split the system into small independent services; flexible but expensive to operate
  • For most small and medium businesses, a modular monolith is the healthiest starting point
  • Split services only when there is a real reason: scale, teams, or different deployment needs
  • Gradual migration with the strangler pattern is safer than a total rewrite

What a monolith is and what microservices are

A monolith is an application whose features, from catalogue and cart to payment and reports, live in one codebase and are deployed as one package. When you fix one feature, the whole application is redeployed. The word "monolith" often sounds negative, yet many highly successful systems have run this way for years.

Microservices split the application into many small services, each handling one business capability such as orders, inventory, or notifications. Each service has its own codebase, deployment, and often its own database, and they communicate over the network through APIs or messages. Different teams can develop and release their own services independently.

The most important difference lies in boundaries and communication. In a monolith, one part calls another as an ordinary function call that is fast and reliable. In microservices, that call becomes a network request that can be slow, fail, or partly break, so the whole set of distributed system problems arrives with it.

A server rack with neatly arranged network cables
Splitting an application into many services means managing many parts connected over a network.

The often underrated strengths of a monolith

A monolith is easy to understand. A new programmer can run the whole application on a laptop, trace the flow from start to finish, and test changes quickly. Debugging happens in one process with a complete stack trace, not across five services that each keep their own logs.

Database transactions are simple. When an order is created, stock decreases, and an invoice is issued, it can all sit in one transaction that either fully succeeds or fully rolls back. In a distributed system, keeping this consistency needs intricate patterns such as sagas and compensation, which are error prone and hard to test.

Operating costs are low. One application means one deployment pipeline, one place to monitor, and smaller infrastructure. For a small team the saving is not just money but time and attention that can go into building the features customers want.

When a monolith starts to hold you back

A monolith left to grow without discipline becomes a "big ball of mud": every part depends on every other, so a small change in one place breaks something unexpected elsewhere. Deployment gets slow and frightening, testing takes hours, and every release needs the whole team to coordinate.

Another sign is uneven scaling needs. If the product search module receives a hundred times more traffic than the reporting module, duplicating the whole application to support search is wasteful. Separating the heaviest part lets you scale it alone at lower cost.

A third sign is organisational friction. When dozens of programmers across several teams wait on one another and collide in the same codebase, speed falls. At this point clear service boundaries help each team work and release independently, and that is the real benefit of microservices: organisational scale, not just technical scale.

Microservices solve organisation problems, not code problems

Conway's law states that a system's design mirrors the communication structure of the organisation. If you have only one small team, splitting the system into dozens of services creates coordination overhead with no benefit. Consider microservices when several teams need to move independently.

The hidden costs of microservices

The first is operational complexity. You need container orchestration, service discovery, an API gateway, secrets management, and deployment for dozens of services. Without a platform team or mature DevOps skills, this burden falls straight on feature programmers and slows everything.

The second is observability. A single user request can pass through many services, so you need distributed tracing, centralised logs, and per service metrics to find the source of a problem. Without them, failures become mysteries that are expensive to solve.

The third is data consistency and versioning. Every change to an API contract must be managed so it does not break other services, and data scattered across many databases makes cross domain reporting harder. Many organisations end up adding a data warehouse just to answer questions that used to take one query.

The fourth is latency and reliability. Every network hop adds time and chances of failure. The system must be designed to survive slow or dead services with timeouts, retries, and circuit breakers. All of this is real work that does not exist in a monolith.

A laptop screen showing colourful program code in an editor
Clear module boundaries inside the code matter as much as service boundaries between servers.

The middle path: a modular monolith

A modular monolith is one application composed of modules with firm boundaries. Each module, for example catalogue, orders, and billing, communicates with other modules only through clear interfaces and may not access another module's database tables directly. Deployment remains a single package, so it is simple to operate.

This approach delivers most of the design benefits of microservices, namely clear responsibilities and isolated change, without the cost of a distributed system. If one day a module needs to be separated, its boundary is already tidy, so extracting it into its own service is far easier.

To keep discipline, use architecture rules that are checked automatically in the test pipeline, for instance forbidding the orders module from importing the billing module's internal code. Rules that exist only in a document get broken when a deadline nears; rules enforced by failing tests survive.

A practical decision framework

Start by asking how many teams work on this product. If one to three small teams, a modular monolith is almost always the best choice. Next ask whether any part has very different scale or reliability needs, such as image processing or bulk notification sending; such a part is the first candidate to separate.

Also ask about operational maturity. Do you already have good automated deployment, monitoring, and recovery plans for one application? If not, multiplying it into twenty services will magnify the chaos. Fix the operational basics before increasing the number of moving parts.

  1. 01Start with a modular monolith and firm module boundaries
  2. 02Measure: deployment time, release frequency, and scaling bottlenecks
  3. 03Identify modules that truly need different scale or release cycles
  4. 04Separate one module as an experiment and evaluate its cost
  5. 05Repeat only when the benefit is proven to exceed the operating burden

Splitting a system gradually

If you already have a large monolith that is hard to change, resist the temptation to rewrite everything. A total rewrite usually takes far longer than estimated, and meanwhile the old system keeps changing, so the team chases a moving target. Many such projects end up cancelled after consuming years of budget.

Use the strangler pattern: place a routing layer in front of the old system, then move one capability at a time to a new service. Start with parts that are isolated and high value, such as notifications or search. Send a small share of traffic to the new service, compare the results, and switch fully only when confident. The old system shrinks bit by bit until it is no longer needed.

Mind the data. Separating code is easier than separating a shared database. Plan who owns each table, and provide interfaces for cross module data access before moving storage. Temporary synchronisation through events or replication can bridge the transition.

Case example: a growing online shop

An online shop started with a single application handling catalogue, orders, and payments. For the first two years this monolith ran smoothly and a three person team could release daily. When a promotional campaign made search traffic surge, only the search module was overwhelmed while the rest was fine.

Rather than splitting everything, the team separated search into its own service with a dedicated search engine and scaled it independently. Orders and payments stayed in the monolith because they need transactional consistency. The result was reasonable infrastructure cost and complexity a small team could still manage.

The lesson: split on evidence, one part at a time, and only when there is a measurable problem. Good architecture grows in step with business need, not ahead of it.

Questions to ask a vendor or technical team

When a vendor proposes microservices, ask what specific problem it will solve and how they measure it. Ask who will operate the system after launch, how monitoring and disaster recovery work, and what monthly infrastructure cost is expected. Vague answers suggest the decision is driven by trend rather than need.

Also ask how module boundaries are protected, how the database is managed, and how hard it will be to separate a part in future. A good vendor will gladly explain why they chose a modular monolith for the early stage and show a sensible evolution path as your business grows.

Closing

Monolith versus microservices is not old versus modern but a question of fit. For most small and medium businesses, starting with a tidy modular monolith gives speed, low cost, and room to grow. Microservices deserve consideration when organisational scale and technical needs truly demand them and operational ability is ready.

Focus on what matters most: clear module boundaries, automated testing, reliable deployment, and good monitoring. With this foundation you can change the architecture whenever needed, without staking the business on a decision made too early.

Unsure which architecture suits your business application?

The AG·SORA team can help assess your needs, design an architecture that fits your business stage, and build it step by step. The first consultation is free and without obligation.

Free consultation

Free checklist: choosing a software house

24 points to evaluate a vendor before you sign. Can be saved as a PDF.

Get the checklist

Ready to build a system that grows with your business?

Discuss your needs with the AG·SORA team, no cost, no commitment.