system-design

Part 5 — Architecture Patterns

How to arrange services and code — and, just as often, when not to. Most of this part is about resisting complexity you don’t need.

Time for this part: Week 9 on the Standard track. It’s where the earlier parts come together into whole-system decisions.

The recurring theme: almost every pattern here solves an organizational or evolution problem, not a throughput problem — and applying them for the wrong reason is the most expensive class of mistake in system design.


Chapters

Structuring services

# Chapter Time The problem it solves
1 Monolith vs Microservices 26 min Microservices solve a people problem, not a scale one
2 Service Decomposition 24 min Where to draw the lines — and why aggregates decide it
8 Service Mesh & Sidecars 20 min mTLS, retries, and tracing out of every app
9 Backend for Frontend 16 min One API can’t serve mobile, web, and TV well
11 Multi-Tenancy 20 min One system, many customers, complete isolation

Data and event flow

# Chapter Time The problem it solves
3 Event-Driven Architecture 26 min Announce facts instead of issuing commands
4 CQRS 20 min The write shape and read shape want opposite things
5 Event Sourcing 24 min Store what happened, not what is

Structuring code and change

# Chapter Time The problem it solves
6 Layered & Hexagonal Architecture 20 min Business rules that don’t depend on the database
7 Serverless 22 min Scale to zero, pay per request — and when it’s a trap
10 Strangler Fig 18 min Replacing a legacy system without turning it off
12 Anti-Patterns 22 min The designs that look right and aren’t

The through-line

More teams need to ship independently (ch 1)
        ↓
So you split — carefully, by capability and aggregate (ch 2)
        ↓
And services announce facts rather than commanding each other (ch 3)
        ↓
Which lets read and write models diverge (ch 4, 5)
        ↓
While the code inside each service stays testable and replaceable (ch 6)
        ↓
Deployed on infrastructure sized to the workload (ch 7, 8)
        ↓
Shaped per client (ch 9) and per customer (ch 11)
        ↓
Migrated to gradually (ch 10) — and avoiding the traps throughout (ch 12)

The five things to remember

  1. Microservices solve organizational scaling, not throughput. Ask “how many teams?” before “how many users?”
  2. The modular monolith is the right default for most systems — boundaries and a migration path, without the distributed cost.
  3. Split by business capability and aggregate, never by technical layer or database table. A feature should touch one service.
  4. Events announce facts (past tense); commands issue instructions. Confusing them recreates the coupling you were removing.
  5. The best pattern is often the simplest one. Serverless, CQRS, event sourcing, and a service mesh are all real costs — each must be justified by a concrete requirement, not by fashion.

Before moving on

You should be able to answer these without notes:


Next: Part 6 — API Design — the contracts through which all of these services talk.