Business Systems

Microservices vs Monolith: Choosing an Architecture That Scales

Microservices vs monolith for business systems: what each costs to run, why a modular monolith often wins, and which signals justify splitting a service.

Weaveward business systems editorial illustration

For most companies building a business system with one or two development teams, the right answer to microservices vs monolith is a well-structured monolith, often called a modular monolith. Microservices pay off when several teams need to release independently, or when one part of the system has very different scaling or reliability needs, and only when you have the operational maturity to run many moving parts. Without those conditions, microservices mostly add cost and new ways to fail.

That answer surprises some business owners, because microservices are often presented as the modern, scalable choice. But architecture decides how fast your team can change the system as much as how much traffic it can handle. A distributed system that nobody can debug at 2 a.m. during a 12.12 sale does not scale in any useful sense.

This article explains the options in plain language, what scaling really means for a growing company, the costs that rarely appear in proposals, and a migration path that lets you split later without stopping the business.

Three architectures in plain language

Monolith

A monolith is one codebase that is built and deployed as one application, usually with one database. Orders, inventory, invoicing and user management live in the same program. It is simple to develop, test and deploy, and a single database makes transactions and reports easy. The risk is that, without discipline, every part of the code ends up depending on every other part, and changes become slow and risky.

Modular monolith

A modular monolith is still deployed as one application, but the code is divided into modules with enforced boundaries: the inventory module exposes a defined interface, and other modules cannot reach into its tables directly. You keep the simplicity of a single deployment while gaining most of the benefits of separation. If you later need to extract a module into its own service, the boundary already exists.

Microservices

Microservices split the system into independently deployable services, each owning its own data and communicating over the network through APIs or events. An order service, a payment service and a stock service can be released, scaled and even written in different languages separately. The price is that every interaction between them becomes a network call that can be slow, fail or arrive twice.

Factor Monolith Modular monolith Microservices
Deployment One unit One unit Many independent units
Data consistency Database transactions Database transactions, separated schemas Eventual consistency between services
Infrastructure cost Lowest Low Highest: more services, networking and monitoring
Debugging Straightforward Straightforward Needs distributed tracing
Team fit One small team One to a few teams Several teams with clear ownership
Main risk Tangled code over time Boundaries ignored under deadline pressure Operational complexity and network failures

What "scales" actually means

When a vendor says an architecture scales, ask: scales what? There are three kinds of growth, and they point to different answers.

Traffic

A monolith can handle substantial traffic by running several copies behind a load balancer. In business systems the bottleneck is often the database: slow queries, missing indexes, or heavy reports running on the same database as transactions. Fixing those problems helps far more than splitting code into services. If one component, such as stock reservation during a flash sale, needs much more capacity than the rest, you can extract just that component.

Teams

Conway's law observes that systems tend to mirror the communication structure of the organization that builds them. With one team of five developers, a single codebase is easy to coordinate. With four teams sharing the same code and release schedule, they start blocking each other: one team's unfinished feature delays another team's urgent fix. This is the strongest real reason to adopt microservices, and it is an organizational problem more than a technical one.

Change

The third kind of scale is how often you can safely ship changes. A monolith with a good automated test suite and a reliable deployment pipeline can release several times a day. Microservices without those practices often release more slowly than the monolith they replaced, because every change now involves coordinating versions between services.

The costs that rarely appear in the proposal

Microservices move complexity from the code into the network and into operations. Before agreeing to them, make sure the plan accounts for these:

  • Distributed data. Each service owns its data, so you lose simple joins and transactions. A customer order that touches payment, stock and loyalty points needs a saga: a sequence of local steps with compensating actions when something fails halfway
  • Network failure handling. Calls time out, get retried and occasionally arrive twice. Payment webhooks must be idempotent, so a duplicate notification does not mark an order paid twice or ship it twice
  • Observability. You need centralized logs, metrics and distributed tracing to follow one request across services. Without them, a slow checkout becomes a guessing game
  • A deployment platform. Container orchestration, service discovery, secrets management and a pipeline per service. Someone must own this platform, and in a small team that is a senior developer's time taken away from features
  • Local development and testing. Running many services on a laptop, managing API contracts between them and testing them together all take effort
  • Infrastructure bills. More running services, load balancers, managed queues and monitoring tools raise the monthly cloud bill, often before traffic justifies it

These costs are not theoretical. In 2023, Amazon's Prime Video engineering team published a widely discussed post describing how they moved an audio and video monitoring workload from distributed components into a single application, mainly to cut cost and remove scaling limits. The lesson is not that microservices are wrong, but that the right boundaries depend on the workload.

Signals that justify splitting, and signals that do not

Use these lists when your team or a vendor proposes microservices.

Good reasons to extract a service:

  • Several teams are blocked by a shared release cycle, and the code already has clear module boundaries
  • One component has very different load, such as search or a pricing engine, and scaling the whole application for it is wasteful
  • One component needs stricter reliability or security isolation, for example payment processing
  • A component needs a different technology for a sound reason, such as a Python service running machine learning models next to a PHP or Java core
  • Integrations with marketplaces such as Tokopedia and Shopee, payment gateways or logistics partners have their own rate limits and outages. Isolating them keeps a partner's downtime from blocking your core system, although a background worker inside the monolith often achieves this first. Our API integration guide covers the retry and queuing patterns involved
  • You already run centralized logging, monitoring and automated deployments reliably

Weak reasons:

  • "Large tech companies use microservices."
  • "We might have millions of users someday."
  • "The code is messy, so we will rewrite it as microservices." A messy monolith tends to become messy microservices, now with network calls in between
  • A vendor proposes microservices for a first version built by one small team

Hosting is a related decision. The trade-offs in our comparison of cloud vs on-premise apply to both architectures, but microservices lean heavily on managed platform services, which makes on-premise operation harder for a small IT team.

A migration path that does not stop the business

If you run a monolith that is getting hard to change, a full rewrite is rarely the answer. The safer approach is incremental, and it pays off whether or not you end up with microservices.

  1. Map the business domains. List the main capabilities, such as sales orders, inventory, purchasing, invoicing and HR, and the data each one owns. This is the same exercise as a legacy system modernization assessment
  2. Enforce module boundaries inside the monolith. Move code into modules, forbid direct access to another module's tables, and route calls through defined interfaces. Automated architecture tests can enforce the rule
  3. Separate data ownership. Give each module its own schema, and remove cross-module joins from transactional code. Reporting can still read across modules through a reporting database or warehouse
  4. Add observability now. Structured logs, metrics and tracing help the monolith today and are a prerequisite for any service later
  5. Extract one service with the strangler fig pattern. Put a routing layer in front, send a small share of traffic for one capability to the new service, compare results, then shift the rest gradually
  6. Review before extracting the next one. If the first service did not reduce release conflicts or scaling costs, stop and keep the rest as a modular monolith

Stock is a good example of why boundaries matter. When inventory is changed by sales, purchasing and warehouse transfers, it needs one clear owner and well-defined events, as described in our guide to multi-warehouse inventory sync. That design work is valuable whichever architecture you choose.

As a rough planning assumption for a mid-sized business system, with a team of three to six developers working on it part-time alongside feature work, steps 1 to 4 can take one to three months. The range depends mostly on how tangled the current code and database are.

How Weaveward can build this for you

For a new system, we would design a modular monolith by default: clear domain modules, one well-structured database, automated tests and deployments, and observability from the first release. We would also document which modules are candidates for extraction and which signal would justify it, so that decision is made later with real data instead of guessed today.

For an existing system, we would start with a review of your code, database and deployment pipeline, then deliver a prioritized plan and the first boundary or extraction work, validated against release frequency and incident data. Learn more about our business systems development work, or talk to our team about the system you run today.

Let’s connect the dots

What would this look like for your business?

Let's turn the right ideas into a clear next step.

Discuss your project