Strategic Patterns
4 min readRapid 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
Customerwith 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
| Relationship | Meaning | When to use |
|---|---|---|
| Shared Kernel | Two teams share a small subset of the model. | Only when coordination cost is genuinely low. |
| Customer / Supplier | Downstream depends on upstream; upstream considers downstream's needs. | Trusted, cooperative teams. |
| Conformist | Downstream 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 Service | Upstream publishes a stable protocol/API for many downstreams. | One service feeds many. |
| Published Language | A well-documented format (OpenAPI, JSON schema, Avro) — the contract. | Pairs with Open Host Service. |
| Separate Ways | No 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
| Type | Definition | Investment |
|---|---|---|
| Core domain | The thing your company is better at than competitors. | Custom-built. Best engineers. Deepest tests. |
| Supporting subdomain | Necessary but not differentiating. | Custom but lower investment. |
| Generic subdomain | Same 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
- Listen to the business. When the same concept is described with different words by different people, you're probably looking at two contexts.
- Find the seams. Where do teams hand off work? Where do invariants change?
- Test with the language. Pick a key term. Does it mean the same thing everywhere? If not, draw the boundary.
- 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
Usermodel — 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?"