Strategic Decisions: A Framework for DDD Choices
Strategic DDD decisions shape your system's architecture for years. This chapter provides frameworks for making these decisions systematically, not ad-hoc.
TL;DRβ
| Decision | Key Question | Framework |
|---|---|---|
| Context boundaries | Where to draw lines? | Linguistic + team + change analysis |
| Integration pattern | How contexts communicate? | Control + model quality matrix |
| Subdomain investment | Where to focus? | Core/Supporting/Generic classification |
| Technology choices | What to use? | Fitness function evaluation |
The Strategic Decision Frameworkβ
Decision 1: Bounded Context Boundariesβ
The Analysis Frameworkβ
Score each potential boundary on these dimensions:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BOUNDARY ANALYSIS SCORECARD β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β LINGUISTIC COHESION (1-5) β
β Do terms have consistent meaning within boundary? β
β 5 = Perfect consistency β
β 1 = Same words mean different things β
β β
β TEAM ALIGNMENT (1-5) β
β Can one team own this boundary? β
β 5 = Natural team ownership β
β 1 = Multiple teams, unclear ownership β
β β
β CHANGE COUPLING (1-5) β
β Do things inside change together? β
β 5 = Changes are isolated within β
β 1 = Changes ripple across boundaries β
β β
β DATA COHESION (1-5) β
β Is data naturally grouped? β
β 5 = Clear data ownership β
β 1 = Data needed from many places β
β β
β CONSISTENCY REQUIREMENTS (1-5) β
β Does this need strong consistency internally? β
β 5 = Strong consistency needed β
β 1 = Eventual consistency acceptable β
β β
β TOTAL: ___/25 β
β >20 = Strong boundary β
β 15-20 = Reasonable boundary β
β <15 = Reconsider boundary β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Example: E-Commerce Boundary Analysisβ
Candidate: Orders Context
| Dimension | Score | Reasoning |
|---|---|---|
| Linguistic | 5 | "Order", "Line Item", "Checkout" are clear |
| Team | 4 | Orders team owns it, some overlap with Payments |
| Change | 4 | Order logic changes independently |
| Data | 4 | Order data is self-contained |
| Consistency | 5 | Order must be consistent |
| Total | 22/25 | Strong boundary |
Candidate: "Customer" Context
| Dimension | Score | Reasoning |
|---|---|---|
| Linguistic | 2 | "Customer" means different things everywhere |
| Team | 2 | Multiple teams need customer data |
| Change | 2 | Customer changes affect many areas |
| Data | 2 | Customer data spread across systems |
| Consistency | 3 | Some consistency needed |
| Total | 11/25 | Weak boundary - split it |
Decision: Split "Customer" into Multiple Contextsβ
Decision 2: Integration Patternsβ
The Control-Quality Matrixβ
Choose integration pattern based on:
- Control: Do you control the upstream system?
- Model Quality: Is the upstream model good?
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β MODEL QUALITY β
β Low High β
β βββββββββββββ¬ββββββββββββ β
β You β β β β
β Control β ACL β Customer- β β
β β β Supplier β β
β C βββββββββββββΌββββββββββββ€ β
β O β β β β
β N Don't β ACL β Conformistβ β
β T Control β (always) β or β β
β R β β ACL β β
β O βββββββββββββ΄ββββββββββββ β
β L β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Decision Treeβ
Example Decisionsβ
| Integration | Control | Model Quality | Pattern | Reasoning |
|---|---|---|---|---|
| Orders β Inventory | Yes | Good | Customer-Supplier | We can influence Inventory team |
| Orders β Stripe | No | Good | Conformist or ACL | Stripe's model is well-designed |
| Orders β Legacy CRM | Yes | Poor | ACL | Protect from legacy mess |
| Identity β All | Yes | Good | OHS | Many consumers |
Decision 3: Subdomain Investmentβ
Investment Allocation Frameworkβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SUBDOMAIN INVESTMENT MATRIX β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β CORE SUBDOMAIN β
β βββ Engineering: Best engineers, dedicated team β
β βββ Architecture: Full DDD, possibly Event Sourcing β
β βββ Testing: Comprehensive, property-based β
β βββ Documentation: Extensive, living docs β
β βββ Investment: 60-70% of engineering effort β
β β
β SUPPORTING SUBDOMAIN β
β βββ Engineering: Competent engineers, shared team OK β
β βββ Architecture: Simpler patterns, CRUD acceptable β
β βββ Testing: Standard coverage β
β βββ Documentation: Adequate β
β βββ Investment: 20-30% of engineering effort β
β β
β GENERIC SUBDOMAIN β
β βββ Engineering: Any level, integration focus β
β βββ Architecture: Use vendor's patterns β
β βββ Testing: Integration tests only β
β βββ Documentation: Vendor docs + integration notes β
β βββ Investment: 5-10% of engineering effort β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Classification Checklistβ
For each subdomain, answer:
Core Indicators (3+ = Core):
- Provides competitive advantage
- Customers choose us because of this
- Requires deep domain expertise
- Changes frequently based on market
- Would be valuable to competitors
Supporting Indicators (3+ = Supporting):
- Necessary for business operations
- Similar across companies in industry
- Stable requirements
- Could describe to other companies
- No off-the-shelf solution fits perfectly
Generic Indicators (3+ = Generic):
- Same problem every company faces
- Multiple commercial solutions exist
- Well-understood, stable problem
- No competitive advantage possible
- Building custom would be wasteful
Decision 4: Technology Selectionβ
Fitness Function Approachβ
Define what "good" looks like for each context:
// Example: Fitness functions for Orders Context
public class OrdersContextFitnessFunctions
{
// Performance: Order placement < 200ms p99
[Fitness("Order placement latency")]
public bool OrderPlacementLatency() =>
Metrics.GetP99("order.place.latency") < TimeSpan.FromMilliseconds(200);
// Reliability: 99.9% success rate
[Fitness("Order success rate")]
public bool OrderSuccessRate() =>
Metrics.GetSuccessRate("order.place") > 0.999;
// Consistency: No orphaned orders
[Fitness("Order consistency")]
public bool NoOrphanedOrders() =>
Database.Query<Order>(o => o.Status == "pending" && o.Age > TimeSpan.FromHours(1))
.Count() == 0;
}
Technology Decision Matrixβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TECHNOLOGY SELECTION BY SUBDOMAIN β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β CORE SUBDOMAIN β
β βββ Database: Depends on requirements β
β β β’ Event Sourcing? β EventStoreDB, Marten β
β β β’ Complex queries? β PostgreSQL β
β β β’ High write throughput? β Cassandra β
β βββ Language: Team's strongest language β
β βββ Framework: Minimal, domain-focused β
β βββ Deployment: Independent, own lifecycle β
β β
β SUPPORTING SUBDOMAIN β
β βββ Database: PostgreSQL (default), or managed β
β βββ Language: Team standard β
β βββ Framework: Full-featured OK β
β βββ Deployment: Can share infrastructure β
β β
β GENERIC SUBDOMAIN β
β βββ Database: Whatever vendor provides β
β βββ Language: Whatever SDK is best β
β βββ Framework: Vendor's recommended β
β βββ Deployment: SaaS when possible β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Decision Documentation: ADRsβ
Architecture Decision Record Templateβ
# ADR-001: Orders Context Boundary
## Status
Accepted
## Context
We need to define the boundary for order management functionality.
Currently, order-related code is spread across multiple modules.
## Decision
Create a dedicated Orders bounded context that owns:
- Order placement and modification
- Order status and lifecycle
- Order lines and pricing at time of order
The context will NOT own:
- Product catalog (Catalog context)
- Inventory levels (Inventory context)
- Payment processing (Payments context)
## Consequences
### Positive
- Clear ownership for Orders team
- Independent deployment
- Focused domain model
### Negative
- Need integration with Inventory for stock checks
- Need integration with Payments for checkout
- Some data duplication (product info at order time)
### Risks
- Over-fetching from other contexts
- Eventual consistency challenges
## Alternatives Considered
### Alternative 1: Merge with Inventory
Rejected because: Different change rates, different team expertise
### Alternative 2: Smaller boundary (just order placement)
Rejected because: Would fragment order lifecycle
Strategic Decision Checklistβ
Before finalizing strategic decisions:
Boundary Decisionsβ
- Scored each boundary on 5 dimensions
- Boundaries align with team structure
- Each boundary has clear ownership
- Ubiquitous language is consistent within boundaries
- Integration points are identified
Integration Decisionsβ
- Pattern chosen for each integration
- ACL used for external/legacy systems
- OHS defined for multi-consumer scenarios
- Contract testing planned
Investment Decisionsβ
- Each subdomain classified (Core/Supporting/Generic)
- Core subdomains have dedicated teams
- Generic subdomains use existing solutions
- Resource allocation matches classification
Technology Decisionsβ
- Fitness functions defined
- Technology matches subdomain type
- Team has required skills
- Migration path exists
Staff+ Interview Questionsβ
Q: How do you make strategic DDD decisions?
A: I use a systematic framework:
- Discovery first - Event Storming, interviews, domain analysis
- Score boundaries - Linguistic, team, change, data, consistency
- Classify subdomains - Core, Supporting, Generic
- Choose integration patterns - Based on control and model quality
- Document decisions - ADRs with context and consequences
- Validate continuously - Fitness functions, retrospectives
Q: How do you handle disagreements about boundaries?
A: I facilitate data-driven discussions:
- Use the scorecard - Makes discussion concrete
- Try both - Prototype with different boundaries
- Defer to team - Who will own and maintain it?
- Accept uncertainty - Boundaries can evolve
- Document reasoning - Future team understands why
Q: What's the biggest strategic DDD mistake you've seen?
A: Treating everything as core. Teams apply full DDD with Event Sourcing to generic subdomains like authentication or email sending. This wastes engineering effort and adds unnecessary complexity. The fix: ruthlessly classify subdomains and match investment to classification.
Quick Reference Cardβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STRATEGIC DECISIONS QUICK REFERENCE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β BOUNDARY ANALYSIS β
β Score: Linguistic + Team + Change + Data + Consistency β
β >20/25 = Strong boundary β
β β
β INTEGRATION PATTERN β
β Control + Good Model β Customer-Supplier β
β No Control + Good Model β Conformist β
β Poor Model β ACL (always) β
β Many Consumers β OHS β
β β
β INVESTMENT ALLOCATION β
β Core: 60-70%, best engineers, full DDD β
β Supporting: 20-30%, simpler patterns β
β Generic: 5-10%, buy/outsource β
β β
β DOCUMENT WITH ADRs β
β Context β Decision β Consequences β Alternatives β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Next Stepsβ
- Entities vs Value Objects - Start tactical implementation
- Aggregates - Define consistency boundaries
- Context Mapping - Implement integration patterns