pattern

Shared Kernel

also called Shared Model, Common Domain Library

A deliberately shared subset of the domain model between two contexts, which removes translation cost by accepting a shared release cadence - the one context relationship that couples teams on purpose.

domain driven designbounded contextscouplingrelease cadencecontext map

A context map describes how bounded contexts relate. Most of the relationships reduce coupling: customer-supplier with a published language, conformist, anti-corruption layer. Shared kernel is the one that increases it, on purpose.

Two contexts agree that a portion of the model — types, invariants, sometimes the code that implements them — is common and jointly owned. Neither may change it unilaterally. In exchange, neither pays for translation, and there is no possibility of the two representations drifting apart.

The price is explicit and unavoidable: a shared model means a shared release cadence for everything that touches it. That is not a defect to be engineered away; it is the deal.

Why it matters

It is the relationship teams adopt by accident and keep by inertia. A shared library starts as 3 of 3 types everybody genuinely needs. Every subsequent type that two contexts want is added, because adding to the shared library is always the smallest immediate step. Two years later nine contexts import it, releases must be coordinated, and nobody remembers choosing that.

Recognising it as a named pattern with a known cost is what makes the conversation possible: the question is not "should we share code" but "are we willing to release together".

Implementation patterns

  • Keep it to concepts with one organisation-wide meaning: money and currency arithmetic, tenant identity, time and time zones, identifier formats. These change rarely, so the coordination cost is near zero.
  • Give it joint ownership with an explicit change protocol — both teams approve, and the test suite of both runs before it merges.
  • Version it and allow a lag window. A kernel that must be upgraded in lockstep on the same day is a distributed monolith; one where consumers may be a version behind for two weeks is workable.
  • Measure it. Co-change analysis over 12 months shows which contexts genuinely share a model and which merely import one.
  • Write down what is not in it. The kernel grows by default; the only defence is a stated boundary and someone who enforces it.

Industry example

The pattern comes from Eric Evans' Domain-Driven Design (2003), which introduces it alongside the alternatives and is explicit that it is appropriate for closely aligned teams willing to coordinate. The failure it warns about is exactly what large estates report: a "common" library that every service imports, after which independent deployability — the property most service decompositions were undertaken to get — is gone while the diagram still shows separate services.

Failure scenarios

  • The universal kernel: nine of eleven relationships are shared kernel, releases are coordinated, and the contexts are packages in one model with a diagram around them.
  • Unilateral change: one team changes a shared type, another team's build breaks, and ownership is discovered during the incident.
  • Kernel creep: anything two teams need is added, so the kernel accumulates concepts that mean different things in each context.
  • Version lockstep: every consumer must upgrade on the same day, which is a distributed monolith with extra ceremony.
  • The wrong concept shared: Order in fulfilment and Order in billing are different things, and forcing one model gives both a type with fields the other ignores.

Trade-offs

Choose Gains Pays
Shared kernel No translation layer; no drift; one implementation of a tricky invariant Coordinated releases; joint ownership overhead; the kernel grows
Published language Independent deployment; each context models what it needs Translation code; the same concept represented two ways; drift is possible

When not to use it

When the two contexts are owned by teams that cannot or will not coordinate, the kernel becomes a source of blocked releases and inter-team escalation, and a published language with per-context models is cheaper even though it looks like duplication. And when the shared concept is a noun both sides use rather than a rule both sides enforceCustomer, Order, Product — sharing it forces one model onto two different sets of decisions, which is how eighty-field entities are born. Share invariants, not vocabulary.

Interview question

Q: You inherit a context map where nine of eleven relationships are shared kernel and the teams complain that every release must be coordinated. What do you change, what do you keep, and what evidence do you bring to the review?

What a strong answer covers: that coordinated releases are the pattern working as designed, so the problem is the choice and not the mechanism; converting most relationships to customer-supplier with a published language, or an anti-corruption layer where the downstream should not be shaped by the upstream; keeping one small kernel of genuine primitives; and bringing 12 months of co-change data rather than an opinion, because the boundary argument does not converge on aesthetics.

Quick check

Quiz: What does adopting a shared kernel between two contexts commit their teams to? A shared release cadence for everything that touches the kernel, which is the cost paid in exchange for having no translation layer and no model drift.

Flashcard: Which concepts belong in a shared kernel? Ones with a single organisation-wide meaning that rarely change — money arithmetic, tenant identity, time handling, identifier formats. Domain nouns like Order or Customer usually mean different things per context and should not be shared.