The Core Idea Behind Domain-Driven Design
Domain-Driven Design (DDD) offers a way to connect complex business requirements with thoughtful application architecture. The main objective is to ensure the software's internal structure mirrors the vocabulary and organization of the actual business domain it serves. DDD splits into two connected practices: Tactical Design and Strategic Design.
Tactical Design gives developers a set of concrete tools and patterns for modeling domain logic. These were initially conceived with object-oriented programming in mind, yet the underlying concepts—like creating rich domain models and keeping business intent alive in the code—work equally well in other styles, including Functional Domain Modeling.
Strategic Design, meanwhile, is concerned with how large systems are carved up into smaller (sub)domains, each with its own bounded context. This method of organization keeps complexity manageable by giving every component of the system clear borders, a consistent language, and a well-understood mission.
Regardless of how one feels about the rest of DDD, the principles of Strategic Design have consistently proven their worth for breaking large codebases into smaller, independent, and maintainable units. This piece focuses purely on those strategic principles and how they apply to Angular development. Other aspects of DDD are beyond the scope of this discussion.
Finding Sub Domains in Your Business
A primary exercise in Strategic Design is the discovery of subdomains. These are specific pockets of the business that bundle together related capabilities, rules, and terminology. Subdomains allow you to slice the problem space into smaller, more approachable chunks. Each one typically maps to a concrete business responsibility and is usually tied to a specific set of domain experts.
Recognizing subdomains is essential for drawing clear boundaries, focusing development where it matters, and connecting technical work to business goals. As an example, an e-procurement system built for employees to order workplace supplies might break down into these subdomains:

Moving from Sub Domains to Bounded Contexts
Where subdomains reflect slices of the real world (the "problem space"), bounded contexts represent those slices within your technical solution (the "solution space"). They are essentially two viewpoints of the same thing. Ideally, there is a one-to-one match between a subdomain and a bounded context. Sometimes, though, it makes sense to split a single subdomain across several bounded contexts.
Every bounded context operates with its own ubiquitous language—a common vocabulary shared by developers and domain experts. This language captures the exact terms, ideas, and rules that matter in that particular context. For instance, the word "product" has a very specific meaning within the ordering context. This shared understanding eliminates confusion and gives everyone involved a single, unambiguous frame of reference.
A useful way to uncover potential bounded contexts is to look at the workflows running through your system. An e-procurement system for office goods, for example, might support these two distinct processes:

Notice that the steps Approve Order, Request Budget, and Approve Budget all revolve around organizational structures, budget limits, and how funds are used. They involve managers making decisions. The other flow, by contrast, centers on individual employees submitting their product requests.
Using Pivotal Events to Draw the Lines
Another technique for spotting the seams between bounded contexts is to search for so-called pivotal events. These are events that "mark a transition between different business phases." A pivotal event typically triggers a significant change of state in a central concept and often hands responsibility from one party to another.
In our example, a pivotal event occurs the moment an employee completes a product request. At that point, the request moves into the Submitted state. Control then shifts to other users—those who will later specify the order and grant approval.
The notion of pivotal events comes from Alberto Brandolini's Event Storming method. Event Storming is a collaborative workshop format where developers and domain experts map out business processes by arranging domain events on a timeline. The exercise often surfaces candidate bounded contexts for further discussion.
I've written a separate, deeper article on applying EventStorming and Strategic Design to frontend solutions.
Multiple Models for the Same Reality
One might argue that "product" is a constant presence throughout an e-procurement system. Yet, a careful look at the processes shows that the word product can mean very different things at different steps. When an employee picks a product from the catalog, the details matter a great deal. In the approval flow, however, only a few essential fields are needed:

So we must treat these two versions of a product as distinct. This results in several models that are each as specific—and therefore as meaningful—as possible. As the example demonstrates, each model is valid only within its own bounded context and follows that context's ubiquitous language.
At the same time, this approach avoids building one mammoth model meant to describe everything at once. Such "god models" are often vague and confusing, and they carry too many entanglements to allow for effective decoupling or subdivision.
Even though these product views differ at the domain level, they can still be linked logically by referencing the same id.
Understanding Context-Mapping
Even though bounded contexts are kept apart from one another, they still need to interact. In our case, the ordering context might need to pull data from the catalog context and also send information to an external ERP system:

How these contexts talk to each other is defined by a context map. In theory, Ordering and Booking could share common model elements. But doing so risks introducing inconsistencies if one side changes.
One option is for one context to directly use the other's model. That raises the question of who depends on whom. Can the consuming side push changes onto the provider and require backward compatibility? Or must the consumer simply accept whatever the provider gives?
In our scenario, Catalog exposes an API that shields its internal changes from consumers. Since ordering has limited leverage over the ERP system, it goes through an anti-corruption layer (ACR). If the ERP system changes, only that layer needs updating.
Another option worth mentioning is Separate Ways. Here, a capability like calculating VAT is deliberately implemented independently in several bounded contexts:

This seems counterintuitive at first glance—it creates duplicate code and goes against the DRY principle (don't repeat yourself). Still, it can be a smart trade-off in certain situations. It avoids a dependency on a shared library. While reducing redundant code is a worthy goal, minimizing dependencies is equally critical. Each dependency is a contract, and contracts are notoriously hard to change. So it's always worth asking whether the cost of a new dependency is truly justified.
Strategic Design offers more patterns for structuring relationships between consumers and providers beyond what's listed here.
Conclusions and What's Next
Strategic Design is about discovering subdomains (the "problem space") and converting them into bounded contexts (the "solution space"). Each bounded context has its own ubiquitous language and its own set of concepts. A context map defines how these contexts interact.
In the upcoming article, we will explore how to turn these bounded contexts into an Angular ecosystem built on an Nx-based monorepo.
