Modeling Shared Entities Across Bounded Contexts in Domain-Driven Design
Lalit Kale

Lalit Kale @lalitkale

About: Principal Software Engineer | Solution Architect | AWS Community Builder

Location:
Dublin, Ireland
Joined:
Oct 7, 2018

Modeling Shared Entities Across Bounded Contexts in Domain-Driven Design

Publish Date: May 25
1 0

Introduction

When modeling complex systems using Domain-Driven Design (DDD), one of the most common dilemmas architects and engineers face is:

“If two bounded contexts use the same concept — like a Customer — should they share a common model or have separate ones?”

Take, for example, Sales and Support systems within an organization. Both deal with a Customer, but they use that concept differently. So what’s the right way to model this scenario in line with DDD principles?

Bounded Context of Sales and Support

original context map image courtesy: https://martinfowler.com/bliki/BoundedContext.html

Let’s explore.


Understanding the Problem: Shared Concepts, Divergent Needs

In many organizations:

  • The Sales team cares about a customer's lead score, purchase intent, and assigned sales rep.
  • The Support team, on the other hand, is focused on support ticket history, SLA agreements, and incident timelines.

Clearly, while the term "Customer" is shared, its meaning and usage diverge across these contexts. This is a textbook case of polysemy in DDD — the same term having multiple meanings in different bounded contexts.


What Does DDD Recommend?

✅ Model Each Bounded Context Independently

Rather than forcing a single Customer entity to serve multiple masters, DDD encourages modeling the concept according to the specific domain's needs.

This means creating:

  • SalesCustomer in the Sales context.
  • SupportCustomer in the Support context.

Each entity will only contain the attributes and behavior relevant to its respective domain. They can be kept in sync using integration events or APIs.


Why Not Share a Single Customer Entity?

Sharing a single customer model across contexts may seem DRY and clean at first, but it introduces tight coupling, cross-team dependencies, and often leads to bloated models full of irrelevant attributes.

Problems with a Shared Model:

  • Code becomes harder to maintain.
  • Changes in one context impact others.
  • The model becomes a compromise that satisfies no one well.

Integration Through Events: The DDD Way

In a properly decoupled system, Sales might publish domain events such as CustomerCreated, CustomerUpdated, or LeadConverted.

Support consumes these events and updates its own SupportCustomer read model.

This keeps the systems loosely coupled and allows each to evolve independently.


Diagram: Visualizing the Pattern

DDD Context Map of Sales and Support

  • Each bounded context maintains its own Customer model.
  • Integration events (via Kafka, EventBridge, etc.) keep the models in sync.
  • The system respects context boundaries and encourages autonomy.

Other Modeling Strategies

In DDD, this scenario can also be approached through different integration patterns depending on organizational and technical constraints:

Pattern Description
Shared Kernel (discouraged but still valid in rare scenarios) Shared subset of the model agreed upon and versioned by both teams
Customer-as-a-Service One context exposes an API or event feed; others consume with translation
Anti-Corruption Layer Context-specific adapter to isolate internal models from external contracts

Practical Guidelines

  • Avoid modeling based on database schemas. Model based on domain semantics.
  • Treat duplication as an acceptable trade-off for autonomy and clarity.
  • Use ubiquitous language in each context; don’t force uniform terminology.
  • Synchronize data through events, not shared objects.

Final Thoughts

In Domain-Driven Design, context is king. Just because different domains refer to a Customer doesn’t mean they are talking about the same concept. Forcing a unified model creates fragility and limits agility.

Instead, embrace duplication, model explicitly, and integrate intentionally. That’s how you build robust, evolvable systems.

Comments 0 total

    Add comment