Part 0 · 2 chapters · ~12 min
Monolith, Modular Monolith, Services: Choosing Honestly
What each shape costs, Conway's law and team topology, the modular monolith as a default, signals that justify a split, the strangler fig pattern for extracting services, and recording the decision in an ADR.
1
Shapes and their costs
code
src/
modules/
ledger/ index.ts (public API) internal/ … migrations/ (schema: ledger)
payouts/ index.ts internal/ … migrations/ (schema: payouts)
identity/ index.ts internal/ … migrations/ (schema: identity)
// eslint no-restricted-imports: modules/*/internal/** may only be imported inside its module
// a database role per module: payouts cannot SELECT from ledger.* directlyConway's law: systems copy the communication structure of the organisation that builds them. Draw the team map before drawing the service map; a service owned by three teams is owned by nobody.
THREE SHAPES, CHOSEN HONESTLY
what each costs and when it pays
swipe the figure sideways, or tap expand for full screen
1/5
monolith
A single deployable is the fastest way to build: one transaction, one debugger, one deploy. Shopify, Stack Overflow and Basecamp run large businesses on (modular) monoliths.
fastest start, simplest operationshurts with many teams
2
Extracting a service: the strangler fig
- Give the module a clean interface inside the monolith and route all callers through it.
- Give it its own schema and remove cross-schema joins (replace with API calls or read models).
- Stand up the new service behind the same interface; route a slice of traffic (by tenant or percentage) through a proxy.
- Migrate data with dual writes or CDC, verify with reconciliation, then cut over and delete the old code.
code
# ADR-014: Extract payouts into a service Status: accepted · Date: 2026-03-02 Context: payouts deploys 6×/day, ledger 1×/week; payout spikes (salary day) need independent scaling. Decision: extract via strangler fig; payouts owns payouts.*; reads ledger through its API. Consequences: +1 network hop (p99 +8 ms budgeted); needs outbox for ledger events; on-call split.