Domain-driven design comes up in every senior-developer conversation one way or another. One person talks about aggregate roots, another about bounded contexts, a third about ubiquitous language. Five minutes in, you can usually tell which of them have actually shipped a DDD project.
The honest truth: DDD is a powerful tool, but it doesn’t pay off on every project. Over the last four years I’ve applied DDD principles partially on at least six projects. Here’s where it earned its keep and where it was overkill.
When DDD actually wins
Eric Evans’ book has been out since 2003. DDD makes a real difference in these situations:
1. Domain complexity exceeds technical complexity. In insurance, finance, or healthcare, business rules come before code. You have 50 pages of regulation, and the code has to reflect it. DDD’s ubiquitous language concept is gold here: the domain expert and the developer share one vocabulary, and no one gets lost halfway through.
2. Long-lived systems with critical business logic. Systems that will still be alive in five years, probably worked on by more teams. Bounded context boundaries also guide team organisation, with Conway’s law you’re rowing in the same direction.
3. Domain expertise is separated from the development team. The business expert is on one side of the country, the team on the other. DDD’s event storming and domain modeling workshops close that communication gap.
When DDD is overkill
1. Simple CRUD projects. A landing-page admin panel, a content management system, a catalog app. The domain isn’t complex. Introducing aggregate roots, value objects, and domain events turns a three-day job into a three-week job.
2. Solo-developer products. DDD’s organisational benefits show up when there are boundaries between two or three teams. If you’re alone, carving out repository, entity, and service layers just adds boilerplate.
3. Prototype or MVP. When you don’t know yet if the product will survive, investing in DDD is wasted money. Product-market fit first, architecture second.
Minimum viable set to start with
Full DDD is expensive, but certain principles pay off in any project:
Ubiquitous language. Use the terms your domain expert uses in the code. orderFulfillment, paymentCapture, whatever the business actually calls it. You stop having to translate between the business conversation and the technical one.
Bounded contexts. At the very least, draw module boundaries. User management, payments, inventory, orders, reporting, these are different contexts. The same User model shouldn’t serve all of them; each context gets its own view of User.
Aggregate boundaries. Which data has to change atomically in a single transaction? The answer gives you your aggregate boundary. If you’re updating something outside the aggregate, you need an eventually-consistent approach.
These three concepts deliver practical value without reading 70% of the DDD book.
Practical rollout tips
When I kick off DDD with a consulting team, I usually suggest this order:
- Run an event storming workshop to list business events. Each event represents a business occurrence.
- Cluster the events. Each cluster is a candidate bounded context.
- Write down each context’s responsibilities. Define how contexts talk (event, API, data copy).
- Pick the first aggregate, code it. Test it, iterate.
That’s typically a 2 to 3 week discovery phase. Then you move into implementation.
The mistake most teams make
The most common DDD failure mode: teams lead with technical patterns instead of domain. They say “let’s use Repository, Factory, Specification pattern”, but they have no clarity on what domain they’re modeling. The result is a codebase full of boilerplate and thin on business logic.
The reverse works. Extract the domain model first, then bolt on technical patterns as mechanical support.
Takeaway
Don’t think of DDD as “all in or nothing”. Ubiquitous language and bounded contexts apply to most products and deliver value on their own. The heavier concepts (aggregate roots, event sourcing, CQRS) are worth adding only when domain complexity demands them.
When deciding, ask: can I manage this domain’s complexity without an explicit model? Is someone on the team genuinely translating between business needs and code? If either answer is no, DDD’s first principles will help. If both are yes, you don’t need the fancy patterns.