Motivation
In the recent year or two I've seen lots of discussions around building Domain-Driven Design in Angular applications. My observation is that people discuss things that are orthogonal to DDD at best - or even totally derailed from what DDD is about at its core.
Participants who attended my Angular and/or Architecture trainings or who came to my NG-Poland workshop, or simply people whom I meet here or there (frontend developers, but mostly from Angular community) all seem to discuss DDD/Angular in terms of specific tooling and specific structure of the application.
Also, I see posts in social media such as this one:

Obviously there's absolutely nothing wrong with asking questions (I'd rather have questions that can't be answered than answers that can't be questioned). However, all this shows that the wide Frontend/Angular community has little idea on why/when/how would you even approach Domain-Driven Design.
All in all, there's a growing semantic diffusion within frontend communities about DDD and it's bringing more harm than good (in short, semantic diffusion happens when people use a term without understanding it and, within some time, the meaning gets derailed βΉοΈ).
That's what I want to address in this post π€.
Business Context Example
In order to illustrate DDD concepts in a more approachable way, let's assume that we're working on a system that allows patients to schedule appointments with doctors, specialists, etc. to deal with medical issues. Putting it very simple, we could say that we're building a medical appointment application.
We'll stick to examples from this domain.
DDD is abstract and difficult
DDD is a methodology that's rather easy to cover just the main topics and building blocks (see: DDD at a glance section below). But it takes many years of hard work to gather the experience (not just theoretical knowledge) to be able to use it in practice for the benefit of your product.
It's difficult to get the abstract concepts right and then to reificate them in your business.
The main problem with DDD is that people stick to a shallow level of it, yet they label it as "doing DDD". Mostly, it's taking the code/organization you have right here right now - and labelling them somehow according to DDD's terminology π€¦.
Thankfully, not all people do that! As a result, on one hand, DDD helped enormous and complex businesses "tackle their complexity" and scale well, it even enabled them to grow in different areas.
On the other hand, for other companies, it turned out to be a failed promise which turned out to be a wasted effort, time and money. And a lack of trust to any DDD-related thingies in the future.
(and that's where my pain point is).
DDD is a tool. In hands of competent people, it could be very helpful. And vice-versa.
DDDD: Derailed Domain-Driven Design
There's a whole legion of frontend devs who think that organizing your code in some modules and automating tooling around monorepos is "doing DDD in Angular". (we'll get back to monorepos later π)
Couldn't be farther from the truth.

DDD is an approach you do within your product, a business segment, organization-wide.
But not separately on Frontend.
One could say (simplifying the topic quite a bit) that it's when the business semantics drive technical boundaries. But these technical boundaries include all the stack: Frontend, Backend, Database(s) - and activities: Deployment, Monitoring/Observability (DevOps) and so on, and so forth.
π₯ You don't do DDD on Frontend in separation, as your frontend is not a separate product. π₯
Frontend is not a separate "module" either. If you feel this sounds like blasphemy, then please get familiar with the C4 model for documenting architecture by Simon Brown. It's a bigger topic, and there are quite some variations of that model, but what's important for us here is that:
- C3 - Components - is a layer of logical architecture, i.e. it defines logical dependencies between modules, e.g. when a customer is charged, the system requires the card information from another place in the system
- C2 - Containers - is a layer of deployment architecture, i.e. it defines deployable artifacts (binaries, bundles, etc.)

Yes, most often you deploy frontend separately from backend (C2). But most often, a business module (Bounded Context, discussed later in the article) consists of Frontend, Backend and Database(s) altogether (C3).
So you don't want to detach frontend's capabilities from its backend counterparts. They achieve a business goal as a whole. If you design a model (i.e. data structures with their semantics) then some parts of it (specific interfaces) are being shared between the server and the client - that's a contract (DTOs, Data Transfer Objects), often automated via Swagger/OpenAPI or Pact.
So you can't do DDD on Frontend?
No, don't get me wrong π you can of course apply DDD to your Frontend. But... that means that there were product-wide considerations about modularity (Bounded Contexts), about dependencies across these Contexts (illustrated within Context Maps, discussed later).
So what DDD is about?
Let me say it again: DDD is the approach where we focus on OUR PRODUCT and UNDERSTANDING THE BUSINESS. That's where we start our activities. And that's where we make sure that what we did actually makes sense. And it's the business (not the tech) is what makes us iterate over our solutions.
If you're thinking in terms of DDD from technical perspective, YOU'RE ULTIMATELY DOING IT WRONG. Very wrong.
What does that mean in practice? Well, first of all, there is no place for you in DDD if you're focused mainly on your beloved framework, beloved language, technology or whatever else.
In DDD, your main focus is THE PRODUCT. That means you're actively interested in understanding:
- How does your product make revenue? What factors can increase or decrease the revenue?
- In our medical case: do we charge individual patients or do we sell some healthcare packages for companies and we charge a whole company for multiple individuals?
- What is the service that the customer buys?
- Do you charge patients per appointment or is there a subscription plan or anything else?
- What is the value that is brought to your customer? How do they benefit from it?
- Are these simply a one-time appointment such as teeth extraction or maybe a long-term process, including lots of appointments, such as cancer treatment?
- How do you charge your customers?
- Single appointment, subscription plan, periodically?
- How does the customer use your product? What makes it a pleasant experience or what is an obstacle that could be removed? Do you talk to your customers directly or do you just receive a Jira ticket?
- How CRUDy your interface is - or how well does the UI express the business process for the user (CRUD-based or task-based UIs)?
- How does your company take advantage on the market as compared to the competition? In other words, which parts of the system should you improve to build competitive advantage: a CRUD-based module for internal employees, or an experimental customer-facing UI?
- Web UI for a medical app is nothing special. So is a mobile app. What compelling business feature would make an individual consider switching from one medical company to another one?
- Here you're seeking for "Genesis" section of Wardley Maps.
- What are your business KPIs? Do you track them? Do you even care about them?
- An example business KPI for a stream-aligned team would be to maximize the consumption of the less popular doctors availability so their services are utilized better.
- Another business KPI would be to reduce the amount of patient appointments that are being cancelled in the very last moment, which is expensive for our business.
- Are there any scarce resources within your business that distinct customers are competing for? In other words, if customer A gets a thing, does it mean that customer B cannot get the very same thing? Is there a limited number of these items or services in time, in a period of time, in quantity, in any other way?
- In a medical center system, the scarce resource is the availability of doctors and the clinics. If a specific time/space slot is allocated, nobody else can use it: First come, first served.
And many, many, maaany more.
DDD at a glance
At this point you might feel a little bit concerned: why am I not speaking much about subdomains and bounded contexts and all these other popular DDD (buzz)words?
The truth is, these are just formalisms. And they are not the essence of the problem that DDD aims to solve. They're just some specialized terminology that helps us to communicate faster, they form a mental model / framework which we can build our understanding on top of.
So let me outline the basic concepts of DDD in very simple words...
Strategic vs Tactical DDD
First, there is Strategic DDD and Tactical DDD.
The Strategic one deals with the business mechanics, the business capabilities, business opportunities, business problems and so on. While the Tactical one deals with technological aspects, essentially: how to code these things And make them work correctly in terms of both scale and business complexity.
Strategic DDD is split in two parts: the Problem Space and the Solution Space.
Domains and Subdomains
We haven't yet covered the first "D". A "domain" is the area in which a business operates. For an online shop, it would probably be e-commerce. For a company that delivers packages, that would be logistics or spedition. In case of our medical app that might be medical care.
But don't you have a feeling, that "medical care" is somehow broad, includes lots of various concerns? You're right! In order to schedule a patient's appointment to a specialized doctor, we need to cover the following:
- What doctors do we have at hand?
- In which clinic or other location would the appointment take place?
- At what exact date and time? i.e. when are both the doctor and the clinic available and does the patient match this availability?
- How is the patient going to pay for the service?
- Are there any referral programs so that the patient could invite other patients to our clinic?
- Do we track the history of the patient's appointments? If we do, how do we exactly use the data? How can we benefit from it?
- How do we communicate with our patients?
- How do we deal with unexpected situations, e.g. the doctor is not available? The scheduled appointments need to be either cancelled or rescheduled.
That's a whole lot of problems that our business need to figure out and have it under control. That might be digitalized within an IT system, but it could also be manually managed by employees (see: sociotechnical systems).
All above questions to be answered could be treated as subparts of the main domain, hence the name: "subdomains".
Domains and subdomains are parts of the "Problem Space". That's not something that we can design. That's how our business operates in the real world.
We discover it.
Bounded Contexts
However, we can design how do we want to tackle these questions and problems. We apply the "Divide and Conquer" approach to split a big problem into smaller, simpler problems. We break our entire system into smaller, more autonomous modules called "Bounded Contexts".
At this point we don't focus on the technology. We don't care much whether it's going to be a frontend monolith or MicroFrontends, whether we're going to use monorepos or multiple repos. Properly shaped Bounded Contexts would fit into any deployment architecture.
It's our decision, how do we split, and how many bounded context we would have. There is, theoretically, an infinite number of viable solutions.
Getting Bounded Contexts right is absolutely the essence of what we do in DDD. And what's very often the source of failed attempts to DDD: jumping straight into tactical phase (implementation) without thinking thoroughly the strategy.
So how do we identify Bounded Contexts?
That's where "Domain Experts" come into play. If you're developing a "product" (i.e. you're not just grabbing and fixing Jira tickets), then there must be some people in your company who know how the business operates. These might be analysts, specialists, product owners or even directors. It doesn't really matter what is their official position within the structure. What matters is that they understand the business.
Context Maps
Bounded Contexts try to be autonomous, but sometimes they have to communicate with each other. We try to keep the amount of communication to the necessary minimum.
From a high-level perspective, architects need to get the context depencencies under some control - that's where Context Maps come into play, along with their patterns, such as: Anti-Corruption Layer, Open Host Service, Shared Kernel and so on).
Below is an exemplary, simplified Context Map. It outlines the boundaries across contexts:

Note that this is in NO WAY UNIVERSAL map for any medical application. I made quite some assumptions on how business works. Each company would probably have a totally different Context Map, based not only on their unique system, but also the business processes and the business rules that drive them.
Also note, that there's no 1:1 correlation between Subdomains and Bounded Contexts. Or at least, there doesn't have to be. Again, that's a deeper topic for another article.
But what matters a lot right now is that:
Frontend is NOT a separate Bounded Context.
Frontend layer just fits into the Context Map. So you'd rather do Angular within a DDD-oriented product, than DDD inside an Angular application.
A single context could have both backend and frontend (e.g. Appointments Search Context), but it could also have backend only (SMS/Email Notifications, e.g. communicating via kafka messaging, whatever) - it depends on what responsibility it has.
A given piece of UI might need to integrate with a legacy backend system - or even with an external backend (e.g. the one processing actual payments, or a SMS/Mailing service), sure. But quite often there is (or at least there should be) some backend faΓ§ade / BFF on your side that communicates with that legacy/external system, which would take care of concerns such as making sure the patient doesn't get the same messages multiple times (even if there are network or system failures).
No matter what's the exact situation - you draw module boundaries from a high-level perspective, and not on frontend-level only.
However, frontend is never a separate Bounded Context. And that's quite a popular misunderstanding.
And quite often a reason for devs inventing frontend-DDD, while searching for aggregates in frontend landscape (spoiler: they won't find it, as Frontend doesn't deal with persistence).
For instance, they tend to view HTML forms handling as DDD aggregates, which doesn't make much sense, as client-side code handles HTTP/WebSockets communication, but not persistence/consistency/transactions. And even if you're using SSR tech such as Next.js which allows to process forms via server actions, then yeah - you might have an aggregate on the server-side, but not on the client. And we go back to the starting point π₯Ή
As you see, DDD is tech-agnostic.
Ubiquitous Language and Semantics
When people communicate, while working on a product with complex domain, they need to exchange quite complex thoughts. Specialized terminology comes into play. You can think of Ubiquitous Language as a dictionary, potentially written down somewhere - or commonly understood within the company - which defines precise terms.
For instance, a specialist is any professional who can perform medical services for patients. A specialist could be, first and foremost, a "doctor", but not only: "nurses", "technicians" and many other professions are also included here.
Explicitly, we don't use "specialists" or "doctors" interchangeably - not to introduce confusion. A specialist in our case is a specialist, period.
Ubiquitous Language is ubiquitous in a way that it appears in conversations, in code, in tests etc. But it's NOT ubiquitous in a way that it appears across the whole company - it's specific to a specific Bounded Context.
Why?
Imagine we've got B2B and B2C services. They're being handled in totally different ways.
Now let's consider who a Customer is: is it an individual (B2C) or a company (B2B)?
Does it make sense to create a Unified, Universal Model (also called Canonical Data Model) of a Customer that would be used throughout the whole application?
That deserves a separate article (let me know if you want that), but clearly: HELL NO!
So what's the relation between a Customer and a Patient? Do these two models exist side by side in a single context or are they exclusive to separate contexts?
Where does it actually make sense to use "Patient" and when to use "Customer"? Patient for Appointment Search, Scheduling, etc. and Customer for Billing, Invoicing etc - or something else?
Customer should have a TAX ID. The Patient should have a Social Security Number (or whatever it's called in your country). Does TAX ID matter when a patient schedules an appointment? Does SSN matter when billing?
How do we draw the boundaries between these models?
π₯ That's DDD. π₯ That's the heart of it. π₯
How much is it related to Nx Monorepos, NGRX glocal or component Store, Signals, services in this style or another?
It's just not.
You can think of Semantics as the first and foundational step in learning DDD. And getting detached from what your database/client-store data model is.
By the way, speaking very formally:
Bounded Context is a SEMANTIC BOUNDARY where a Ubiquitous Language makes sense.
π
A term/word, outside of a Bounded Context, has totally different meaning.
So who is a patient?
In terms of appointments, it's someone who utilizes our resources. Sad but true π
In terms of billing, it's someone who pays for our services (directly, or indirectly)
In terms of referral programs, it's someone who brings new customers (and revenue).
In terms of unexpected situations, a patient is a "problem", as we have to reschedule their appointments if the doctor unexpectedly becomes unavailable. And, probably, we're not automating this fallback process, as that would hit UX significantly (would you like a machine to reschedule your visit without asking you?)
And so on. Each Bounded Context is "enclosed" by specific semantics. In various Bounded Contexts you might have ffew, several or even tens of different representations of what the Patient is. That's normal.
(that's also, by the way, a reason why you might NOT want to use any centralized state management solution on Frontend, as they tend to normalize client state, which breaks autonomy across modules. In short: integrate modules via EVENTS, not via STATE - but that's yet another topic for a separate article).
Tactical DDD on Frontend? No, thank you
Of course, there's a whole separate part: the Tactical DDD.
In very short, it deals with specific design patterns that we apply to implement DDD. This again, deserves separate articles, but just to put it short:
- Entities - define business objects that change over time, so they have their identities (IDs).
- Examples: specialist, patient, customer.
- Value Objects - immutable data values
- Examples: price, visit duration.
- Aggregates - the most important one. It's NOT a graph of related objects, as many explain it. It's a consistency boundary for concurrent operations to take place. Sounds complex, isn't it? Yep, you determine one's skills in DDD but looking at their aggregates.
- Example: few patients want to schedule an appointment on the same date/time, same specialist, same place etc. Only one can get it.
- What matters: concurrent access to a resource, and that the resource is scarce (there might be a race for obtaining that resource between users/parties)
- Would there be a problem, if multiple patients would schedule the same specialist/clinic/time slot? If there is a problem, how big of a business problem is it? Can we accept that in small amounts (and what does a "small amount" mean?)
- Technically, think of an aggregate as the smallest possible chunk of data that allows you to handle race conditions. You might need to federate your database or shard it (usually, complex domain systems come with big scale, i.e. horizontal scaling). The aggregate technically uses some way of database transactions to ensure that no business rule is broken.
- Quite mouthful, isn't it? Told ya, it's not that simple... And, oh, by the way, why Tactical DDD doesn't make sense on Frontend? YES - aggregates don't make sense on clients, since they almost never handle database/persistence/concurrency directly.
- Very common mistake: aggregates are too big or absolutely way too big, which make them perform bad, and also enforce unnecessary data integration (data consistency) for data which is totally not needed there.
- Another common mistake: there's no concurrent access for a resource, e.g. we collect patients' feedback. Feedback of one patient has no concurrency/race conditions/etc. with another patient's feedback. Hence, you might not need an aggregate in many cases.
- Repositories - they extract the data from, most probably, RDBMS, and build a domain-friendly tree of objects, often as an aggregate. What's important, the ORM/DB model could be quite different from your domain model. A repository is not meant to do the DB call directly, probably it uses some technical layer underneath. and quite a bit more...
These patterns are critical in some Bounded Contexts on backend (not all though - it's perfectly fine if some backend parts are simple CRUDs if that's what fits). However...

In 99,99% cases, that'd be pure Accidental Complexity. You don't want that.
By the way, if you name your Angular Services performing HTTP requests as "Repositories" they most probably, you make your code look smarter than it actually is. That's not technically wrong, but most probably it's semantically wrong, as the JSONs you fetch from the server (contract DTOs) should be already shaped in a client-friendly way. And the point of a Repository is to adjust the server's model to your domain model. That should be done on backend, not frontend.
Don't stick to fancy names just for the sake of it - it doesn't help anyone.
DDD Terminology Summary
After wrapping up the DDD terminology, we could come up with a diagram similar to the following:

Lovely diagram, isn't it? Now you can say you understand DDD, right?

Unfortunately, THIS DIAGRAM DOESN'T HELP YOU much in getting the point of DDD.
You can also refer to the original diagram included in the Blue Book:

(sidenote: it doesn't help much in getting to the core of DDD either - BUT π - if you like books, start with the Red Book instead of the Blue one, as it's way more approachable)
A wise person once said:
There's a big difference between knowing a word and understanding its meaning.
I could only add that, from my observations, the difference is really huge. And it's often the reason for the semantic diffusion. People use a term without understanding what it is. It diverges from its origin. And hence, when someone uses the term, what's the understanding of the person using it π.
At this point, if you think that using DDD's terminology here and there, without some additional effort, doesn't make things anyhow simpler - then I'm absolutely happy.
Don't rush to claim you're doing DDD. It's better to think in terms of being business-driven (not a buzzword yet), business-centric or business-aligned.
Are you?
Monorepos has nothing to do with DDD
Having understood the basic concepts behind DDD - let's get back to... Monorepos.
When it comes to monorepos, how you organize your code in directories/repos is purely orthogonal to your business/domain concerns - although it could affect team efficiency (development and operations - yep, DevOps is NOT about docker or k8s π ).
But bear in mind, splitting your business codebase into Bounded Contexts aims to make them autonomous, independent on each other. And the whole point of using monorepos is to make sharing easier at a bigger scale, i.e. without CI/CD delay penalty, without long build queues etc.
But, again, sharing reduces autonomy. The more you share, the less autonomous your team/module/context is.
Share with care.

Monorepos are double-edged swords.
It's wonderful that monorepo tooling allow us to limit who can import what (e.g. using Nx Module Boundaries or ESLint Restricted Imports). But let's quickly reframe the problem... Why would you introduce module boundaries/restricted imports? Hm, because people tend to import too much what they shall never import? Hm, if you didn't put entire codebase (many modules from many teams) into the single repository, would the problem exist at all? π
From my personal experience (I do lots of consultancy and trainings), in majority of cases, people try to share too much. And they have to reach out to solve problems they introduced themselves.
I've seen frontend monorepos abused (used unnecessarily or misused) more often than used effectively and having a good reason. Not to mention CV-driven development. Though, there might be people strongly disagreeing with the statement - and we can never come to a conclusion unless we analyze specific case studies.
DISCLAIMER: Having written all that, there's nothing wrong with monorepos. It's just a tool. But as each tool, use it with care. Don't make it a default choice blindly.
Component Library
Yes, you might need to share a reusable component library. However, there's no silver bullet, no universal solution. "It depends" on so many factors. If someone is trying to sell "a universal solution that fits everywhere" - run away. You'll thank me later.
There are multiple ways for sharing UI libraries. It could be a monorepo, but it doesn't have to be.
Component Libraries are the #1 Frontend problem in big systems I've audited. And the #1 reason for it, it's because people try to put too much there. Again, topic for a separate article.
If you disagree with what I wrote above, please refer to Thinnest Viable Platform on TeamTopologies.com. You want your platforms to be small, not big.
But let's get back to the main topic...
When can we call it DDD?
Finally, there's a quote from Eric Evans that I need to address:
[...] the most fundamental pattern of Domain-driven Design is probably the ubiquitous language. [...]
[A model] applies within a certain context, and that context has a definitely defined limit, [it's] a bounded context.
With those two ingredients, I would say, someone is doing Domain-Driven Design, and there are a lot of other practices that help solve more specific problems.
The quote is being used as a universal justification for "doing DDD" if only you have ubiquitous language and bounded contexts.
I hope at this point we have well understood that:
- Frontend is not a separate Bounded Context
- DDD is a product/organization-wide discipline
- Frontend-only DDD is an architectural delusion
- you can do DDD on Frontend, if you're doing it throughout your entire product.
Also, note that... while using the above quote and while ignoring the semantics of what ubiquitous language and bounded contexts are, you could justify labelling pretty much anything as DDD. Feel free to call any context a "bounded" context. Same with ubiquitous language. Quod erat demonstrandum.
Does it help anyone in achieving their goals? I strongly doubt that.
Does it sound fancy? Probably... Unless you encounter someone who really understands the topic - then you might look like... someone really incompetent.
π₯ The true mastery is when you deeply understand a topic - yet you use simple words, that are approachable by majority. π₯
No need for fancy words, if they don't bring measurable benefits.
Community Reception
And you know what? Experienced backend/DDD folks would likely summarize the article as: "ah, that's kind of obvious, nothing new to me". Because it is π€·.
And yet, all above narrative might make some frontend folks' heads explode, as it ruins what they considered DDD to be.
That's how semantic diffusion grows.
Wrap up
As a summary - let's get back to the initial post and go through the questions:

Note the question:
I want to start a new project in #Angular using Domain Driven Design.
Why?
Do you have a complex domain?
Do you have Domain Experts at hand?
How would you draw Bounded Contexts?
Also, "DDD in Angular" - but what about the rest of the system?
DDD is not an architecture style, like modular monoliths, onions, hexagonal, etc. DDD could fit those for better or worse.
When a seasoned DDD practitioner reads "I want to start a new project using Domain Driven Design", following questions pops up:
- new project? Mkay, but how well do you know the domain? How likely is the domain concerns to cause trouble? Do you even know where the difficult part of your system is?
- or in other words: if it's a new project, how do you know you already need DDD? DDD is not something you can "setup initially".
What are your thoughts/opinions about DDD in big projects?
What is your application doing?
DDD is not a matter of taste. Or trends. It's a tool.
It's not a matter of being big or small either. It's a matter of your domain being complex - or not.
It's a matter of how much you can or cannot rely on "simple CRUDs"... or how many business processes you've got... or how many people work on the system in parallel, and how much collaboration they need on a daily basis. And what do they have to agree upon (for the sake of system integration, yet keeping coupling at a minimum).
Is it worth it?
As with everything, some will say "yes", some will say "no". It depends on what you need, what's your context, what's your architectural expertise and so on. Thankfully, there are tons of experts in the area we can all learn from.
If you're interested in learning DDD, feel free to reach out to me, or follow any of people I consider experts in the field. You might also like to check out my aDDDvent series.
Enjoy learning DDD!
