Software Architect · Module 11

A monolith doesn't mean chaos, and microservices don't mean architecture. What matters is boundaries, ownership, and operational maturity.

Modular monolith · service boundaries · operational complexity

§ 01

Microservices buy independence at the price of distributed complexity. If you don't need the independence, the price is wasted.

A service is an organizational unit

A separate office helps when a team has its own work, rhythm, and responsibility. If everyone is on the same call anyway, the walls don't help.

A microservice is justified when the context has its own lifecycle, owning team, load profile, security requirements, or release rhythm. Pulling code into a separate deployable unit isn't enough.

A modular monolith is often better early on: one codebase and one deployment, but strict internal modules, public interfaces, no circular dependencies, and clear ownership.

Distribution adds an operational price

One kitchen can be cramped. Ten kitchens require logistics, communication, delivery schedules, and rules for handing dishes off.

Microservices require service discovery, observability, network security, backward-compatible contracts, distributed tracing, deployment orchestration, incident response, data ownership, and SRE practices. None of that is a downside if there's a reason for it. It's the price.

The architect has to ask honestly: which pain goes away after the split, and which new pain appears?

§ 02

A good split reduces coordination. A bad split creates more sign-off meetings than there were before it.

Example: extracting billing

The register, the accounting office, and the warehouse are connected, but accounting has its own rules, audits, and responsibility.

Billing has its own compliance requirements, audit trail, integrations with payment providers, and an owning team. It can be extracted into a service with its own data and contracts: invoices, subscriptions, payment events.

That split makes sense: it protects a domain with a high cost of error and a separate pace of change.

Anti-example: a microservice per table

If every shelf of the warehouse became a separate shop, the customer would have to walk through ten checkouts for one order.

The team builds users-service, profiles-service, addresses-service, roles-service, but every use case requires calls to all four. The data is still coupled, releases are still coordinated, and latency and debugging are both worse.

That's a distributed monolith: there are services, but no independence.

Self-check
  • Which team will own this service? - Can the service be released independently? - Whose data does it own? - Which new operational responsibilities appear after the split?