ddd-best-practices
Skill5 starsChanged 30 days agoMITView on GitHub
Use when modeling domain language, subdomains, bounded contexts, aggregates and invariants, value objects, domain events, typed domain failures, repository contracts, cross-aggregate consistency, context integration, CQRS, Event Sourcing, or hexagonal architecture. Focuses on domain ownership and consistency; use infrastructure guidance for delivery, storage, and transaction mechanisms.
In this repository11 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- boostSkill
- data-migration-best-practicesSkill
- design-patterns-best-practicesSkill
- flowSkill
- fp-best-practicesSkill
- infrastructure-designSkill
- oop-best-practicesSkill
- refactoring-best-practicesSkill
- rest-api-best-practicesSkill
- tdd-best-practicesSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
32 rules. About 0 are common, 11 are distinctive, and 21 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈11
Distinctive · estimate
This author's own choices. Worth a look.
21
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Use this skill when the main question is how to model a domain, where to draw boundaries, or how to structure collaboration between …
- Distinctive: line 16
Start from the domain problem, not from technical constructs.
- Distinctive: line 18
Keep Aggregates small — consistency boundary, not convenience grouping.
- Distinctive: line 19
Prefer Value Objects when a domain concept has value semantics, not as a blanket wrapper for every primitive.
- Distinctive: line 21
Never let infrastructure concerns leak into the domain model.
- Distinctive: line 36
Start from one business command and state the invariants it must preserve.
- Distinctive: line 41
Check lifecycle, cardinality, contention, and concurrency.
- Distinctive: line 53
Use Anti-Corruption Layers when consuming upstream models you don't control.
- Distinctive: line 62
If a recognized business invariant requires two objects to commit or reject together, they likely belong in the same Aggregate.
- Distinctive: line 65
If you track it over time or need to distinguish between two instances with the same data, it's an Entity.
- Distinctive: line 68
If a significant domain operation doesn't naturally belong to any Entity or Value Object, it belongs in a Domain Service — but use …
- Very specific: line 72
Prefer a specific semantic fact such as UserArchived over generic UserUpdated or StatusChanged.
- Very specific: line 98
Read references/aggregates.md for Aggregate discovery, boundary signals, rule ownership, creation vs.
- Very specific: line 99
Read references/repositories.md for repository semantics, contract ownership, Repository vs DAO/query service/gateway, absence, mapping, …
- Very specific: line 100
Read references/domain-events.md for event semantics, granularity, payload/envelope design, aggregate recording, creation vs …
- Very specific: line 101
Read references/model-evidence.md when resolving terminology, ownership, lifecycle states, or a consequential domain decision.
- Very specific: line 103
Read references/tactical-patterns.md for Entities, Value Objects, Aggregates, Domain Services, Domain Events, Repositories, Factories.
- Very specific: line 104
Read references/strategic-design.md for Subdomains (Core/Supporting/Generic), Bounded Contexts, and Ubiquitous Language.
- Very specific: line 105
Read references/context-mapping.md for Context Map patterns: Partnership, Shared Kernel, Customer-Supplier, Conformist, ACL, Open Host …
- Very specific: line 106
Read references/cqrs-and-events.md for CQRS, Event Sourcing, Event Storming, and process managers.
- Very specific: line 107
Read references/hexagonal-architecture.md for Ports & Adapters: primary/driven ports, adapters, dependency direction, test strategy, …
- Very specific: line 108
Read references/ddd-in-practice.md for practical DDD application: discovery process (Impact Mapping, Model Exploration Whirlpool), team …
- Very specific: line 109
Read references/domain-errors.md for failure taxonomy and ownership, Option vs Result/Either vs exception decisions, stable codes, …
- Very specific: line 110
Read references/read-models.md for aggregate-derived DTOs vs dedicated read models, CQRS query shapes, projection handlers, atomic …
- Very specific: line 111
Read references/typescript-ddd-examples.md for the TypeScript DDD skeleton: folder structure by Bounded Context, explicit Value Objects, …
- Very specific: line 112
Read references/go-ddd-examples.md for DDD in Go: folder structure by Bounded Context, Value Objects, Aggregate Root with unexported …
- Very specific: line 116
Use oop-best-practices for detailed Value Object construction, equality, immutability, optionality, persistence, and everyday object design …
- Very specific: line 117
Use design-patterns-best-practices for GoF and enterprise patterns inside the domain.
- Very specific: line 118
Use refactoring-best-practices when evolving an existing domain model safely.
- Very specific: line 119
Use tdd-best-practices for invariant-first Aggregate tests, deterministic fixtures, and concurrency integration tests.
- Very specific: line 120
Use infrastructure-design for transaction boundaries, optimistic locking, and reliable Outbox implementation.
- Very specific: line 121
Use rest-api-best-practices when exposing the domain through an HTTP API and translating domain errors to status codes.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
DDD Best Practices
Use this skill when the main question is how to model a domain, where to draw boundaries, or how to structure collaboration between subdomains.
Working Style
- Start from the domain problem, not from technical constructs.
- Build a Ubiquitous Language before writing any code.
- Keep Aggregates small — consistency boundary, not convenience grouping.
- Prefer Value Objects when a domain concept has value semantics, not as a blanket wrapper for every primitive.
- Let Domain Events tell the story of what happened, not what to do next.
- Never let infrastructure concerns leak into the domain model.
Design Workflow
- Discover the domain.
- Who are the domain experts? What language do they use?
- What are the core subdomains (Core, Supporting, Generic)?
- Where does the most complex business logic live?
- Draw Bounded Contexts.
- One model per context — resist the urge to share models across contexts.
- Name each context after a team or capability, not a technical layer.
- Define context relationships explicitly (Partnership, Customer-Supplier, Anti-Corruption Layer, etc.).
- Design Aggregates.
- Start from one business command and state the invariants it must preserve.
- Include only state that must commit or reject atomically.
- Each Aggregate has one root Entity that controls access.
- Enforce invariants within the Aggregate boundary only.
- Reference other Aggregates by identity, never by object reference, and make eventual consistency explicit.
- Check lifecycle, cardinality, contention, and concurrency; table count does not define the consistency boundary.
- Model with tactical patterns.
- Entity: has identity that persists over time.
- Value Object: defined by its attributes; value equality; immutable by default; no identity.
- Domain Service: stateless logic that doesn't belong to any single Entity.
- Domain Event: records that something significant happened.
- Repository: collection-like access to Aggregates.
- Factory: encapsulates complex construction.
- Integrate contexts.
- Translate at boundaries — never let one context's model pollute another.
- Use Anti-Corruption Layers when consuming upstream models you don't control.
- Translate internal Domain Events into stable Integration Events before crossing a context boundary.
Heuristics
Bounded Context
Draw the boundary where the Ubiquitous Language changes — the same word meaning different things is a signal for a boundary.
Aggregate
If a recognized business invariant requires two objects to commit or reject together, they likely belong in the same Aggregate. Do not confuse a convenient synchronous workflow with an invariant. If temporary inconsistency has an acceptable recovery path, prefer separate Aggregates.
Entity vs Value Object
If you track it over time or need to distinguish between two instances with the same data, it's an Entity. If all that matters is its value, it's a Value Object.
Domain Service
If a significant domain operation doesn't naturally belong to any Entity or Value Object, it belongs in a Domain Service — but use sparingly.
Domain Event
Name events in the past tense: OrderPlaced, PaymentFailed, UserRegistered. They record facts — they don't issue commands.
Prefer a specific semantic fact such as UserArchived over generic UserUpdated or StatusChanged; let the Aggregate record it and the application deliver it.
Repository
One Repository per Aggregate Root. Never expose a Repository for child entities within an Aggregate. Return complete Aggregates for invariant-bearing work; use dedicated query models for reports and partial projections, and gateways for external capabilities.
Warning Signs
- Anemic Domain Model: Entities have only getters/setters; all logic is in services.
- God Aggregate: one Aggregate contains everything related to a concept.
- Shared database between Bounded Contexts — contexts are coupled through the schema.
- Ubiquitous Language drift: code uses different terms from the domain experts.
- Application Service doing domain logic instead of orchestrating domain objects.
- Repository returning arbitrary queries instead of meaningful collection operations.
- Repository exposing ORM/query-builder types, interpolated SQL, or transaction control.
- Generic CRUD events carry full Aggregate snapshots without a consumer or compatibility reason.
- A use case invents Domain Events after the transition, or an Aggregate publishes through an Event Bus.
- Raw internal Domain Events cross a Bounded Context instead of being translated to versioned Integration Events.
- One transaction routinely modifies multiple Aggregate Roots without a documented invariant.
- Public setters or mutable child collections let callers bypass the Aggregate Root.
- Repository access exists for a child Entity inside an Aggregate.
- Aggregate boundaries mirror ORM relationships, UI screens, or table layouts.
- A global uniqueness rule is checked only in memory, without a concurrent persistence constraint.
References
- Read
references/aggregates.mdfor Aggregate discovery, boundary signals, rule ownership, creation vs. reconstitution, concurrency, cross-Aggregate coordination, persistence, and review checklists. - Read
references/repositories.mdfor repository semantics, contract ownership, Repository vs DAO/query service/gateway, absence, mapping, transactions, caching, pagination, testing, and legacy migration. - Read
references/domain-events.mdfor event semantics, granularity, payload/envelope design, aggregate recording, creation vs reconstitution, Integration Event translation, subscribers, and delivery boundaries. - Read
references/model-evidence.mdwhen resolving terminology, ownership, lifecycle states, or a consequential domain decision. - Read
references/tactical-patterns.mdfor Entities, Value Objects, Aggregates, Domain Services, Domain Events, Repositories, Factories. - Read
references/strategic-design.mdfor Subdomains (Core/Supporting/Generic), Bounded Contexts, and Ubiquitous Language. - Read
references/context-mapping.mdfor Context Map patterns: Partnership, Shared Kernel, Customer-Supplier, Conformist, ACL, Open Host Service, Published Language. - Read
references/cqrs-and-events.mdfor CQRS, Event Sourcing, Event Storming, and process managers. - Read
references/hexagonal-architecture.mdfor Ports & Adapters: primary/driven ports, adapters, dependency direction, test strategy, Walking Skeleton implementation, and comparison with Clean/Onion Architecture. - Read
references/ddd-in-practice.mdfor practical DDD application: discovery process (Impact Mapping, Model Exploration Whirlpool), team topology, DDD adoption anti-patterns, and PHP implementation examples (Value Objects, Entities, Aggregate Root, Application Service, Specification). - Read
references/domain-errors.mdfor failure taxonomy and ownership, Option vs Result/Either vs exception decisions, stable codes, exhaustive composition, state atomicity, and safe boundary translation. - Read
references/read-models.mdfor aggregate-derived DTOs vs dedicated read models, CQRS query shapes, projection handlers, atomic idempotency, missing event data, incremental updates, and shadow rebuilds. - Read
references/typescript-ddd-examples.mdfor the TypeScript DDD skeleton: folder structure by Bounded Context, explicit Value Objects, AggregateRoot/DomainEvent examples, creation vs reconstitution strategies, use case structure, CommandBus/QueryBus, Object Mother, and Criteria pattern. - Read
references/go-ddd-examples.mdfor DDD in Go: folder structure by Bounded Context, Value Objects, Aggregate Root with unexported fields, Domain Events, Repository interface (port) vs implementation (adapter), Use Case, ACL, CQRS query side, Domain Service.
Related Skills
- Use
oop-best-practicesfor detailed Value Object construction, equality, immutability, optionality, persistence, and everyday object design within a Bounded Context. - Use
design-patterns-best-practicesfor GoF and enterprise patterns inside the domain. - Use
refactoring-best-practiceswhen evolving an existing domain model safely. - Use
tdd-best-practicesfor invariant-first Aggregate tests, deterministic fixtures, and concurrency integration tests. - Use
infrastructure-designfor transaction boundaries, optimistic locking, and reliable Outbox implementation. - Use
rest-api-best-practiceswhen exposing the domain through an HTTP API and translating domain errors to status codes.
Source Influences
This skill is synthesized from:
- Domain-Driven Design by Eric Evans (the blue book)
- Implementing Domain-Driven Design by Vaughn Vernon
- Domain-Driven Design Distilled by Vaughn Vernon
- Learning Domain-Driven Design by Vladik Khononov
- Patterns, Principles, and Practices of Domain-Driven Design by Scott Millett & Nick Tune
- Hexagonal Architecture Explained by Alistair Cockburn & Juan Manuel Garrido de Paz
- DDD in PHP (community resource)
- CodelyTV Aggregates course
- CodelyTV Repository Pattern course (including production counterexamples)
- CodelyTV Domain Events course (including modeling and delivery counterexamples)
- CodelyTV Domain Modeling Errors course (including Optional, Result, Effect, exhaustivity, and boundary counterexamples)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

