This chapter offers a high-level intermission that shows how secure outcomes often emerge from solid domain design and collaboration. It uses a real incident to illustrate how a perfectly “working” set of components can combine into a broken system when concepts drift between domains. The message is that deliberate context mapping and cross-domain discovery act like a free insurance policy against subtle, securable failures—especially in architectures that split responsibilities across teams and services.
The story follows an insurance company that split a monolith into finance and policy services, then added a bank giro payment option. The bank produced three messages—Payment (request registered), Confirm (funds transferred), and Bounce (transfer failed or retried). Finance mapped the bank’s Payment to its own notion of payment and continued emitting the same event to the policy service. Policy, assuming “payment means paid,” extended coverage and mailed renewal letters on receipt. When some payments later bounced, customers still held renewal letters and coverage appeared active; a crash and court case ensued. The judge ruled for the customer, interpreting the company’s mailed letters as acceptance of an outstanding debt, exposing that no single part was obviously wrong—the fault lay in mismatched semantics across domains.
The remedy is deliberate discovery and precise context mapping: involve experts from banking, finance, and policy early; favor specificity before abstraction; and let ubiquitous language reflect true domain distinctions. Concretely, rename ambiguous concepts (for example, split Payment into CashPayment and GiroPayment), wait for confirmation of funds transfer, and publish a policy-centric event (such as PolicyPayment) only when money is actually received; have policy extend coverage based on that event, not on intent-to-pay. The broader lesson for microservices is to resist myopic, service-local changes: keep maps of neighboring contexts, align meanings at integration boundaries, and be willing to change technical contracts when semantics demand it.
Figure 11.1. When a payment is made, the insurance system mails a new policy letter.
Figure 11.2. A context map showing the one single context of the monolith.
Figure 11.3. Payment for an insurance policy, across the two domains of finance and policy
Figure 11.4. A Payment message arrives from the bank and is interpreted as a Payment by the finance system.
Figure 11.5. Mapping of a bank giro payment through the three domains: bank, finance, and policy
Figure 11.6. For some goods, it makes sense to take those back if payment isn’t made; for others, not so much.
Figure 11.7. A bank giro payment isn’t what you expect it to be.
Figure 11.8. A customer with a valid policy letter
Figure 11.9. What a system does can be interpreted as what it’s intended to do.
Figure 11.10. A map of the three domains after renaming Payment to CashPayment
Figure 11.11. A map of the three domains with the newly created GiroPayment. What should it map to?
Figure 11.12. The difference between early deliberate discovery and late ignorant discovery
Figure 11.13. A map of the three domains with complete mappings
Summary
- Do deliberate discovery early to get deep insights into subtle aspects of the domain.
- Start specific, then abstract later.
- Collect expertise from all adjacent domains.
- Refactor names if they change semantics, especially if they change semantics outside the bounded context.
Secure by Design ebook for free