DEV Community

Mostafijur Rahman
Mostafijur Rahman

Posted on • Originally published at mrsajib.com

I Thought Domain-Driven Design Was a Waste of Time. I Was Wrong.

The first time someone explained Domain-Driven Design (DDD) to me, I thought it was a lot of ceremony for very little payoff.

Aggregates, value objects, bounded contexts — a whole vocabulary to learn. I had shipped plenty of features without any of it. My honest assumption: this will just slow me down.

I was wrong. Here's the short version of how I found out.

The project that changed my mind

I worked on a system with a hierarchy — Site, then Aggregator, then a unit under that. A "plan" existed at every level.

In the code, all three were just plan. Same name, same shared object, everywhere.

It worked — until it didn't. Features started colliding. A change to one level's plan quietly broke another. Every function needed a comment explaining which plan it meant. New people asked the same question every week: "is this the site plan or the unit plan?"

The code ran fine. The understanding around it was rotting.

That's the exact problem DDD is built to fix.

What DDD actually is

DDD is not a framework. Nothing to install. It's a discipline: design your software around the business problem, not the database or the framework.

The patterns get all the attention, but the real value is in two boring ideas.

1. Ubiquitous language — name things honestly

Pick precise words and use them everywhere — in conversations, tickets, and the code itself.

If the business has a "draft plan" and a "submitted plan," those exact words belong in your class names. Not plan with a vague status field. The moment a name is vague, logic starts hiding inside it.

My entire mess traced back to one overloaded word.

2. Bounded context — stop forcing one model

"Customer" means different things to billing, support, and analytics. Forcing one shared Customer class gives you 40 fields nobody dares touch.

A bounded context is a line you draw: inside this boundary, a word means exactly one thing. Cross the line, you're allowed a different model.

This is also the most reliable way to answer "how do I split this microservice?" — split where the domain actually splits.

The patterns, in one line each

  • Entity — has a stable identity over time (an order stays that order).
  • Value object — defined only by its values (money, a date range).
  • Aggregate — a group of objects with one entry point that enforces the rules.
  • Repository — hides how data is stored from your domain code.
  • Domain event — something meaningful happened (PlanSubmitted).

But these only make sense after the language and boundary work. Reach for them first and you get fancy code that models nothing real.

When to skip DDD

My old skepticism wasn't wrong — just aimed at the wrong project.

Skip DDD if: the app is simple CRUD, the project is small or short-lived, or the complexity is technical (algorithms, performance) rather than business logic.

Use DDD if: the domain is genuinely complex and the software has to live and evolve for years.

"This will slow me down" is correct — for simple projects. It's completely wrong for complex ones.

What I'd tell my earlier self

The patterns are not the point. You can memorize aggregates and value objects and still build a mess.

The point is the boring stuff: talk to the people who understand the business, agree on exact words, draw honest boundaries, and let the code follow.

DDD is overhead. On a simple project, bad trade. On a complex one meant to last, it's the cheapest insurance you'll ever buy.


Originally published on mrsajib.com. I write weekly about backend engineering and building software that lasts.

Top comments (0)