Core Concept

Domain Driven Design

A strategic approach to software development that centers on understanding and modeling the core business domain. Build systems that speak your business language and evolve with your organization.

🏛️
The Core Insight

Most software projects fail not because of technical issues, but because developers and domain experts speak different languages. DDD bridges this gap by putting the domain model at the center of everything.

What is Domain Driven Design?

Domain Driven Design (DDD) was introduced by Eric Evans in his 2003 book. The core philosophy: software should reflect the mental model of the business domain it serves. When code mirrors how domain experts think, it becomes easier to understand, maintain, and evolve.

Key DDD Principles

1
Focus on the Core Domain

Invest your best talent and effort in the business areas that differentiate you

2
Model-Driven Design

Code should directly implement the domain model—no translation layer between design and code

3
Ubiquitous Language

Developers and domain experts use the same terminology everywhere—in code, documentation, and conversation

4
Bounded Contexts

Large systems are divided into explicit boundaries where each model is consistent and meaningful

When to Use DDD

DDD shines in complex domains where:

  • •Business logic is complex: Rules change often and have many edge cases
  • •Domain expertise is critical: You need to work closely with business experts
  • •Long-term evolution: The system will be maintained and extended for years
  • •Multiple teams: Different teams need clear boundaries and interfaces

Not everything needs DDD. For simple CRUD apps or straightforward data pipelines, DDD adds unnecessary complexity. Save it for your core domain.

Strategic Design

Strategic design is about the big picture: how to organize your system into distinct parts and how those parts relate.

🗣️

Ubiquitous Language

A shared vocabulary used by everyone—developers, product managers, designers, and domain experts—in all communication and code.

Why it matters:
  • • Eliminates translation errors between business and tech
  • • Code becomes self-documenting for domain experts
  • • New team members ramp up faster
  • • Reduces misunderstandings in requirements
❌ Without Ubiquitous Language
  • • PM says "customer", dev writes User
  • • Business talks "orders", code has Transaction
  • • "Active user" means different things to different people
âś“ With Ubiquitous Language
  • • Everyone says "Customer", code has Customer
  • • "Order" everywhere: docs, code, conversations
  • • Glossary defines "Active Customer" precisely
📦

Bounded Contexts

Explicit boundaries within which a particular domain model is defined and applicable. Each context has its own ubiquitous language and model.

Key insight:

The same real-world thing often means different things in different contexts. A "Customer" in Sales is different from a "Customer" in Billing—they have different attributes, behaviors, and rules.

Example: E-commerce Platform
Sales Context

Customer, Lead, Quote, Discount

Fulfillment Context

Order, Shipment, Inventory, Warehouse

Billing Context

Account, Invoice, Payment, Subscription

Each context owns its own "Customer" representation with only the data it needs.

🎯

Subdomains: Core, Supporting, Generic

Not all parts of your domain deserve equal investment. Classify subdomains to focus your best effort where it matters most.

🌟 Core Domain

What makes you unique. Your competitive advantage.

  • • Invest heavily
  • • Best developers
  • • Custom built
  • • DDD fully applied
đź”§ Supporting Domain

Necessary but not differentiating. Supports the core.

  • • Medium investment
  • • Could outsource
  • • Simpler patterns OK
  • • Good enough wins
📦 Generic Domain

Commodity. Same for everyone.

  • • Minimal investment
  • • Buy, don't build
  • • Use SaaS products
  • • Auth, email, payments
🗺️

Context Mapping

How bounded contexts relate to and communicate with each other. Understanding these relationships prevents integration nightmares.

Partnership

Teams coordinate closely, succeed or fail together

Customer-Supplier

Upstream team provides what downstream needs

Shared Kernel

Contexts share a small, agreed-upon model subset

Anti-Corruption Layer

Translate external models to protect your domain

Open Host Service

Provide a published API for multiple consumers

Conformist

Downstream adopts upstream's model as-is

Tactical Design

Tactical patterns are the building blocks for implementing your domain model in code. Use these within a single bounded context.

Entities

Objects with a unique identity that persists over time. An entity is the same entity even if all its attributes change.

Customer(id: "C-123")
// Still same customer even if name/email changes

Value Objects

Objects defined by their attributes, not identity. Two value objects with same attributes are equal. Immutable.

Money(100, "USD") === Money(100, "USD")
// Always equal if attributes match

Aggregates

Cluster of entities and value objects treated as a single unit. One entity is the "aggregate root"—all access goes through it.

Order (aggregate root)
  ├── OrderLine[]
  ├── ShippingAddress
  └── PaymentInfo

Domain Events

Something significant that happened in the domain. Used for communication between aggregates and bounded contexts.

OrderPlaced(orderId, customerId, total)
PaymentReceived(orderId, amount)

Repositories

Abstraction for retrieving and persisting aggregates. Hides database details from the domain model.

OrderRepository.findById(id)
OrderRepository.save(order)

Domain Services

Operations that don't naturally belong to an entity or value object. Stateless operations on domain objects.

PricingService.calculateDiscount(order, customer)
InventoryService.checkAvailability(items)

Applying DDD to Your Workflows

DDD + Research to Backlog

Apply DDD thinking during the Research to Backlog flow.

1.Use domain language in user stories and PRDs
2.Identify which bounded context owns the feature
3.Map feature to entities/aggregates early
4.Define domain events that the feature produces

DDD + Backlog to Production

Apply DDD during the Backlog to Production flow.

1.Design aggregates before writing code
2.Keep bounded context boundaries in code structure
3.Use domain events for cross-context communication
4.Validate naming matches ubiquitous language

How saaslete Tools Help

Domain Discovery

  • →Dovetail: Extract domain language from user interviews
  • →Miro/Figma: Event storming and context mapping workshops

Implementation Support

  • →Linear: Organize work by bounded context
  • →Notion: Maintain ubiquitous language glossary

DDD vs Other Approaches

ApproachFocusBest For
Domain Driven DesignBusiness domain model at centerComplex domains, long-lived systems
CRUD/Active RecordDatabase tables drive designSimple apps, admin panels
MicroservicesDeployment & scaling independenceLarge teams, scaling needs
Clean ArchitectureDependency direction & layersTestability, framework independence

đź’ˇ Pro Tip: They're Complementary

DDD provides the strategic boundaries (bounded contexts) that often map to microservices. Clean Architecture works great inside a bounded context. Use DDD to decide what to build; use other patterns for how to build it.

Getting Started with DDD

1

Start with Event Storming

Gather domain experts and developers. Map out domain events on a timeline. This reveals bounded contexts, aggregates, and the ubiquitous language naturally.

2

Build a Ubiquitous Language Glossary

Document every important term. Define it precisely. Update it when understanding evolves. Make it accessible to everyone.

3

Identify Your Core Domain

Ask: "What makes us unique? What do competitors struggle to copy?" That's your core domain. Apply DDD rigorously there. Be pragmatic elsewhere.

4

Draw Context Boundaries

Identify where models diverge. Where does "Customer" mean different things? Draw explicit boundaries. Define how contexts communicate.