DDD: These aren’t the bounded context you’re looking for

Joe FRANCOIS
The Yield Studio Playbook
5 min readDec 8, 2024

After yet another post titled “DDD with Framework X, the ultimate guide,” I can’t resist the urge to set the record straight.

Me playing with AI for the second time. Well… Did you notice the “BS”? 😅

Why DDD starts with the Business, not the Code

We are far too often flooded with resources claiming to show us how to implement DDD in our favorite tech stack.
Unfortunately, there’s a fundamental misunderstanding of what a domain or a bounded context truly is.

These approaches are overly technical, whereas DDD is meant to encourage developers to design their applications based on the business itself, not constrained by technical considerations.

Clarifying Domains and Bounded Contexts as simply as possible

I notice that the difference isn’t always clear, but as you’ll see, it’s much simpler than it seems!

Let’s imagine a bank: its main business is to offer bank accounts to its customers, enabling them to manage their money on a daily basis. Nothing extraordinary here — I think we all know what a bank is for!

Now, let’s imagine that this same bank also offers vehicle insurance.

It’s still the same company, but it’s engaged in two completely different activities. Here, we’re talking about two distinct domains.

We can therefore separate the banking domain and the insurance domain.

In summary, the domain is the core of the business problem. It encompasses all the concepts, rules, processes, and logic that describe how the business operates.

Within each domain, we can identify bounded contexts, which can also be thought of as “subdomains.”

A bounded context is an explicit boundary that divides a domain into several logical parts.
Each bounded context represents a clearly defined space where a specific vocabulary, rules, and business logic are coherent and autonomous.

For example, within our banking domain, we could identify these bounded contexts: “Account Management,” “Loans and Credits,” “Investments,” “Customer Relations,” or “ATM Management.”

Each bounded context would have its own representation of a “customer” or a “bank account,” for instance.

A low tech method to model a Business

Now that we’ve clarified these core concepts, let’s explore a practical method to model a business domain.

If you’re struggling to model a business domain, here’s a simple and personal way to easily identify bounded contexts:

Forget tech for a moment and focus on how the business works at its core, independent of software. Forget the internet, forget computers, and look at how everything works — or would work — without them.

Try observing your organization’s workflows as if no tech were involved — what departments and processes emerge?

You’ll notice “departments” or “offices,” with real people handling real documents, each working independently in their own office while collaborating with other offices in other departments.

See what I mean?

Now all you need to do is model those documents, processes, and interactions.
Of course, in reality, it’s not that simple, but it’s a good starting point.

If you have another way to model a business, I’d be curious to hear your thoughts.

That said, this modeling often serves as a starting point.
The most important thing is to validate or invalidate elements of this initial approach through discussions with representatives from each area of the business and by conducting workshops.

An overly technical and mistaken perspective, you said?

Let’s get back to the point: defining domains or bounded contexts while completely ignoring the business and forcing technical constraints.

The following example is the one I see most often. Let’s continue using our banking and insurance domains as a foundation.

app/
├── Domains/
│ ├── User/
│ │ ├── Application/
│ │ │ └── UserService
│ │ ├── Domain/
│ │ │ └── Models/
│ │ │ └── User
│ │ ├── Infrastructure/
│ │ └── Http/
│ │ └── Controllers/
│ │ ├── CreateUserController
│ │ ├── UpdateUserController
│ │ ├── DeleteUserController
│ │ ├── ShowUserController
│ │ └── ListUsersController
│ ├── Account/
│ │ ├── Application/
│ │ ├── Domain/
│ │ └── Infrastructure/
│ └── Transfer/
│ ├── Application/
│ ├── Domain/
│ └── Infrastructure/

These aren’t bounded context or domain, these are features or entities. There’s absolutely no notion of DDD in this example.
There are no business concepts, just a technical implementation of entities “translated technically” from a personal interpretation of the business.

If we have to add the “Insurance” bounded context following this approach, how would we do it?
Lemme guess! I imagine we’d add an “Insurance” tree structure and share “Customer” between Banking and Insurance.

Sharing entities like ‘Customer’ across domains can lead to confusion, as their definitions and purposes differ in each context. This results in a model that’s tightly coupled to technical details instead of reflecting the business.
Sure, they might share a unique identifier or some attributes, but they’re not exactly the same thing!

The issue becomes even clearer if you imagine that each component of this tree structure represents the technical elements of a framework.

For instance, in “Domain,” you might find “Models” that are actually tied to the ORM of the chosen framework.
Not only does this fail to model the domain, but it also couples everything tightly to the database schema and technical implementation details. It’s a lose-lose situation.

Business comes first

If you want to do DDD, here’s a simple example that’s much more suitable.

app/
├── Domain/
│ ├── Banking/
│ │ ├── AccountManagement/
│ │ │ ├── Application/
│ │ │ ├── Domain/
│ │ │ │ ├── Entities/
│ │ │ │ │ └── Customer
│ │ │ │ └── AccountAggregateRoot
│ │ │ └── Infrastructure/
│ │ │ └── Http/
│ │ │ └── Controllers/
│ │ │ ├── OpenAccountController
│ │ │ ├── CloseAccountController
│ │ │ └── GetBalanceController
│ │ ├── LoanAndCredit/
│ │ │ ├── Application/
│ │ │ ├── Domain/
│ │ │ │ ├── Entities/
│ │ │ │ │ ├── Customer
│ │ │ │ │ └── Credit
│ │ │ │ ├── CreditAggregateRoot
│ │ │ │ └── LoadAggregateRoot
│ │ │ └── Infrastructure/
│ │ │ └── Http/
│ │ │ └── Controllers/
│ │ │ ├── SimulateLoanController
│ │ │ └── SendLoanRequestController
│ │ ├── Investment/
│ │ ├── CustomerRelationshipManagement/
│ │ └── ATM/
│ ├── Insurance/
│ │ ├── Subscription/
│ │ ├── Quote/
│ │ ├── Claims/
│ │ ├── Billing/
│ │ └── CustomerRelationshipManagement/

This is not an exhaustive example, but the main goal here is to give you an idea of the difference rather than providing a complete example of what’s possible.
Here, we can easily guess the business we’re talking about.

Domains, contexts, and business processes are clearly identified.

What we’re focusing on is not the language or the framework, but the business itself. That’s what really matters!

Conclusion

The first approach is perfectly fine; it’s feature-oriented and highly technical, but it’s not DDD!

DDD isn’t about forcing tech onto the business — it’s about aligning your application to the real-world needs of the business. Start with understanding, model thoughtfully, THEN implement with the tools that best suit your needs.”

Have you faced challenges when applying DDD? Share your thoughts or examples in the comments!

--

--

The Yield Studio Playbook
The Yield Studio Playbook

Published in The Yield Studio Playbook

At Yield Studio, we believe that the ability to design and develop the best products starts with exchanging and sharing knowledge. We share cutting-edge knowledge in programming, design and product excellence.

Joe FRANCOIS
Joe FRANCOIS

Written by Joe FRANCOIS

Tech Lead, Software craftsman, Software Architect. 20+ years of bad code :D

Responses (2)

Write a response