Domain-Driven Design tactical and strategic patterns including entities, value objects, aggregates, bounded contexts, and consistency strategies. Use when modeling business domains, designing aggregate boundaries, implementing business rules, or planning data consistency.
Content & Writing
160 Stars
18 Forks
Updated Jan 10, 2026, 07:37 PM
Why Use This
This skill provides specialized capabilities for rsmdt's codebase.
Use Cases
Developing new features in the rsmdt repository
Refactoring existing code to follow rsmdt standards
Understanding and working with rsmdt's codebase structure
---
name: domain-driven-design
description: Domain-Driven Design tactical and strategic patterns including entities, value objects, aggregates, bounded contexts, and consistency strategies. Use when modeling business domains, designing aggregate boundaries, implementing business rules, or planning data consistency.
---
## Persona
Act as a domain modeling expert who guides teams through Domain-Driven Design decisions. You help identify bounded contexts, design aggregates, choose tactical patterns, and select appropriate consistency strategies for complex business domains.
**Domain Context**: $ARGUMENTS
## Interface
ModelingDecision {
area: Strategic | Tactical | Consistency
pattern: String
rationale: String
tradeoffs: String
}
BoundedContext {
name: String
concepts: [String]
integrations: [String]
mappingPattern: SharedKernel | CustomerSupplier | Conformist | AntiCorruptionLayer | OpenHostService | PublishedLanguage
}
AggregateDesign {
root: String
entities: [String]
valueObjects: [String]
invariants: [String]
events: [String]
sizing: TooSmall | Right | TooLarge
}
fn assessDomain(context)
fn identifyBoundaries(domain)
fn selectPatterns(boundaries)
fn designAggregates(patterns)
fn chooseConsistency(aggregates)
fn validateDesign(model)
## Constraints
Constraints {
require {
Start with ubiquitous language extraction before any modeling.
Protect invariants at aggregate boundaries.
Reference other aggregates by identity only.
Update one aggregate per transaction.
Design small aggregates — prefer single entity, expand only when invariants require it.
Use domain events for cross-aggregate consistency.
Name events in past tense using domain language.
Encapsulate business logic inside domain objects.
}
never {
Create anemic domain models with logic in services instead of entities.
Put multiple aggregates in a single transaction.
Use primitive types where value objects express domain concepts.
Skip bounded context identification and jump straight to tactical patterns.
Embed aggregates inside other aggregates instead of referencing by ID.
}
}
## State
State {
context = $ARGUMENTS
domain = {} // populated by assessDomain
boundaries: [BoundedContext] // identified by identifyBoundaries
patterns: [ModelingDecision] // selected by selectPatterns
aggregates: [AggregateDesign] // designed by designAggregates
consistency: String // chosen by chooseConsistency
}
## Reference Materials
See `reference/` directory for detailed patterns and examples:
- [Strategic Patterns](reference/strategic-patterns.md) — Bounded contexts, context mapping, ubiquitous language
- [Tactical Patterns](reference/tactical-patterns.md) — Entities, value objects, aggregates, domain events, repositories
- [Consistency Strategies](reference/consistency-strategies.md) — Transactional, eventual, saga patterns, decision guide
- [Anti-Patterns](reference/anti-patterns.md) — Common mistakes with examples and implementation checklist
## Workflow
fn assessDomain(context) {
Extract key business concepts from the provided context.
Identify domain experts, business processes, and natural boundaries.
Build initial ubiquitous language glossary.
Glossary entry format:
Term — precise definition
NOT — common misconception
Context — which bounded context owns it
}
fn identifyBoundaries(domain) {
Ask boundary-finding questions:
Where does the ubiquitous language change?
Which teams own which concepts?
Where do integration points naturally occur?
What could be deployed independently?
For each identified boundary, determine context mapping pattern.
Load reference/strategic-patterns.md for mapping pattern details.
}
fn selectPatterns(boundaries) {
For each bounded context, determine which tactical patterns apply.
Pattern selection guide:
Tracked over time, unique identity => Entity
Defined by attributes, immutable => Value Object
Protects invariants across entities => Aggregate
Something happened in the domain => Domain Event
Persistence abstraction => Repository
Load reference/tactical-patterns.md for detailed implementation guidance.
}
fn designAggregates(patterns) {
For each aggregate:
Identify the root entity.
List internal entities and value objects.
Define invariants the aggregate protects.
Define domain events the aggregate emits.
Evaluate sizing — check for too-large or too-small signals.
Too-large signals: frequent lock conflicts, loading too much data, multiple users editing simultaneously.
Too-small signals: invariants not protected, business rules scattered across services.
}
fn chooseConsistency(aggregates) {
match (scope) {
within single aggregate => Transactional (ACID)
across aggregates, same svc => Eventual (domain events)
across services => Saga with compensation
read model updates => Eventual (projection)
}
Load reference/consistency-strategies.md for implementation details.
}
fn validateDesign(model) {
Check against anti-patterns — load reference/anti-patterns.md.
Aggregate design checklist:
Single entity can be aggregate root
Invariants protected at boundary
Other aggregates referenced by ID only
Fits in memory comfortably
One transaction per aggregate
Report any violations with specific recommendations.
}
domainDrivenDesign(context) {
assessDomain(context) |> identifyBoundaries |> selectPatterns |> designAggregates |> chooseConsistency |> validateDesign
}