Source · Ford, Richards, Sadalage & Dehghani, Software Architecture: The Hard Parts (O'Reilly)
Why this matters
Ford, Richards, Sadalage & Dehghani, Software Architecture: The Hard Parts, Ch. 1-2The 'easy parts' of architecture have known best practices. The hard parts are the decisions with no textbook right answer — how finely to split services, how to break apart a shared database, how to keep data consistent when it no longer lives in one place. These are trade-off analyses, not recipes.
Software Architecture: The Hard Parts frames the architect's real job as making these trade-offs explicit: identifying the forces that push a system apart and those that hold it together, and choosing deliberately rather than by fashion.
The concept
The Hard Parts, Ch. 4-7 (Granularity & Data)For service granularity, the book names two opposing sets of forces. Disintegrators are reasons to break a service into smaller pieces: service scope and function (single responsibility), code volatility (parts that change at different rates), scalability and throughput differences, fault tolerance (isolating failure), security needs, and differing data or access requirements. Integrators are reasons to keep or merge services: database transactions (needing consistency in one place), data dependencies, and workflow/choreography that would otherwise incur heavy communication. Right-sizing a service means balancing these opposing forces, not maximizing smallness.
For data decomposition, the book gives disintegrators (change control, connection management, scalability, fault tolerance, separation of concerns, independent deployability) and integrators (data relationships, database functions, and data consistency needs) for deciding whether to split a monolithic database into separate ones.
Once data is split, you face distributed data problems: how services access data they no longer own (data ownership, and patterns to read remote data), and distributed transactions, which cannot use ACID guarantees and instead rely on eventual consistency, sagas, and patterns to reason about consistency versus availability.
Worked scenario
The Hard Parts, Ch. 6-8 (Distributed Data & Transactions)A monolith bundles Order Management and Fraud Detection in one service. Two disintegrator forces argue for splitting them: Fraud Detection changes weekly (code volatility) and needs to scale independently at peak (scalability differences). But an integrator force pushes back: an order and its fraud check are currently updated in a single database transaction (transactional integrity).
The architect weighs these explicitly. If the business can tolerate the fraud check being eventually consistent — resolved slightly after the order is placed — the disintegrators win and the split proceeds. The team then decomposes the shared database, assigning Fraud Detection its own data, and replaces the lost ACID transaction with a saga and eventual consistency, accepting a well-understood window of inconsistency in exchange for independent deployability and scaling.
This is the recurring shape of the hard parts: name the forces, decide which dominate for this context, and pay the resulting trade-off knowingly.
How it connects
The Hard Parts, Ch. 12-13; Learning DDD; Building Evolutionary Architectures 2eService and data boundaries are where DDD's bounded contexts become physical deployables, and the distributed transactions here are managed with the sagas and compensating actions from Communication Patterns. The coupling created by data dependencies is measured by Architecture Metrics.
And because every split risks regressing coupling, latency, or contract compatibility, evolutionary fitness functions guard the decompositions the Hard Parts recommends — the topics form one continuous chain from strategy to runtime.
- Believing 'smaller is always better'. Disintegrators push services apart, but integrators (transactions, data dependencies, workflow) push back; right-sizing balances both, it does not maximize smallness.
- Thinking distributed transactions can keep ACID guarantees. Across service boundaries you generally trade ACID for eventual consistency managed by sagas — atomicity across services is not free.
- Splitting a database without addressing data ownership and access. Decomposition creates the new problem of how services read data they no longer own; ignoring it just moves the coupling into runtime calls.
- Service granularity balances disintegrators (scope, volatility, scalability, fault tolerance, security, data access) against integrators (transactions, data dependencies, workflow).
- Data decomposition splits a shared database only when disintegrator forces outweigh integrators like data relationships and consistency needs.
- Distributed data and transactions trade ACID for eventual consistency, handled with sagas and explicit data-ownership decisions.