Context mapping
A context map documents how bounded contexts integrate. The patterns — Shared Kernel, Customer/Supplier, Conformist, ACL, Open Host Service — describe team relationships and translation strategies, not just API shapes.
The B2B order platform’s Sales context was calling a third-party tax-calculation service. The service had its own model of “products” — it called them “taxable items,” with a commodityCode, a taxJurisdiction, and a lineNetAmount. The Sales context had its own model of a LineItem with a NegotiatedPrice and a productId. The developer integrating the two contexts took the path of least resistance: they used the tax service’s object model directly in the Sales context. The LineItem class grew a commodityCode field. The Quote service method that called the tax service began returning the tax service’s TaxCalculationResult directly to the rest of the Sales context. Within three months, the entire Sales codebase was scattered with commodityCode and taxJurisdiction fields that meant nothing to any Sales domain expert. When the tax service provider changed their API — replacing taxJurisdiction with a jurisdictionCode enum — the change propagated into the Sales context’s core domain model. A Sales feature change required understanding the tax service’s object model. The Sales context had been corrupted by the tax service’s language. This is what Evans calls “model corruption through integration.” When two bounded contexts integrate without an explicit translation layer, the upstream model leaks into the downstream context. The downstream context’s ubiquitous language is gradually replaced by the upstream’s language. The context boundary dissolves. The context map is the strategic tool that prevents this: a diagram and a set of named patterns that describe not just how contexts communicate, but what power relationship they have and what translation strategy they use.
What a context map is
A context map is a strategic overview of the bounded contexts in a system and the relationships between them. It answers:
- Which contexts exist?
- How does each context integrate with the others?
- What is the team relationship at each integration point?
- What translation strategy prevents model corruption?
The context map is not an architecture diagram of services or APIs. It is a team and model diagram. The arrows on a context map carry labels that describe organizational and modeling relationships — Shared Kernel, Customer/Supplier, Conformist, Anticorruption Layer — not just “calls” or “sends event to.”
The B2B platform’s context map includes: Sales, Billing, Shipping, Product Catalog, Tax Calculation (external). Each pair of contexts that integrates has a labeled relationship. The label determines how teams interact and how models translate.
The integration patterns
Shared Kernel
Two contexts share a small, explicitly agreed subset of the domain model. Both teams own the shared piece — changes to it require coordination between both teams. This is the tightest coupling and the highest coordination cost.
Use it when: two contexts genuinely share a core concept that would be expensive to duplicate or translate. In the B2B platform, the Money value object (amount + currency) might be a shared kernel element — both Sales and Billing need it, it is stable, and having two separate Money implementations that could silently differ is dangerous.
Avoid it for: anything that evolves at different rates in each context. A shared kernel that one team wants to change and the other does not creates a coordination bottleneck.
Customer/Supplier
One context (the Supplier) produces data or services that another (the Customer) consumes. The Supplier’s model defines the interface. The Customer adapts to it. But critically, the relationship is negotiated: the Customer can request changes, the Supplier considers them, and the interface evolves with explicit coordination.
This is the most common pattern between internal teams. In the B2B platform, Product Catalog is a Supplier to Sales: Sales consumes catalog data. The Product Catalog team maintains the API; the Sales team can request additions or changes; the Catalog team prioritizes and schedules them.
The power relationship matters. If the Supplier team ignores the Customer team’s needs, the Customer team is forced to work around the Supplier’s model — which often leads to model corruption in the Customer context.
Conformist
The Customer context has no leverage over the Supplier. The Supplier will not change its interface to suit the Customer. The Customer simply conforms: it adopts the Supplier’s model as-is, including its language, its object shapes, and its lifecycle. The Customer context’s ubiquitous language is subordinated to the upstream’s language.
This is the right choice when: the Supplier is a large external system with no interest in your needs (a SaaS platform, a third-party data feed), AND the Supplier’s model is reasonable enough to use directly, AND the cost of building a translation layer exceeds the benefit of keeping your own model.
The B2B platform might be Conformist with respect to a payment processor — if the processor’s API is stable and its model of “payment,” “charge,” and “refund” maps cleanly enough to Billing’s concepts, conforming may be pragmatic.
The danger: once you conform, you have imported the upstream’s ubiquitous language into your context. Your model now evolves at the Supplier’s pace. Model drift in the upstream propagates directly into your context.
Anticorruption Layer (ACL)
The Customer context translates between the Supplier’s model and its own model, protecting its own ubiquitous language. The ACL is an explicit translation component — it lives at the integration boundary, speaks the Supplier’s language on the outside, and the Customer’s language on the inside.
This is the pattern the B2B platform’s Sales context should have used with the tax service. The ACL would translate: LineItem → TaxableItem (when calling the tax service), TaxCalculationResult → QuoteTaxSummary (when returning the result to Sales). The Sales context’s model never sees commodityCode or taxJurisdiction. The ACL absorbs the translation.
The ACL is the default choice when integrating with external systems whose model you do not control and whose language differs significantly from your own.
▸Why this works
Why “anticorruption”? Because the alternative — letting the upstream model leak into your context — is described by Evans as “corruption” of your domain model. The Conformist pattern is a deliberate choice to accept that corruption because the cost of building a translation layer is not justified. The ACL is the explicit rejection of that corruption: we will spend the engineering effort to maintain our own model rather than let the upstream’s language replace ours. The cost of an ACL is real (translation code to write, maintain, and test). The benefit is that your context’s model remains yours — it evolves in response to your domain experts, not in response to your upstream’s API changes.
Open Host Service (OHS) and Published Language (PL)
When a context is a Supplier to many downstream contexts, it can formalize its integration interface as an Open Host Service: a well-defined protocol that any downstream can integrate with, without requiring custom negotiation. The OHS is stable, versioned, and designed for consumption by multiple consumers.
A Published Language is the formal, well-documented data format used by the OHS — typically a versioned event schema, a public API contract, or a standard format. In the B2B platform, the Product Catalog context might expose a Published Language of product events (ProductCreated, ProductPriceChanged, ProductDiscontinued) with a stable schema that Sales, Billing, and Shipping all consume. The schema is versioned; breaking changes are communicated in advance.
The OHS + PL pattern reduces the coordination overhead of the Customer/Supplier relationship at scale — the Supplier does not negotiate with each customer individually; it maintains a published contract.
Reading a context map: power and translation
The most important thing a context map communicates is not the API topology — it is the power relationship between teams and the translation strategy at each boundary.
Power relationship: in a Customer/Supplier relationship, the Supplier has leverage. If the Supplier is responsive and the teams have good communication, the Customer can evolve. If the Supplier is unresponsive (a large platform team with many customers), the Customer eventually becomes Conformist by default — they cannot get changes they need, so they adapt their model to the Supplier’s constraints.
Translation strategy: ACL means “we translate at the boundary, our model is protected.” Conformist means “we have accepted the upstream model.” Shared Kernel means “we jointly own this piece.” These choices have compounding consequences over years. A team that was Conformist ten years ago now has an internal model deeply coupled to an upstream service’s 2015 API design.
▸lesson.inset.note
The context map is not a one-time diagram. It should be updated when: a new integration is added, a relationship changes (a Customer/Supplier becomes Conformist because the Supplier stops responding), or a context is split or merged. The map is a living document of the team’s organizational and architectural decisions. A stale context map is as harmful as stale code comments — it describes a system that no longer exists.
The Sales context is integrating with an internal Inventory context. The Sales team wants to check product availability before confirming a Quote. The Inventory team says: 'Use our API directly — just call our InventoryItem endpoint and use the InventoryStatus enum we return.' The Sales tech lead says: 'We need an ACL here.' The Inventory team pushes back: 'Why add translation overhead for an internal service? It's wasteful.' How do you decide?
The Product Catalog context publishes a `ProductPriceChanged` event with a schema versioned as v1. Six months later, the Catalog team wants to add a `previousPrice` field to the event. Sales and Shipping are both consumers. What does the Open Host Service / Published Language pattern require the Catalog team to do?
Two years ago the Billing context became Conformist to an internal Payments context, importing the Payments team's `PaymentMethod`, `ChargeResult`, and `RefundPolicy` types directly into Billing's domain model. The Payments team has now been acquired by another company and their service is being replaced with a third-party processor. The Billing context must migrate. Why is this migration significantly harder than it would have been if Billing had used an ACL?
- 01What is a context map, and what does it communicate beyond API topology?
- 02What is the difference between Conformist and Anticorruption Layer, and when is each appropriate?
- 03What is the Open Host Service pattern, and how does it reduce coordination overhead compared to Customer/Supplier?
The opening story’s model corruption — Sales context filled with commodityCode and taxJurisdiction from an external tax service — was not an accident. It was the predictable result of integrating without a named strategy. The developer took the path of least resistance: use the upstream model directly. The bounded context boundary dissolved.
A context map names the strategy at every integration point. Shared Kernel: both teams co-own a small piece. Customer/Supplier: negotiated interface, downstream has leverage. Conformist: downstream accepts the upstream model consciously. ACL: downstream translates at the boundary and protects its own model. Open Host Service: upstream publishes a stable versioned contract for multiple consumers.
Each pattern describes a team relationship, not just a technical shape. The ACL’s value is not avoiding code — it is making the upstream change’s blast radius a single translation component rather than the entire domain model. Conformist’s danger is not theoretical — it materializes when the upstream’s model changes years later.
The context map is drawn once and updated continuously. It is the strategic picture that tells every team: here is who you depend on, how much power you have, and what your model protection strategy is.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.