Index

A Context Map Must Say What the Arrow Means

The cancellation workshop ends with three boxes: Orders, Payments, and Fulfilment. Someone connects them in event order. The diagram looks plausible.

It is also impossible to read.

Does the arrow mean an HTTP request, a domain event, a dependency, ownership, or influence over another model? Does it describe the system that exists or the one the team hopes to build? Who translates “refund declined” into an order state? The line answers none of these questions.

An EventStorming wall shows a process unfolding over time. A context map earns its place when it preserves a different view: where meaning changes, which model influences another, how information currently crosses the boundary, and what remains unknown.

The wall answers when; the map answers where

Consider this deliberately synthetic workshop fragment:

Cancellation approved
    ├─▶ Refund requested ─▶ Refund completed / Refund declined
    └─▶ Inventory release requested ─▶ Inventory released

The sequence is useful, but it does not establish a model boundary. Support uses “cancellation approved” for a case decision. Orders uses “cancelled” for whether an order may continue towards fulfilment. Payments owns “refund completed” and “refund declined.” These phrases are related without being synonyms.

The distinction matters because a chronological arrow and an influence arrow can point in opposite directions. Orders sends a refund request to Payments, but Payments controls the refund model and provider integration. A change to that model forces Orders to adapt more often than an order-specific preference forces Payments to change. For that relationship, Payments is upstream and Orders is downstream even though the request travels from Orders to Payments.

Context Mapper’s language reference makes this precise: its upstream-to-downstream arrow represents influence flow. It also keeps implementation technology and downstream governance rights as separate relationship properties. Message direction is not a substitute for either.

Give the map one question

“Map the domain” is too broad to decide what belongs on the page. The DDD Crew’s Context Mapping guidance recommends small maps for explicit questions and separate maps for different perspectives.

For the cancellation example, the question is:

Where does cancellation meaning change, and who absorbs a change in refund behavior?

That question excludes most of the system on purpose. Customer search, shipping rates, invoicing, and warehouse layout may matter to other maps. Adding them here would make the picture more complete and the answer harder to find.

The companion evidence fixture starts with 21 synthetic observations. Each observation has a stable identifier, source category, confidence, and one disposition into the map. Four candidate contexts survive that transformation:

ContextMeaning it owns in this questionBoundary evidence
Case ManagementA support case has approved cancellation processing.Support workflow language and ownership.
Order ManagementAn order may no longer continue towards fulfilment.Order policy, stored state, and lifecycle ownership.
PaymentsA provider accepted or declined a refund.Refund language, API control, and provider integration.
FulfilmentAllocated inventory has been released.Release behavior and warehouse-system ownership.

They remain bounded-context hypotheses. Nothing in the workshop observations proves that they should become four services. A module boundary in one Laravel deployment can test the language and translation seam before a team accepts network failure, independent delivery, and operational ownership.

One relationship needs at least two directions

The Payments relationship becomes readable only after model influence and information flow are written separately:

Model influence
Payments ─────────────────────────────▶ Order Management

Information flow
Order Management ── refund request ──▶ Payments       (HTTPS)
Order Management ◀─ refund outcome ─── Payments       (webhook)

The structured form carries details that the lines cannot:

{
  "upstream": "payments",
  "downstream": "order-management",
  "influence": { "evidence": ["OBS-10"] },
  "information_flows": [
    {
      "direction": "order-management_to_payments",
      "mechanism": "HTTPS request"
    },
    {
      "direction": "payments_to_order-management",
      "mechanism": "provider webhook"
    }
  ],
  "translation_owner": "order-management",
  "progress_expectation": "refund outcome arrives after the request",
  "hotspots": ["HS-01", "HS-02"],
  "state": "as_is"
}

OBS-10 records the premise behind the influence direction: Payments controls its refund API and does not automatically accept order-specific model changes. Without that evidence, the arrow is a guess with a confident arrowhead.

The relationship does not need a Customer/Supplier, Conformist, or Anticorruption Layer label yet. Those names carry claims about planning influence and translation strategy. Naming one before the corresponding organizational evidence exists would hide the missing decision.

Put translation and progress on the boundary

Orders must turn provider outcomes into order policy. That makes Order Management the translation owner for this relationship. If the provider adds refund_reversed, changes the meaning of a decline, or returns a state Orders does not understand, the adapter is where that mismatch becomes visible.

Translation ownership is different from transport ownership. Payments may own the webhook endpoint contract while Orders owns the decision that a completed refund permits final cancellation. Both facts belong near the relationship.

So does progress. The refund request and provider outcome do not form one atomic transaction. A map which says only “Orders integrates with Payments” conceals the interval in which the order is waiting, the webhook may be redelivered, and recovery may require a person. The map need not solve those behaviors, but it must not imply synchronous completion where none exists.

Keep the coupling nobody wants

The synthetic current system writes cancelled_at before the payment provider returns a refund outcome. Finance’s account says a paid order remains active until the refund clears. The storage model and the stated policy disagree.

It is tempting to omit the early write and draw the event-driven flow the team intends to build. That produces a cleaner diagram by deleting the reason for changing the system.

The primary map therefore stays as_is and retains the early write as a current constraint. Context Mapper distinguishes AS_IS and TO_BE states for the same reason: a desired relationship is not evidence of a current one. A target map may follow, but readers should never have to guess which state they are looking at.

An open hot spot is part of the result

Three questions remain open in the fixture:

  • When may a paid order become visibly cancelled?
  • What state follows a declined refund?
  • Does inventory release wait for refund completion?

Each hot spot records the observations which created it, its consequence for the map, an owner or unassigned, and the next evidence action. The EventStorming Rush to the Goal pattern treats hot spots as deferred complexity that must be revisited, not discarded. Its Deliverable Obsession pattern likewise describes the workshop output as a draft model rather than a complete record of the learning.

This is why unassigned is more honest than an invented owner and open is more useful than a plausible answer. Refund-decline behavior could change the Order Management state model. Inventory timing could change the relationship between Orders, Payments, and Fulfilment. Hiding either question would make the map easier to present and less useful for deciding what to investigate next.

Try to make the map lie

A map is not trustworthy merely because its JSON validates. The fixture runs 12 isolated counterfactuals against the transformation. Among them:

  • infer a context directly from a sticky-note cluster;
  • reverse upstream and downstream to follow the HTTPS request;
  • remove the translation owner;
  • hide the early cancelled_at constraint;
  • mark the declined-refund hot spot answered without new evidence;
  • call the relationship Customer/Supplier without planning-influence evidence;
  • turn every context hypothesis into an independently deployed service; and
  • orphan one workshop observation.

All 12 must fail. The retained verifier also requires all 21 observations to reach a context, relationship, constraint, hot spot, or hypothesis. This does not prove that the synthetic boundaries are correct for a real organization. It proves something narrower and useful: the rendered map cannot silently drop the evidence, reverse the declared influence, or convert uncertainty into fact.

The DDD Reference describes a Context Map in terms of the actual relationships between bounded contexts. “Actual” is doing important work. A reproducible transformation can keep those claims internally consistent; only observation, ownership, code inspection, and change history can establish them for a real system.

A table may be the more honest map

A diagram helps when several relationships must be compared spatially. A relationship table is often better when the decision depends on influence, translation, transport, progress, and unresolved evidence. Use both when each adds a view, but keep one structured source authoritative.

The map is ready to guide the next investigation when a reader can answer:

  1. What single question is this map answering?
  2. Which meaning and model does each context own?
  3. Why is one side upstream for this relationship?
  4. What information crosses the boundary, and how?
  5. Who absorbs translation when the upstream model changes?
  6. Which ugly current constraints remain visible?
  7. What evidence would resolve each open hot spot?

If the answer to an arrow is still “these systems talk,” keep the arrow off the map. Record the information flow separately, gather the missing influence and ownership evidence, and let the uncertainty remain visible. An unfinished map with explicit questions can guide a decision. A polished line with no declared meaning can only decorate one.