Landscapes
One map says what we agreed. The other says what is running. Neither is interesting alone.
A context map with no system map behind it is a wish that survives because nothing contradicts it. A system map with no context map above it is a network diagram — true, and unable to tell you which of its arrows should not exist. Draw both against the same catalog and the third artefact appears for free: a list of the places where the estate has quietly stopped implementing the business.
Landscapes
Context mapping
How the 9 bounded contexts are meant to relate, in the vocabulary of the strategic patterns: who is upstream, who conforms because they had no choice, where an anticorruption layer is doing real work. 11 relationships declared.
How the map is drawnSystem mapping
What the 9 running systems actually do to each other, observed rather than asserted: 11 integrations, each recorded with the evidence that found it and the mechanism it runs over.
How the evidence is gatheredConformance and drift
The difference between the two, as findings with owners. 5 of 11 integrations disagree with the model, and 1 declared relationships have nothing observed behind them.
How drift is judged
Where they disagree
5 findings
Each one is a sentence about the business, not about the wiring. “Claims reads the live policy” is an integration detail; “a claim can be assessed against cover that was added after the loss” is the same fact stated so that somebody who can authorise the fix understands it.
legacy-policy-masterclaims-platform
DriftsObserved: Claims queries the live policy tables 40,000 times a day. No snapshot table exists and no read is date-qualified.
Should realise: Policy lifecycleClaims
The anticorruption layer this relationship depends on has never been built. A mid-term endorsement silently changes the cover an open claim is assessed against. Highest-value fix in the estate: materialise a cover snapshot at notification and read only that.
legacy-policy-masteruw-workbench
UnmappedObserved: A nightly renewal batch reads appetite rules straight out of the underwriting schema, bypassing the service.
Should realise: nothing on the context map corresponds to this integration.
No relationship on the context map corresponds to this. Either the renewal pre-screen belongs to Risk appetite and should be asking for it properly, or the appetite rules belong to Policy lifecycle. Deciding is a modelling question, not an integration one.
crmlegacy-policy-master
DriftsObserved: Party records exported and matched on name and postcode. Match rate observed at 87%.
Should realise: Party and relationshipsPolicy lifecycle
A shared kernel implemented as an overnight fuzzy match is not a shared kernel. Either promote party identity to a real shared model with one identifier, or accept separate ways and stop pretending the two sides agree.
claims-platformbilling-saas
DriftsObserved: Vendor field names appear in claims-platform source. The adapter is bypassed.
Should realise: ClaimsBilling
Conformist is the agreed pattern, so conforming is not the problem — bypassing the shared adapter is. The vendor vocabulary is now inside a core context, and a vendor upgrade becomes a core-domain change.
policy-servicedoc-gen
UnobservedObserved: Nothing is collecting from doc-gen; this edge is asserted rather than observed.
Should realise: Policy lifecycleDocuments
Not a defect — an observability gap. Until the collector covers doc-gen, this row is somebody’s memory, and the conformance column for Documents stays "unknown".
The context map
Intent. The pattern column is the one that carries the information: customer/supplier and conformist describe the same arrow and differ only in whether the downstream team has any negotiating power, which is a political fact a generic “depends on” would hide. 9 of 9 catalogued contexts appear here.
| Upstream | Downstream | Pattern | What crosses | Why this pattern |
|---|---|---|---|---|
| Product catalogue | Rating | Open host service | Versioned product definitions: covers, limits, exclusions and their compatibility rules. | Product is consumed by five contexts with no two wanting the same shape. One published interface serving all of them is cheaper than five bespoke integrations, and it forces product to keep its language stable. |
| Product catalogue | Quotation | Open host service | The same versioned product definitions, pinned to the version a quote was made against. | A quote has to remain explicable after the product changes, so the version is part of what crosses the boundary rather than something resolved at read time. |
| Risk appetite | Quotation | Customer/supplier | An accepted Risk with its terms and any referral conditions attached. | Both teams sit under the same director, so quotation can genuinely ask for a change to the upstream model and get it. That is what makes this customer/supplier rather than conformist. |
| Rating | Quotation | Published language | A technical price with its rating factor breakdown and the rate table version used. | The breakdown is read by quotation, by the regulator, and by the actuarial review. A published schema is the only version of this that survives three audiences. |
| Quotation | Policy lifecycle | Customer/supplier | An accepted offer, which becomes an inception. | The handover where a commitment becomes an obligation. Policy administration is downstream and says so, but has a real say in the shape of what it receives. |
| Policy lifecycle | Claims | Anticorruption layer | A cover snapshot as at the date of loss — deliberately not the live policy. | Claims must never see a policy change made after the loss. The layer exists to make that impossible rather than to make it unlikely, and it is currently the most-violated rule in the estate. |
| Party and relationships | Policy lifecycle | Shared kernel | Party identity and the roles a party plays on a policy. | A shared kernel because both contexts write to the same notion of identity and neither can be made downstream of the other without a lie. It is the most expensive pattern on this map and it is chosen knowingly. |
| Policy lifecycle | Billing | Conformist | Premium due, instalment plan, and any mid-term adjustment. | The billing package will not change its model for us and we will not fork it, so downstream conforms. Recorded honestly as conformist rather than dressed up as customer/supplier. |
| Claims | Billing | Conformist | Settlement payments and recoveries. | Same package, same trade-off. |
| Policy lifecycle | Documents | Anticorruption layer | A render request: template identifier plus a payload in our language. | The vendor template vocabulary is not ours and must not become ours. The adapter is small, boring and owned by us. |
| Risk appetite | Rating | Partnership | Appetite signals that change the price, and prices that change the appetite. | The only genuine partnership on the map: neither side can succeed if the other fails, and the two models are changed in the same conversation. Both report to a joint monthly review. |
1 declared relationship has nothing observed behind it.Risk appetite → Quotation. Either the integration exists and the collector cannot see it, or the relationship was agreed and never built. The two have very different owners, and the map cannot tell them apart on its own.
The system map
Reality, across 9 systems: billing-saas, claims-platform, crm, doc-gen, legacy-policy-master, policy-service, product-service, rating-engine, uw-workbench. Every row carries the observation that produced it, so a reader who doubts one can go and check it — which is the difference between a map and a diagram.
| From | To | Transport | Evidence | Verdict |
|---|---|---|---|---|
| product-service | rating-engine | HTTP, versioned REST resources | Continuous request traffic; every call carries an explicit product version. | Matches |
| product-service | uw-workbench | HTTP, versioned REST resources | Same interface as rating-engine consumes; no bespoke endpoints observed. | Matches |
| rating-engine | uw-workbench | HTTP, published JSON schema | Schema in the registry matches the payloads on the wire; no undeclared fields. | Matches |
| uw-workbench | policy-service | Domain events on the broker | OfferAccepted consumed within seconds; inception created downstream. | Matches |
| legacy-policy-master | claims-platform | Shared database schema, direct reads | Claims queries the live policy tables 40,000 times a day. No snapshot table exists and no read is date-qualified. | Drifts |
| legacy-policy-master | uw-workbench | Database link, direct reads of the appetite tables | A nightly renewal batch reads appetite rules straight out of the underwriting schema, bypassing the service. | Unmapped |
| crm | legacy-policy-master | Nightly CSV export | Party records exported and matched on name and postcode. Match rate observed at 87%. | Drifts |
| policy-service | billing-saas | HTTP, vendor API behind our adapter | All calls pass through the adapter; no vendor vocabulary observed upstream of it. | Matches |
| claims-platform | billing-saas | HTTP, vendor API, called directly | Vendor field names appear in claims-platform source. The adapter is bypassed. | Drifts |
| policy-service | doc-gen | HTTP, adapter owned by us | Nothing is collecting from doc-gen; this edge is asserted rather than observed. | Unobserved |
| uw-workbench | rating-engine | HTTP, synchronous | Bidirectional traffic with rating-engine calling back for appetite context. | Matches |
Collection is not deployed yet, so the evidence column is a worked example of what the collector would write rather than what it has written. Thetools pagesays what it would take.