Digital Product Engineering1.5 Monoliths, Microservices & Event-Dri
VOL. I · CH. 1.5 · FOUNDATIONAL

Monoliths, Microservices & Event-Driven Systems

Three ways to organize a backend's internal structure — each solving a different scale of problem.

DivisionSoftware Architecture
DifficultyIntermediate
Prerequisites1.3
Related5.5 7.9
2 min read · 446 words

1.5.1Definitions

A monolith is a backend built and deployed as one single, unified codebase and process — every feature lives in the same application. A microservices architecture instead splits the backend into many small, independently deployable services, each owning one specific responsibility and communicating over the network. An event-driven system organizes communication around asynchronous events — a service announces that something happened, and any number of other services can react, without the announcing service needing to know who's listening. These are not mutually exclusive: many real systems are microservices that communicate through events.

MONOLITH
one codebase
vs.
SERVICE A
SERVICE B
SERVICE C

1.5.2Why They Exist

A monolith is the natural starting point for almost any product — one codebase is simpler to build, test, deploy, and reason about than several. Microservices exist to solve problems monoliths develop only at real scale: when different parts of a system need to scale independently (checkout traffic vs. reporting traffic), when different teams need to deploy without blocking each other, or when a single failing component shouldn't take down the entire application. Event-driven design exists to decouple services further, so producers and consumers of information don't need direct, synchronous knowledge of each other.

1.5.3When to Use Each

PatternBest fit
MonolithNew products, small teams, unproven product-market fit, most startups
MicroservicesLarge teams needing independent deployment, components with very different scaling needs
Event-drivenSystems with many loosely related consumers of the same underlying event (order placed, user signed up)

1.5.4Common Mistakes

  • Adopting microservices prematurely. Splitting a product with a small team and low traffic into a dozen services, multiplying operational complexity (deployment, monitoring, networking) long before any of its benefits are actually needed.
  • Building a "distributed monolith." Splitting code into separate services that are still tightly coupled and must be deployed together — inheriting all the complexity of microservices with none of the independence benefit.
  • Using events for things that need a synchronous, guaranteed-order response (e.g., authorizing a payment before showing a confirmation), where the added latency and complexity of eventual consistency actively hurts the user experience.

1.5.5Best Practices

  • Start with a well-organized monolith by default; migrate specific pieces to services only when a concrete, measured need appears.
  • If splitting into services, split along genuine business boundaries (billing, inventory, notifications) — not arbitrary technical lines.
  • Use events for "something happened, multiple things may care" scenarios; use direct requests for "I need an answer right now" scenarios.
Real-World Example Amazon's platform is famously composed of hundreds of independent microservices — but Amazon began as a monolith, and only decomposed it as team size and traffic scale made a single codebase a genuine bottleneck, not before.