Strategic Patterns

4 min read
Senior5 min read
Rapid overview

Strategic Patterns

TL;DR

  • Ubiquitous Language: same words used in code, tests, UI, and conversations with domain experts.
  • Bounded Context: the boundary inside which a single model and language apply.
  • Context Map: how bounded contexts relate (Shared Kernel, ACL, Open Host Service, …).
  • Core / Supporting / Generic subdomains drive where to spend engineering effort.

Why it matters

  • Strategic decisions made wrong produce years of pain. Tactical refactors fit in a PR.
  • You can defend a context boundary in a design meeting.
  • You can pick the right relationship pattern when integrating with another team.

How it works

Ubiquitous Language

A shared vocabulary between domain experts and developers — every term has one meaning inside a context and shows up identically in code, tests, and UI copy.

// Bad — code uses one word, business uses another
ticket.SetHighPriority(true);

// Good — vocabulary matches the business
ticket.Escalate(reason: EscalationReason.SlaBreach);

Rename in code when the business renames. Drift = stale model.

Bounded Context

The boundary inside which one model is consistent.

  • Each context owns its own database / schema / persistence.
  • Two contexts can have an entity named Customer with different attributes — that's fine. Don't merge them.
  • A team typically owns one or two contexts end-to-end.

How to find boundaries: where the language changes, where teams diverge, where invariants stop applying.

Context Map relationships

RelationshipMeaningWhen to use
Shared KernelTwo teams share a small subset of the model.Only when coordination cost is genuinely low.
Customer / SupplierDownstream depends on upstream; upstream considers downstream's needs.Trusted, cooperative teams.
ConformistDownstream takes upstream's model as-is, no translation.Upstream is stable and you don't mind their naming.
Anti-Corruption Layer (ACL)Downstream translates upstream's model into its own.Upstream is volatile, legacy, or outside your control.
Open Host ServiceUpstream publishes a stable protocol/API for many downstreams.One service feeds many.
Published LanguageA well-documented format (OpenAPI, JSON schema, Avro) — the contract.Pairs with Open Host Service.
Separate WaysNo integration. Each side solves its own problem.When integration cost exceeds the value.

Anti-Corruption Layer (ACL)

A translation layer that converts another context's (or a legacy system's) model into yours.

// Legacy CRM speaks this
public record CrmContact(
    string CONTACT_ID,
    string FIRST_NM,
    string LST_NM,
    string EM_PRIM,
    string ACT_FLAG);

// Our Billing context speaks this
public record Customer(
    CustomerId Id,
    string FullName,
    EmailAddress Email,
    bool Active);

// ACL — the only place that knows CRM's schema
public static class CrmContactMapper
{
    public static Customer ToCustomer(CrmContact raw) => new(
        Id: new CustomerId(raw.CONTACT_ID),
        FullName: $"{raw.FIRST_NM} {raw.LST_NM}".Trim(),
        Email: EmailAddress.Parse(raw.EM_PRIM.ToLowerInvariant()),
        Active: raw.ACT_FLAG == "Y");
}

If CRM renames a field, only the ACL changes. The domain stays clean.

Core / Supporting / Generic subdomains

TypeDefinitionInvestment
Core domainThe thing your company is better at than competitors.Custom-built. Best engineers. Deepest tests.
Supporting subdomainNecessary but not differentiating.Custom but lower investment.
Generic subdomainSame problem everyone has (auth, billing, mail).Buy or use OSS.

Strategic DDD says: spend tactical effort on the core. Don't model a payments processor from scratch when Stripe exists.


Detailed Explanation

Finding bounded contexts in practice

  1. Listen to the business. When the same concept is described with different words by different people, you're probably looking at two contexts.
  2. Find the seams. Where do teams hand off work? Where do invariants change?
  3. Test with the language. Pick a key term. Does it mean the same thing everywhere? If not, draw the boundary.
  4. Validate with a context map. Sketch the relationships before committing.

Sample context map for a SaaS platform

+----------------+   ACL   +-------------+   OHS+PL    +----------------+
| External CRM   |-------->| Sales       |------------>| Marketing      |
+----------------+         +-------------+             +----------------+
                                 |
                                 | Customer/Supplier
                                 v
                           +-------------+   Shared Kernel  +-------------+
                           | Billing     |<---------------->| Identity    |
                           +-------------+                  +-------------+
                                 |
                                 v ACL
                           +-------------+
                           | Fulfilment  |
                           +-------------+

Common pitfalls

  • One mega-context with everything in it ("the monolith model").
  • Shared Kernel everywhere because "we don't want duplication". The duplication is the point — it lets contexts evolve independently.
  • No published contract when many teams depend on you (becomes a moving target).
  • Sharing a database between contexts — coupling masquerading as integration.

Interview prompts

  • "How do you find bounded contexts in a new domain?"
  • "Two teams want to share a User model — when is a Shared Kernel a smell?"
  • "What's an Anti-Corruption Layer and when would you build one?"
  • "Same entity, different meaning in two contexts — what do you do?"

See also