Documents/domain/Business Domain Model

Business Domain Model

Business Domain — Product A Analysis

Applying DDD to the specific case study. Domain.md covers theory — this document is the PRACTICAL APPLICATION.


1. Domain Overview

Domain: Enterprise Travel, Event & Workforce Management Platform
Users: ~40,000 globally
Current: Legacy .NET monolith, shared SQL database
Target: .NET 8 microservices, per-service databases

2. Subdomain Classification

Subdomain Type Business Value Build vs Buy Investment
Travel Booking Core ★★★★★ Build (custom logic, competitive) Highest
Event Management Core ★★★★☆ Build (custom workflows) High
Payment Processing Core ★★★★★ Build + integrate gateway Frozen Phase 1
Workforce Management Supporting ★★★☆☆ Build (domain-specific) Medium
Allocation Algorithms Supporting ★★★☆☆ Build (merge with WFM) Medium
Communications Generic ★★☆☆☆ Build thin + use platform (SendGrid, Twilio) Low
Reporting Supporting ★★★☆☆ Build (cross-domain aggregation) Medium

Decision: Merge Allocation into Workforce (same domain: people + resource allocation). Add Reporting (not explicitly stated in the brief, but "Operational Reporting" exists in the monolith diagram).


3. Bounded Context Deep-Dive

3.1 Travel Booking Context

┌─────────────────────────────────────────────────────────────┐
│  TRAVEL BOOKING BOUNDED CONTEXT                              │
│  ════════════════════════════════                             │
│                                                              │
│  Ubiquitous Language:                                        │
│    Booking, Itinerary, Traveler, Supplier, Segment,          │
│    Quote, Confirmation, Cancellation, Amendment               │
│                                                              │
│  Aggregates:                                                  │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Booking (Root)   │  │ Supplier (Root)  │                  │
│  │ ├─ BookingItems  │  │ ├─ Contracts     │                  │
│  │ ├─ Travelers     │  │ ├─ RateCards     │                  │
│  │ ├─ Segments      │  │ └─ Availability  │                  │
│  │ └─ PaymentRef    │  └──────────────────┘                  │
│  └──────────────────┘                                        │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Itinerary (Root) │  │ Quote (Root)     │                  │
│  │ ├─ Legs          │  │ ├─ PriceBreakdown│                  │
│  │ ├─ Accommodations│  │ └─ Expiry        │                  │
│  │ └─ Transfers     │  └──────────────────┘                  │
│  └──────────────────┘                                        │
│                                                              │
│  Domain Events:                                               │
│    BookingRequested → BookingConfirmed → BookingAmended       │
│    BookingCancelled, QuoteExpired, SupplierBooked             │
│                                                              │
│  Commands:                                                    │
│    CreateBooking, ConfirmBooking, AmendBooking,               │
│    CancelBooking, SearchAvailability, RequestQuote            │
│                                                              │
│  Queries:                                                     │
│    GetBookingById, SearchBookings, GetItinerary,              │
│    GetBookingHistory, GetSupplierAvailability                 │
│                                                              │
│  External Dependencies:                                       │
│    → Payment (via ACL): charge, refund                        │
│    → Communications: send confirmation/cancellation email     │
│    → Reporting: publish booking events for dashboards          │
│    → Supplier APIs (GDS/external): search, book, cancel       │
│                                                              │
│  Complexity: HIGH                                             │
│  Reason: "Expedia-like" = search, multi-leg, pricing rules,  │
│          supplier integration, amendment workflows             │
│  Team: D2 (Senior) lead + D1 (Tech Lead) support             │
│  Phase: Phase 1 (M2-4), go-live M3 (canary) → M4 (100%)     │
└─────────────────────────────────────────────────────────────┘

3.2 Event Management Context

┌─────────────────────────────────────────────────────────────┐
│  EVENT MANAGEMENT BOUNDED CONTEXT                            │
│  ════════════════════════════════                             │
│                                                              │
│  Ubiquitous Language:                                        │
│    Event, Venue, Session, Attendee, Registration,            │
│    Agenda, Speaker, Capacity, RSVP                            │
│                                                              │
│  ⚠️ "Event" here = business event/conference,                │
│     NOT a domain event (DDD). Easy to confuse!                │
│                                                              │
│  Aggregates:                                                  │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Event (Root)     │  │ Registration     │                  │
│  │ ├─ Sessions      │  │  (Root)          │                  │
│  │ ├─ Agenda        │  │ ├─ Attendee      │                  │
│  │ ├─ Venue         │  │ ├─ Tickets       │                  │
│  │ └─ Capacity      │  │ └─ DietaryReqs   │                  │
│  └──────────────────┘  └──────────────────┘                  │
│                                                              │
│  Domain Events:                                               │
│    EventCreated, EventPublished, RegistrationOpened,          │
│    AttendeeRegistered, EventCancelled, CapacityReached        │
│                                                              │
│  Commands:                                                    │
│    CreateEvent, PublishEvent, RegisterAttendee,               │
│    CancelEvent, UpdateAgenda, AssignVenue                     │
│                                                              │
│  Queries:                                                     │
│    GetEventById, ListUpcomingEvents, GetAttendeeList,         │
│    GetEventCapacity, SearchEvents                             │
│                                                              │
│  External Dependencies:                                       │
│    → Payment (via ACL): registration fee                      │
│    → Communications: event reminders, updates                 │
│    → Workforce: staff assignment for events                   │
│    → Reporting: event metrics                                 │
│                                                              │
│  Complexity: HIGH (but less than Travel)                      │
│  Reason: Calendar logic, capacity management, attendee flows  │
│  Team: D3 (Mid) lead + D2 (Senior) support                   │
│  Phase: Phase 1 (M3-4), go-live M4                           │
└─────────────────────────────────────────────────────────────┘

3.3 Payment Processing Context (FROZEN)

┌─────────────────────────────────────────────────────────────┐
│  PAYMENT PROCESSING BOUNDED CONTEXT                          │
│  ══════════════════════════════════                           │
│  ⚠️ STATUS: FROZEN Phase 1. Stays in monolith.              │
│                                                              │
│  Ubiquitous Language:                                        │
│    Transaction, Payment, Refund, Invoice, Receipt,           │
│    PaymentMethod, Reconciliation, Settlement                  │
│                                                              │
│  Aggregates (in monolith, NOT migrating):                    │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Transaction(Root)│  │ Invoice (Root)   │                  │
│  │ ├─ LineItems     │  │ ├─ LineItems     │                  │
│  │ ├─ PaymentMethod │  │ └─ TaxBreakdown  │                  │
│  │ └─ Status        │  └──────────────────┘                  │
│  └──────────────────┘                                        │
│                                                              │
│  Integration via ACL:                                         │
│  ┌──────────────────────────────────────────────┐            │
│  │ New Services → PaymentACL → Legacy Payment   │            │
│  │                                               │            │
│  │ ACL exposes:                                  │            │
│  │   ProcessPayment(bookingId, amount, method)   │            │
│  │   RequestRefund(transactionId, amount)         │            │
│  │   GetPaymentStatus(transactionId)              │            │
│  │                                               │            │
│  │ ACL translates:                               │            │
│  │   New service format → legacy API format       │            │
│  │   Legacy errors → standard error codes         │            │
│  │   Adds: logging, retry, circuit breaker        │            │
│  └──────────────────────────────────────────────┘            │
│                                                              │
│  Why frozen?                                                 │
│    1. PCI DSS compliance risk                                │
│    2. Financial transaction = zero error tolerance            │
│    3. Payment gateway integrations (complex)                  │
│    4. Regulatory requirements                                 │
│    5. 5 engineers — insufficient bandwidth                    │
│                                                              │
│  Future (post-Phase 1, possibly Phase 3 or post-9-months):   │
│    Extract → Payment Service (.NET 8)                         │
│    Own database, Stripe/gateway integration                   │
│    PCI compliance validation                                  │
│                                                              │
│  Team: N/A (ACL built by D1 Tech Lead + D2 Senior, ~2 weeks) │
│  Phase: ACL Phase 1 (M2). Migration: deferred beyond M9      │
└─────────────────────────────────────────────────────────────┘

3.4 Workforce Management Context (includes Allocation)

┌─────────────────────────────────────────────────────────────┐
│  WORKFORCE MANAGEMENT BOUNDED CONTEXT                        │
│  ════════════════════════════════════                         │
│  (Merged: Workforce Management + Allocation Algorithms)      │
│                                                              │
│  Ubiquitous Language:                                        │
│    Staff, Shift, Schedule, Skill, Availability,              │
│    Allocation, Assignment, Capacity, Roster                   │
│                                                              │
│  Why merge Allocation?                                       │
│    • Allocation = staff/resource assignment → same WFM domain │
│    • Same data: staff skills, availability, constraints       │
│    • Splitting = 2 services too small for the same domain     │
│    • 1 service with 2 internal modules is sufficient          │
│                                                              │
│  Aggregates:                                                  │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Staff (Root)     │  │ Schedule (Root)  │                  │
│  │ ├─ Skills        │  │ ├─ Shifts        │                  │
│  │ ├─ Availability  │  │ ├─ Assignments   │                  │
│  │ └─ Preferences   │  │ └─ Constraints   │                  │
│  └──────────────────┘  └──────────────────┘                  │
│  ┌──────────────────┐                                        │
│  │ Allocation (Root)│  ← Allocation algorithm                 │
│  │ ├─ Request       │                                        │
│  │ ├─ Candidates    │                                        │
│  │ └─ Result        │                                        │
│  └──────────────────┘                                        │
│                                                              │
│  Domain Events:                                               │
│    StaffCreated, ShiftAssigned, AllocationCompleted,          │
│    SchedulePublished, StaffUnavailable, SkillUpdated          │
│                                                              │
│  Commands:                                                    │
│    CreateStaff, AssignShift, RunAllocation,                   │
│    PublishSchedule, UpdateAvailability                         │
│                                                              │
│  Queries:                                                     │
│    GetStaffById, GetScheduleByWeek, GetAvailableStaff,       │
│    GetAllocationResult, SearchStaffBySkill                    │
│                                                              │
│  External Dependencies:                                       │
│    → Event Management: staff allocated for events             │
│    → Travel Booking: staff assigned for travel support         │
│    → Communications: notify shift changes                     │
│    → Reporting: workforce utilization metrics                  │
│                                                              │
│  Complexity: MEDIUM                                           │
│  Reason: Scheduling logic, constraint-based allocation        │
│  Note: Allocation algorithms = CPU-intensive,                 │
│         may require async processing (queue + worker)         │
│  Team: D4 (Mid) lead                                         │
│  Phase: Phase 2 (M5-6), go-live M6                           │
└─────────────────────────────────────────────────────────────┘

3.5 Communications Context

┌─────────────────────────────────────────────────────────────┐
│  COMMUNICATIONS BOUNDED CONTEXT                              │
│  ══════════════════════════════                               │
│                                                              │
│  Ubiquitous Language:                                        │
│    Notification, Template, Channel, Recipient,               │
│    DeliveryStatus, Preference, Queue                          │
│                                                              │
│  Aggregates:                                                  │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Notification     │  │ Template (Root)  │                  │
│  │  (Root)          │  │ ├─ Placeholders  │                  │
│  │ ├─ Recipients    │  │ ├─ Channel       │                  │
│  │ ├─ Channel       │  │ └─ Version       │                  │
│  │ └─ DeliveryLog   │  └──────────────────┘                  │
│  └──────────────────┘                                        │
│  ┌──────────────────┐                                        │
│  │ Preference(Root) │  ← User notification settings          │
│  │ ├─ Channels      │                                        │
│  │ └─ Frequency     │                                        │
│  └──────────────────┘                                        │
│                                                              │
│  Domain Events:                                               │
│    NotificationQueued, NotificationSent,                      │
│    NotificationFailed, TemplateUpdated                        │
│                                                              │
│  Commands:                                                    │
│    SendNotification, CreateTemplate, UpdatePreference,        │
│    RetryFailedNotification                                    │
│                                                              │
│  Queries:                                                     │
│    GetDeliveryStatus, GetNotificationHistory,                 │
│    GetTemplates, GetUserPreferences                           │
│                                                              │
│  Channels:                                                    │
│    Email (SendGrid/SES), SMS (Twilio), Push, In-App           │
│                                                              │
│  External Dependencies:                                       │
│    ← ALL other services: everyone sends notifications         │
│    → External providers: SendGrid, Twilio, Firebase           │
│                                                              │
│  Complexity: LOW                                              │
│  Reason: Well-defined, stateless processing, no complex logic │
│  Why pilot? Simplest domain, cross-cutting, thin integration  │
│  Team: D4 (Mid) primary + D3 secondary                       │
│  Phase: Phase 0 (M1) pilot (D3+D4) → Phase 2 (M7) complete  │
└─────────────────────────────────────────────────────────────┘

3.6 Reporting Context

┌─────────────────────────────────────────────────────────────┐
│  REPORTING BOUNDED CONTEXT                                   │
│  ═════════════════════════                                   │
│  (Not explicitly stated in the brief, but the monolith has   │
│   "Operational Reporting" → needs extraction)                │
│                                                              │
│  Ubiquitous Language:                                        │
│    Report, Dashboard, Metric, KPI, DataSource,               │
│    Aggregation, Schedule, Export                               │
│                                                              │
│  Aggregates:                                                  │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ Report (Root)    │  │ Dashboard (Root) │                  │
│  │ ├─ DataSources   │  │ ├─ Widgets       │                  │
│  │ ├─ Filters       │  │ ├─ Layout        │                  │
│  │ └─ Schedule      │  │ └─ Permissions   │                  │
│  └──────────────────┘  └──────────────────┘                  │
│                                                              │
│  Notable — READ-ONLY service:                                │
│    • No complex business commands                            │
│    • Subscribes to events from ALL services                  │
│    • Materializes into read-optimized tables                 │
│    • CQRS pattern: this IS the read side                     │
│                                                              │
│  Data Sources (via events):                                   │
│    ← Travel: BookingCreated, BookingCancelled → booking stats │
│    ← Event: AttendeeRegistered, EventCreated → event metrics  │
│    ← Workforce: ShiftAssigned, AllocationDone → utilization   │
│    ← Payment (via ACL): TransactionCompleted → revenue data   │
│    ← Communications: NotificationSent → delivery metrics      │
│                                                              │
│  Queries:                                                     │
│    GetDashboard, RunReport, ExportCSV, GetKPIs,              │
│    GetTrendData, GetBookingStats, GetRevenueReport            │
│                                                              │
│  Complexity: MEDIUM                                           │
│  Reason: Many data sources, aggregation logic, but no write   │
│          business logic. Main challenge = data consistency     │
│  Team: D5 (Mid) lead                                         │
│  Phase: Phase 2 (M6-7), go-live M7                           │
└─────────────────────────────────────────────────────────────┘

4. Context Map — Inter-Service Relationships

                    ┌──────────────────┐
                    │   API Gateway    │
                    │     (YARP)       │
                    └────────┬─────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
        ▼                    ▼                    ▼
┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│   TRAVEL     │   │    EVENT     │   │  WORKFORCE   │
│   BOOKING    │   │  MANAGEMENT  │   │  + ALLOCATION│
│              │   │              │   │              │
│  [Core]      │   │  [Core]      │   │  [Supporting]│
└──────┬───────┘   └──────┬───────┘   └──────┬───────┘
       │                  │                  │
       │    Events (Azure Service Bus)       │
       ├──────────────────┼──────────────────┤
       │                  │                  │
       ▼                  ▼                  ▼
┌──────────────┐   ┌──────────────┐   ╔══════════════╗
│ COMMS        │   │  REPORTING   │   ║   PAYMENT    ║
│              │   │  (read-only) │   ║  (MONOLITH)  ║
│ [Generic]    │   │  [Supporting]│   ║  [Frozen]    ║
└──────────────┘   └──────────────┘   ╚══════╤═══════╝
                                             │
                                      ┌──────┴───────┐
                                      │     ACL      │
                                      │ (Adapter)    │
                                      └──────────────┘

Relationship Types:
─────────────────────────────────────────────────────

Travel ──[Customer-Supplier]──→ Payment (via ACL)
  Travel requests payment processing, Payment provides service

Event ──[Customer-Supplier]──→ Payment (via ACL)
  Event registration fees processed by Payment

Travel ──[Publisher]──→ Comms (via events)
  BookingConfirmed → send confirmation email

Event ──[Publisher]──→ Comms (via events)
  AttendeeRegistered → send welcome email

Event ──[Partner]──→ Workforce
  EventCreated → trigger staff allocation request

Travel ──[Publisher]──→ Reporting (via events)
Event ──[Publisher]──→ Reporting (via events)
Workforce ──[Publisher]──→ Reporting (via events)
  All services → publish events → Reporting materializes

All New Services ──[ACL]──→ Legacy Monolith
  Anti-Corruption Layer protects new services from legacy internals

4.1 Event Flow Matrix

Publisher Event Subscribers Action
Travel BookingCreated Comms, Reporting Send email, update dashboard
Travel BookingConfirmed Payment (ACL), Comms, Reporting Charge card, send confirmation, record
Travel BookingCancelled Payment (ACL), Comms, Reporting Refund, send cancellation, record
Event Mgmt EventCreated Reporting Record new event
Event Mgmt AttendeeRegistered Payment (ACL), Comms, Reporting Charge fee, send welcome, record
Event Mgmt CapacityReached Comms Notify waitlist
Workforce ShiftAssigned Comms, Reporting Notify staff, record
Workforce AllocationCompleted Event Mgmt, Reporting Confirm staff for event
Payment (legacy) PaymentProcessed Travel/Event (via ACL), Reporting Confirm booking, record revenue

5. Shared Kernel — Shared Concepts (Minimal)

⚠️ Shared Kernel must be EXTREMELY SMALL. Only share what is MANDATORY.

Shared package: PhoenixDX.SharedKernel (NuGet internal)

Contains:
  • UserId (value object) — identifier across services
  • Money (value object) — Amount + Currency
  • DateRange (value object) — Start + End date
  • Address (value object) — Street, City, Country
  • IntegrationEvent (base class) — EventId, Timestamp, CorrelationId
  • Result<T> (generic) — Success/Failure pattern
  
Must NOT contain:
  ✗ Business entities (Booking, Event, Staff)
  ✗ Business logic
  ✗ Database entities/migrations
  ✗ Service-specific DTOs
  
Rule: Any SharedKernel change → requires updating ALL services
      → Keep it as small as possible

6. Migration Order — Domain-Driven Justification

Order Service Justification
1 Communications Generic subdomain, simplest, AI pilot. Establishes pattern template for the team
2 Travel Booking Core domain, highest value, hardest. Start early = more time for complexity
3 Event Management Core domain, runs in parallel with Travel tail. Reuses patterns from Travel
4 Workforce + Allocation Supporting, depends on Event (staff for events). Extract after Event is stable
5 Reporting Read-only, depends on events from ALL services. Extract last = more event sources are available
6 Payment Frozen. ACL only. Migration deferred beyond 9 months

Why NOT start with the core domain (Travel) immediately?

Phase 0 pilot = Communications because:
  1. Simple → team learns patterns without being overwhelmed
  2. Cross-cutting → every service will call Comms → build API contracts early
  3. Low risk → if email is delayed 5 min = acceptable, booking delay = NOT OK
  4. AI pilot → test agentic migration workflow on a simple domain first
  5. Pattern template → Travel team copies proven patterns from Comms pilot
  
After pilot → Travel begins Phase 1 with confidence + proven patterns

7. Database Decomposition Strategy

LEGACY (current state):
┌──────────────────────────────────────────────────┐
│              Shared SQL Server                    │
│                                                   │
│  dbo.Bookings        dbo.Events                  │
│  dbo.Travelers       dbo.Attendees               │
│  dbo.Payments        dbo.Invoices                │
│  dbo.Staff           dbo.Shifts                  │
│  dbo.Notifications   dbo.Templates               │
│  dbo.Reports         dbo.Users                   │
│                                                   │
│  ← Shared tables: dbo.Users, dbo.AuditLog        │
│  ← Cross-domain FKs: Bookings.PaymentId → Payments│
│  ← Cross-domain views: vw_BookingRevenue (JOIN 5) │
└──────────────────────────────────────────────────┘

MIGRATION STEPS:
─────────────────

Step 1: Identify table ownership
  Travel owns: Bookings, Travelers, Itineraries, Suppliers
  Event owns: Events, Attendees, Sessions, Venues
  Workforce owns: Staff, Shifts, Skills, Allocations
  Comms owns: Notifications, Templates, Preferences
  Reporting owns: Reports, Dashboards (+ materialized views)
  Payment owns: Payments, Invoices, Transactions (STAYS in monolith)
  Shared: Users → extract to identity service or keep in gateway

Step 2: Break cross-domain FKs
  Bookings.PaymentId → replace with PaymentReference (string, not FK)
  Events.VenueId if Venue is shared → duplicate into Event DB
  
Step 3: CDC for transition
  New service DB ← CDC sync ← Legacy DB (during dual-run period)
  When service goes live → stop CDC → service owns data solely
  
Step 4: Handle cross-domain queries
  vw_BookingRevenue → Reporting service materialized view
  Built from events: BookingConfirmed + PaymentProcessed

8. Summary — Service Registry

Service BC Type DB Phase Go-Live Owner Complexity
Travel Booking Travel Core Azure SQL Phase 1 M3-M4 D2 (+D1) High
Event Management Event Core Azure SQL Phase 1 M4 D3 (+D2) High
Workforce + Allocation WFM Supporting Azure SQL Phase 2 M6 D4 Medium
Communications Comms Generic Azure SQL Phase 0→2 M1(pilot)→M7 D4 (+D3) Low
Reporting Reporting Supporting Azure SQL (read) Phase 2 M7 D5 (+D3) Medium
Payment (ACL only) Payment Core (frozen) Legacy DB Phase 1 M2 (ACL) D1 (+D2) ACL only
API Gateway Infra Platform N/A Phase 0 M1 D1 Medium
Shared Libraries Infra Platform N/A Phase 0 M1 D1+D5 Low