Skip to content
kc@kumarChandrachooda.com:~$ cd /blog/the-context-map-they-drew && read --section="top" 0%
Architecture

The Context Map They Drew

ADR 03 declares six relationship patterns across ten bounded contexts and gives a reason for each - read on its own terms, before any code is checked against it.

By Kumar Chandrachooda 17 Nov 2025 7 min read
Ten boxes and the labelled lines between them, drawn before the code

Most context maps I have seen in the wild are drawn after the fact by someone trying to explain a system they did not design, and every line on them says the same thing: “calls”. Boxes and arrows, arrows labelled with a protocol if you are lucky. That is a dependency diagram, not a context map. A context map's job is to record the social and organisational relationship between two teams' models — who may impose a contract on whom, who has to absorb the other side's vocabulary, who translates.

Part 2 walked the eight modules and their three architectures. This part reads ADR 03, 03-wspolpraca-z-innymi-modulami.md — “Collaboration with other modules” — on its own terms. No code yet. The next part goes looking for the code, and the diff between the two is the point; but you cannot diff a document you have not read carefully.

The picture and the rule behind it

03-wspolpraca-context_map.PNG is checked into the repository next to the ADR that references it by relative path. It puts Sales in the middle as a wide box — visually the core domain, and the ADR says so in prose: Sales is “our core area and simultaneously the most active when it comes to integration with other modules”.

Ten context boxes surround or contain it: Backoffice, IAM, Customer Service, Time Management, Communication, Sales, Post-Sales, Finance, Inquiries, Workload Management. Two further shapes are drawn as gear icons rather than boxes — Email Service and Payment Gate — the visual convention for something outside the organisation's model entirely.

Every line carries a label, and the labels are Evans' relationship patterns:

Edge Label on the map
Sales ↔ Time Management OHS + PL on Time Management, PL on Sales
Sales ↔ Communication OHS + PL on Communication, PL on Sales
Sales ↔ Workload Management OHS + PL on Workload Management, PL on Sales
Sales ↔ Finance OHS + PL on Finance, PL on Sales
Sales ↔ Inquiries PARTNERSHIP
Sales ↔ Post-Sales SUPPLIER on Sales, CUSTOMER on Post-Sales
Backoffice → Sales CONFORMS
Customer Service → Sales CONFORMS
IAM → Sales CONFORMS
Communication → Email Service ACL
Finance → Payment Gate ACL

Two details are easy to miss on a first look. Communication's and Workload Management's OHS + PL connectors do not terminate at Sales — each fans out to a small bus that reaches both Sales and Post-Sales. And Time Management is itself a consumer of Communication, with its own PL connector. The map is not a hub and spoke; the supporting contexts talk to each other.

The decision, in the ADR's own words

The ADR's ## Decyzja section splits the world in two and gives a reason for each half, and the reasons are better than the diagram.

For the modules collaborating as Open Host Service, translated:

In the case of modules collaborating with us on an Open Host Service basis, we cannot impose a contract nor a means of communication, because we are not the only (present or planned) consumer.

And so, it says, we must adapt to that module's contract — optionally closing the complexity of the remapping on our side — and be the active party: we are the ones who request that an operation be performed, synchronously or asynchronously, using the contract that module publishes. Named: Time Management, Communication, Workload Management, Finance.

For the dependent modules — Partnership, Conformist, Supplier-Customer — translated:

In the case of modules dependent on us in some way, we can allow ourselves (depending on our “standing” in the relationship) to impose the contract and the means of communication.

Here we impose the contract of our public API on consumers, optionally taking their needs into account for Partnership and Supplier-Customer, and we expect them to be the active party — either explicitly requesting an operation, or reacting to our events by performing operations we need. Named: Backoffice, Inquiries, Post-Sale.

That “who is the active party” test is the most useful sentence in the whole ADR. It converts an abstract relationship label into something you can check by opening a file. If Sales is downstream of Time Management, Sales must be the caller. If Backoffice is downstream of Sales, Backoffice must be the one subscribing. The map does not just describe a shape; it predicts a direction of initiative, and directions of initiative show up in code as ProjectReference edges and event-handler placement. That is what makes part 4 possible at all.

What each label commits you to

If you have not spent time with these patterns, here is what the map is promising, in the order they appear.

Open Host Service plus Published Language. The upstream context publishes a stable, documented protocol and a shared vocabulary for it, and it does so for everyone, not for you. The commitment is asymmetric: the provider owes stability to a population of consumers, and the consumer owes the provider nothing except using the published shape. In this estate that translates directly into the seven <Module>.Shared contract projects — a published assembly per module, which is part 7.

Published Language on the downstream side. Notice the map labels Sales' end of those four edges with a bare PL. That is a claim that Sales speaks the other module's language rather than translating it at the border. It is deliberate and it is the cheaper option, and it has a cost that shows up much later: when a downstream context adopts an upstream vocabulary without an anti-corruption layer, upstream's types get into your model. They do here. Nine files under Sales.Domain import Communication.Shared.Models and construct a Message — a type owned by a different bounded context — inside the Sales domain model.

Partnership. The strongest and most expensive relationship: two contexts succeed or fail together, coordinate their releases, and negotiate the contract jointly. Drawn here between Sales and Inquiries, in green, the only edge on the map with that label.

Supplier-Customer. Upstream is still in charge but has an obligation to the downstream context's requirements; the downstream context gets a seat at the planning table. The ADR spells the standing out for the Postsale case in ADR 04: Sales will be “the more important party”, and Postsale gets a public API in a Supplier-Customer relation so it can apply its finished change back onto a reservation.

Conformist. The downstream context adopts the upstream model wholesale with no translation and no negotiating power. Three contexts get this label: Backoffice, Customer Service, IAM. It is the cheapest downstream posture and the one with the least protection — you inherit upstream's model, including the parts you did not want.

Anti-corruption layer. Drawn only twice, and only where the line leaves the organisation: Communication → Email Service, Finance → Payment Gate. That is exactly where an ACL earns its keep. Inside the boundary you control both ends and can afford shared contracts; across a process or vendor boundary you cannot, so you translate. The estate honours this one: Finance.Core/External/IPaymentGatewayFacade.cs is the port, Finance.Api/ExternalServices/FakePaymentGatewayFacade.cs is the adapter, and SetUpPaymentWithMetadata is deliberately duplicated on both sides of the process boundary rather than shared. It is the one place in the estate that copies a contract instead of sharing it, and it is the correct place.

The stated benefit, and the thing it does not claim

The ADR's ## Oczekiwany wynik — expected outcome — is disarmingly modest:

An explicitly declared collaboration model together with examples of expected integrations will allow us to limit the risk of decision paralysis of the “who, what and how should do it” variety.

Not correctness. Not decoupling. Not testability. The claimed benefit is that nobody has to relitigate the direction of an integration in a stand-up, because the direction was decided once and written down with an approver's name on it. Having watched teams burn a fortnight on precisely that argument, I think this is an undersold claim rather than an oversold one.

What the ADR conspicuously does not do is name an enforcement mechanism. There is no test that fails when Backoffice stops conforming. There is no lint rule that notices a Partnership edge has become one-directional. The map is a promise between people, and the ADR that governs project references — part 6 — chose the same posture on purpose. When a promise between people is your only enforcement, the interesting question is not whether it will drift, but how you would find out.

There is a way to find out, it takes about twenty minutes, and it needs nothing but the .csproj files and a grep. Next, the context map the compiler drew.