Software Architecture
Styles and patterns for organizing services and code — microservices vs monolith, DDD, event-driven, CQRS, Clean / Hexagonal layering
Software Architecture
If distributed systems is about correctness in the presence of multiple nodes, software architecture is about fit — how a system is sliced, layered, and named so that it can be changed by humans over years without collapsing under its own weight.
The decisions here are rarely provably right. They are bets: about team size, about how fast the domain will change, about where the next year of pain will come from. The job of this section is to make those bets legible — what each style optimizes for, what it gives up, and the failure mode you sign up for when you choose it.
Topics
Styles
- Monolith — The default that more systems should have stayed.
- Modular Monolith — One deployable, real internal boundaries, the underrated middle ground.
- Microservices — When the cost of coordination is lower than the cost of distribution.
- Service-Oriented Architecture (SOA) — The predecessor, and what it got right.
- Serverless / Function-as-a-Service — Architecture implications, not just billing.
Domain-Driven Design (DDD)
- Strategic Design — Bounded contexts, context maps, ubiquitous language.
- Tactical Patterns — Aggregates, entities, value objects, domain events, repositories.
- Anticorruption Layer — Defending a clean model from a messy upstream.
Event-Driven
- Event-Driven Architecture — Notifications vs event-carried state transfer vs event sourcing.
- CQRS — Splitting writes from reads, when and when not.
- Event Sourcing — Storing the log, not the snapshot.
- Saga Pattern — Long-running business workflows (the protocol view lives in Distributed Systems).
- Outbox Pattern — The reliable bridge between a database and a message bus.
Layering & Boundaries
- Clean Architecture — Dependency direction as the central rule.
- Hexagonal / Ports & Adapters — Domain in the middle, I/O at the edges.
- Onion Architecture — The sibling no one introduces.
- BFF (Backend for Frontend) — When the API your service offers and the API your UI needs diverge.
Decisions
- When to Split — Symptoms that justify going from monolith to services.
- Conway's Law — Organization shapes architecture, whether you like it or not.
- Architecture Decision Records (ADR) — Cross-link with
code-craft/design/adr. - Anti-Patterns — Distributed monolith, microservice-per-table, premature event sourcing.
Scope and Boundaries
| Concern | Lives here | Lives elsewhere |
|---|---|---|
| Service slicing, layering, DDD, event-driven | ✓ | — |
| Saga as a workflow pattern | ✓ | — |
| Saga as a correctness protocol | — | distributed-systems/correctness |
| Class-level SOLID, function shape, naming | — | code-craft/ |
| Specific orchestrator selection (Temporal vs Airflow) | partly | architecture/comparison, infrastructure/workflow-orchestration |
| Capacity, SLO, on-call practice | — | (planned: architecture/reliability/) |
How to Read This Section
A practical sequence:
- Monolith → Modular Monolith → Microservices — pick your style with both eyes open. Conway's Law tells you whether your organization can even support the architecture you want.
- DDD strategic design — most "microservice" mistakes are actually missing bounded contexts.
- Event-driven + CQRS + outbox — the patterns that recur once services exist.
- Anti-patterns — read this before greenfield work, not after.
The most important habit this section tries to install is naming the trade-off out loud. "We are choosing X, knowing Y will get worse" is the kind of architecture decision that ages well. "X is best practice" is the kind that does not.