DDD in Microservices World
- Anand Nerurkar
- Apr 18
- 12 min read
🧭 What Is DDD?
Domain-Driven Design (DDD) is a software design approach focused on:
Deep understanding of the business domain
Structuring code around business capabilities
Using ubiquitous language (shared between devs and business stakeholders)
⚙️ How DDD Aligns with Microservices
DDD naturally fits into microservices because each microservice encapsulates a business subdomain.
🧱 DDD → Microservices Mapping
DDD Concept | Microservices Concept |
Bounded Context | Microservice |
Aggregate | Consistent data boundary within service |
Entity / Value Object | Domain Model |
Domain Events | Asynchronous messaging (Kafka, etc.) |
Ubiquitous Language | Shared APIs, aligned naming |
Repositories | Data access within each service boundary |
🧱 What is a Bounded Context?
A bounded context is a logical boundary within your system where a specific domain model is defined and used consistently.
It:
Represents a module or subdomain of the application.
Has clear boundaries and a ubiquitous language specific to that context.
May communicate with other contexts via APIs, messaging, or events.
🧩 What is an Aggregate?
An aggregate is a group of related entities and value objects that are treated as one unit for data changes.
It:
Has an aggregate root (main entity) that controls access to its internals.
Enforces business rules and transactional consistency.
Is the only thing exposed outside its own boundary.
💼 Banking Example: "Loan Management" Context
Let’s say you're building a digital banking platform, and one of the bounded contexts is:
🔹 Bounded Context: Loan Management
Purpose: Handle everything related to customer loans — application, approval, disbursement, and repayment.
Ubiquitous language: "Loan", "Credit Score", "Repayment", "Installment", "EMI", etc.
Owned by: The Loan Product team.
🧱 Inside this context, we define the Loan Aggregate:
✅ Aggregate Root: Loan
Main entry point; all operations go through this.
📦 Other Entities/Value Objects:
LoanApplication (Value Object)
RepaymentSchedule (Entity)
Installment (Value Object)
LoanStatus (Enum or Value Object)
🔄 Example Use Case:
A customer applies for a ₹5 lakh loan. The loan goes through credit checks, and upon approval, a repayment schedule is generated.
Internally:
The Loan aggregate handles:
Checking eligibility (e.g., based on credit score).
Generating repayment plan (EMIs, interest).
Changing status from Pending → Approved.
Ensuring no external service can just modify a RepaymentSchedule or mark the loan as Approved directly — only the Loan aggregate can do this.
📬 Integration with Other Bounded Contexts:
The Customer Context is responsible for customer data.
The Risk Assessment Context evaluates credit scores.
The Loan Management context calls APIs or subscribes to events from those contexts but does not mix their logic or models internally.
🔄 Summary:
Concept | In Banking Example |
Bounded Context | Loan Management System |
Aggregate Root | Loan |
Aggregate Components | RepaymentSchedule, Installments, LoanApplication |
External Communication | Customer, Risk Assessment via API/Events |
🏗️ Practical Usage of DDD in Microservices
1. Identify Bounded Contexts
Split the system into bounded contexts like:
User Management
KYC
Wallet
Transactions
Ledger
Notifications
Each of these maps to a microservice, owning its own database, logic, and APIs.
2. Define Aggregates
Within a service, identify aggregates that ensure consistency boundaries.
Example (Transaction Service):
java
CopyEdit
class Transaction { TransactionId id; Wallet fromWallet; Wallet toWallet; Amount amount; Status status; void initiate() { // business rules } }
3. Use Domain Events
Emit events when something happens in your domain.
java
CopyEdit
class TransactionService { void completeTransaction(Transaction txn) { txn.complete(); eventPublisher.publish(new TransactionCompletedEvent(txn.getId())); } }
Events are consumed by other services like WalletService, NotificationService.
4. Ubiquitous Language
Business and devs agree on terms like "Top-up", "Disbursement", "KYC-Verified", etc.
These terms are reflected in class names, API endpoints, events, and documentation.
5. Strategic Design + Team Organization
Align teams with bounded contexts (Conway’s Law)
Each team owns a domain and its associated service end-to-end
🧰 Tech Stack in DDD for Microservices
Spring Boot: Rich support for layered architecture (entities, repositories, services)
Kafka/Event Hubs: For domain event propagation
JPA: For modeling entities and aggregates
MapStruct/Lombok: For mapping DTOs and clean domain code
Swagger/OpenAPI: Documenting APIs using domain language
✅ Benefits of DDD in Microservices
Business-aligned microservice boundaries
Decoupled, scalable architecture
Easier to evolve and test
Clear ownership and separation of concerns
Would you like:
A sample DDD-based microservice project structure in Spring Boot?
Visuals (like DDD layered architecture or bounded context diagrams)?
A real-world banking use case explained with DDD principles?
Let me know how deep you want to go!
4o
You said:
A real-world banking use case explained with DDD principles?
ChatGPT said:
Perfect — let’s walk through a real-world banking use case using Domain-Driven Design (DDD) principles, step by step. We'll focus on the Loan Origination Process in a Digital Lending Platform, a common and rich domain that fits DDD really well.
🏦 Real-World Banking Use Case: Loan Origination
🎯 Business Goal:
Allow customers to apply for loans digitally, perform credit checks, verify KYC, and approve/disburse loans — fully automated, yet modular.
🧠 Step 1: Understand the Domain
Break the process into high-level business capabilities:
Customer Onboarding / KYC
Loan Application Submission
Credit Evaluation
Risk Assessment
Loan Approval
Loan Disbursement
Notification & Tracking
🔲 Step 2: Define Bounded Contexts → Microservices
Bounded Context (DDD) | Corresponding Microservice |
Customer Management | CustomerService |
KYC Verification | KYCService |
Loan Origination | LoanApplicationService |
Credit Evaluation | CreditService |
Risk Management | RiskAssessmentService |
Approval Workflow | ApprovalService |
Disbursement | DisbursementService |
Notification | NotificationService |
Each bounded context encapsulates domain logic and owns its data.
🧱 Step 3: Model Aggregates
Example: LoanApplication Aggregate
java
CopyEdit
class LoanApplication { UUID id; CustomerId customerId; LoanAmount amount; LoanStatus status; void submitApplication() { if (status != LoanStatus.DRAFT) throw new InvalidStateException(); status = LoanStatus.SUBMITTED; } void approve() { if (status != LoanStatus.UNDER_REVIEW) throw new InvalidStateException(); status = LoanStatus.APPROVED; } void reject() { status = LoanStatus.REJECTED; } }
This ensures consistency within the boundary of the LoanApplication entity.
📣 Step 4: Use Domain Events
Each domain action emits events to inform other services:
java
CopyEdit
eventPublisher.publish(new LoanApplicationSubmittedEvent(applicationId));
CreditService consumes LoanApplicationSubmittedEvent
ApprovalService listens to CreditCheckedEvent and starts review
DisbursementService listens to LoanApprovedEvent to release funds
✅ Ensures eventual consistency and loose coupling
💬 Step 5: Define Ubiquitous Language
“Loan Application”, “KYC-Verified”, “CreditScoreCalculated”, “LoanDisbursed”
These terms are used in code, APIs, documentation, and business meetings
Promotes shared understanding
🔐 Step 6: Strategic Design + Team Alignment
Each microservice is owned by a cross-functional team (dev + QA + BA)
DDD encourages teams to go deep into their subdomain
Use Context Maps to document integrations between services
🖼️ Architecture View (Simplified)
css
CopyEdit
[ CustomerService ] ──> [ KYCService ] ──> [ LoanApplicationService ] └──> [ CreditService ] └──> [ RiskAssessmentService ] └──> [ ApprovalService ] └──> [ DisbursementService ] └──> [ NotificationService ]
All services are:
Spring Boot based
Communicate via Kafka for events
Use Azure SQL per service
Deployed via AKS + Istio for service mesh
CI/CD via Azure DevOps
✅ Summary: DDD in This Banking Use Case
Principle | Implementation |
Bounded Contexts | Microservices per domain capability |
Aggregates | Domain models with invariants |
Domain Events | Kafka events for async communication |
Ubiquitous Language | Shared business language everywhere |
Strategic Design | Team ownership per service/domain |
Would you like:
A full Spring Boot project structure implementing this?
A context map diagram or C4 model view of this architecture?
Sample domain models in code?
Let me know how you’d like to go deeper!
4o
You said:
DDD layered architecture or bounded context
ChatGPT said:
Great! Let’s break down both DDD Layered Architecture and Bounded Context, and then show how they fit together — especially in a microservices-based banking system like Digital Lending or Wallet platforms.
🧱 1. Domain-Driven Design (DDD) Layered Architecture
DDD typically follows a 4-layered architecture, separating concerns clearly:
pgsql
CopyEdit
+-----------------------------+ | Presentation Layer | → Exposes APIs/UI, handles HTTP/REST +-----------------------------+ | Application Layer | → Orchestrates use cases, invokes domain logic +-----------------------------+ | Domain Layer | → Pure business logic, entities, value objects, aggregates +-----------------------------+ | Infrastructure Layer | → DB access, messaging, external systems +-----------------------------+
🔍 Layer Details
Layer | Responsibilities |
Presentation | Controllers, UI, API endpoints |
Application | Service classes, use-case orchestration, transaction management |
Domain | Business rules, entities, aggregates, value objects, domain events |
Infrastructure | Repositories, Kafka clients, REST clients, file systems, database connectivity |
✅ Only Application Layer should coordinate things; Domain Layer should not know anything about Infrastructure or Web.
🧭 2. Bounded Context in DDD
✳️ Definition
A Bounded Context defines the boundaries of a particular domain model and ensures clear meaning and responsibility within that boundary.
Each bounded context maps to one microservice.
💡 Example: Bounded Contexts in a Banking Use Case
Business Domain | Bounded Context | Microservice |
Customer Onboarding | Customer Management | CustomerService |
Identity Management | KYC Verification | KYCService |
Lending | Loan Origination | LoanApplicationService |
Lending | Credit Evaluation | CreditService |
Risk | Risk Assessment | RiskAssessmentService |
Finance Ops | Loan Disbursement | DisbursementService |
Communication | Notification | NotificationService |
Each context:
Has its own model
Owns its data store
Communicates via events or APIs
Uses ubiquitous language for its domain
🧩 How Layered Architecture Fits Within a Bounded Context
Each bounded context (microservice) implements the DDD layers internally:
Example: LoanApplicationService
markdown
CopyEdit
loan-application-service/ ├── application/ │ └── LoanApplicationService.java ├── domain/ │ ├── LoanApplication.java │ ├── LoanStatus.java │ └── LoanSubmittedEvent.java ├── infrastructure/ │ ├── LoanRepositoryImpl.java │ └── KafkaEventPublisher.java └── presentation/ └── LoanApplicationController.java
✅ This structure enforces clean architecture principles with DDD.
🗺️ Visualizing Both Together
🖼️ System-Level View
lua
CopyEdit
+---------------------------+ | CustomerService | | (Bounded Context) | +---------------------------+ | v +---------------------------+ | KYCService | +---------------------------+ | v +---------------------------+ | LoanApplicationService | +---------------------------+ | v +---------------------------+ | CreditService | +---------------------------+
Each microservice has its own:
Bounded context
Domain model
Layered architecture
✅ Benefits of This Approach
Clear ownership and modularity
Each team focuses on one bounded context
Enables scalability and independent deployment
Avoids entangled data models and logic
Promotes business-aligned architecture
Would you like:
A diagram showing the layered architecture inside a microservice?
A context map of all bounded contexts in a banking platform?
A Spring Boot project skeleton using DDD layering?
Let me know how you want to visualize or implement it!
4o
You said:
context map of all bounded contexts in a banking platform
ChatGPT said:
Here’s a Context Map of bounded contexts in a typical digital banking platform, following DDD principles — it shows how various domains are broken down, and how they interact.
🧭 What is a Context Map?
A Context Map is a high-level diagram in DDD that:
Shows all bounded contexts
Maps relationships between them
Highlights integration styles (REST, messaging, APIs)
Helps visualize team ownership and service responsibilities
🏦 Banking Platform: Context Map
pgsql
CopyEdit
+------------------------+ | External Systems | | (Credit Bureau, Aadhaar)| +-----------+------------+ | v +-------------------+ +--------------------+ +----------------------+ | Customer Context |<------>| KYC Context |<---->| Identity Verification | | (CRM, Profile) | | (eKYC, PAN/Aadhaar)| | (External APIs) | +--------+----------+ +---------+----------+ +----------------------+ | | v v +--------+----------+ +---------+----------+ +------------------------+ | Loan Origination |<------>| Credit Evaluation |<---->| Risk Management Context | | (Apply, Status) | | (Score, History) | | (Rule engine, ML) | +--------+----------+ +---------+----------+ +------------------------+ | | v | +--------+----------+ +---------+----------+ +-------------------------+ | Approval Workflow |<------>| Underwriting Rules | | Product Catalog | | (Manual + Auto) | | (Credit Policy) | | (Loan, Credit, Cards) | +--------+----------+ +---------------------+ +-------------------------+ | v +--------+----------+ +----------------------+ +-------------------------+ | Disbursement |<----->| Payment Gateway |<---->| Core Banking Context | | (Fund Transfer) | | (UPI, IMPS, NEFT) | | (Accounts, Ledger) | +--------+----------+ +----------------------+ +-------------------------+ | v +--------------------+ +---------------------+ | Notification |<----->| Audit/Activity Logs | | (Email, SMS, Push) | +---------------------+ +--------------------+
📦 Bounded Contexts with Descriptions
Context | Responsibility | Tech/Integration |
Customer Context | Profile, contact info, preferences | REST APIs, Azure SQL |
KYC Context | Aadhaar, PAN, eKYC checks | Kafka, Aadhaar APIs |
Identity Verification | OCR, Face Match, Liveness | External API integrations |
Loan Origination | Apply for loan, track status | REST, Event-based |
Credit Evaluation | Fetch credit score/history | REST APIs, Kafka |
Risk Management | Apply risk models, fraud scoring | ML Models, Python, Kafka |
Underwriting Rules | Credit rules and eligibility logic | Internal rules engine |
Approval Workflow | Human or auto approval flows | Camunda/Workflow engine |
Disbursement | Initiate bank transfers | Payment API, IMPS/NEFT |
Notification | Send emails, SMS, push alerts | Kafka, Twilio, SendGrid |
Audit Logs | Track activity logs and user actions | Kafka, Azure Monitor |
Core Banking | Ledger, transactions, account balances | Mainframe, API Gateway |
Product Catalog | Loan types, interest rates, term plans | Azure SQL, Cache |
External Systems | Credit bureaus, UIDAI, PAN, banking APIs | External REST APIs |
🔄 Integration Patterns
Pattern | Usage Example |
REST APIs | Customer → KYC, Loan → Credit, Loan → Product |
Event-Driven | Loan Submitted → Credit Check → Risk Assessment |
Synchronous | Loan App → Product Catalog |
Asynchronous | KYC → Notification, Disbursement → Audit Log |
🧑🤝🧑 Team Alignment (Strategic DDD)
Each context is typically owned by one cross-functional team
Ensures bounded autonomy, modularity, and faster deployments
⚙️ Rate Limiting vs Throttling – Quick Difference
Term | Description |
Rate Limiting | Controls how many requests a client can make in a given time window (e.g., 100 requests per minute). Prevents system abuse. |
Throttling | Controls or slows down traffic when the system is under high load. May delay or queue requests instead of rejecting them. |
📊 Key KPIs for Rate Limiting and Throttling
Here are the important KPIs you should monitor to ensure healthy API usage and enforce policies effectively:
1. Requests Per Second (RPS) / Transactions Per Second (TPS)
Measures how many requests are coming in.
Helps decide thresholds for rate limiting.
2. Rate Limit Hit Count
Number of requests that were blocked due to exceeding the rate limit.
Shows how often users are hitting the ceiling.
3. Throttled Request Count
Number of requests that were intentionally delayed or queued due to throttling.
4. Rejected Requests Count
Requests rejected (e.g., HTTP 429: Too Many Requests).
Critical for identifying potential abuse or misconfigured limits.
5. API Usage Per Client / Token / IP
Breaks down request counts by client ID, API key, or IP.
Helps identify high-volume consumers and shape usage.
6. Latency of Throttled Requests
Measures how long throttled requests waited before being processed.
Helps fine-tune throttling policies.
7. Burst Rate
Measures short-term spikes in traffic that may violate sustained rate limits.
Useful for tuning burst windows.
8. Quota Consumption (if using quotas)
How much of the allocated monthly/weekly quota is used.
Useful for API monetization or partner management.
📈 Example Dashboard Components (for observability)
In Azure or other platforms, you might include:
Rate Limit Graph: Shows usage vs threshold over time.
Throttle Heatmap: Visual of when and where throttling occurred.
Top Offenders: List of top IPs or API clients hitting limits.
Alerting Metrics: Triggers for excessive 429s or throttling spikes.
📦 Tools & Services Supporting This
Azure API Management
Built-in support for rate limiting and quotas.
Monitors throttling with metrics and logs.
Istio / Envoy
Fine-grained rate limiting per route or user.
Spring Cloud Gateway (Java microservices)
RateLimiter filter using Redis for distributed limits.
Kong, Apigee, NGINX: Commercial gateways with good rate limit dashboards.
🏁 Summary Table
KPI Name | Description | Use |
Requests Per Second (RPS) | Overall traffic metric | Capacity planning |
Rate Limit Hits | Number of denied requests (HTTP 429) | Abuse detection |
Throttled Requests | Number of delayed/queued requests | Load control |
Top Clients/IPs | Who’s consuming the most | Governance |
Latency of Throttled Req. | Delay introduced due to throttling | Performance tuning |
Quota Usage | Usage per consumer vs allowed quota | API plans |
Let me know if you'd like a Prometheus/Grafana dashboard setup, an Azure API Management policy snippet, or a Spring Cloud Gateway example!
4o
You said:
what is typical response in enterprise for rate limiting and throttling
ChatGPT said:
In an enterprise environment, handling rate limiting and throttling requires a balance of system protection, user experience, and communication with consuming systems or partners. Below is the typical response strategy — both technical (HTTP-level) and process/policy-wise.
✅ Typical Technical Response
1. Rate Limiting
When a client exceeds the allowed number of requests per time window:
HTTP Status Code: 429 Too Many Requests
Response Headers (common practice):
http
CopyEdit
HTTP/1.1 429 Too Many Requests Retry-After: 60 X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1713475380
Body (JSON or XML):
json
CopyEdit
{ "error": "Rate limit exceeded", "message": "You have exceeded the number of allowed requests. Please try again after 60 seconds." }
2. Throttling (During Load)
When the system is under heavy load and needs to slow down request processing (not necessarily reject):
HTTP Status Code:
503 Service Unavailable (if rejecting)
429 Too Many Requests (with soft retry mechanism)
Headers may include:
Retry-After, or custom X-Throttle-* headers
Body (optional message):
json
CopyEdit
{ "error": "Service temporarily overloaded", "message": "Your request was throttled. Please retry after some time." }
🏢 Enterprise-Level Practices & Policies
🔐 API Gateway Layer
Use tools like Azure API Management, Apigee, Kong, or NGINX for implementing policies.
Set rules per:
API
IP address
Subscription key/client ID
User role or tier
🧾 Policy Documents Include:
SLA (Service Level Agreement) definitions
Request quotas per client (hourly/daily/monthly)
Behavior during burst traffic
Retry guidance
Escalation process for partners/customers
🤝 Communication with Clients (Internal or External)
Documentation:
Publish rate limits and retry policies in API docs (e.g., Swagger + portal).
Onboarding Process:
Explain rate limiting and throttling policies upfront during API client onboarding.
Support Guidance:
Include detailed error messages with retry-after headers.
Provide monitoring dashboards or usage reports for API clients.
Graceful Degradation Strategy:
For internal consumers, throttle lower-priority features (e.g., logs, analytics) first.
For premium clients, implement tiered limits or allow burst capacity.
💡 Pro Tips
Use circuit breakers + retry with backoff to avoid cascading failures.
Log every rate limit or throttle event for audit and analytics.
Alert if throttling or 429 errors spike — may indicate abuse or misconfigured consumers.
Would you like a sample Azure API Management rate-limiting policy, or a Spring Cloud Gateway filter implementation for rate limiting?
4o
You said:
what is typical value in enterprse for rate liming for ex : 100 req/sec smae for throttling
ChatGPT said:
Great question! The typical rate limiting and throttling values in an enterprise depend on the type of API, business criticality, consumer profile, and infrastructure capacity. But here are some practical baseline values and patterns you’ll commonly see in real-world enterprise environments:
✅ Typical Rate Limiting Values (Enterprise Use Cases)
API Type | Typical Limit Example | Notes |
Internal Microservices | 100–1000 requests/sec | Usually higher, trust-based, tuned by service importance |
Partner APIs | 50–100 requests/sec | Controlled access, especially in B2B use cases |
Public APIs (tiered) | Free Tier: 10–20 req/sec Premium: 100–200 req/sec | Monetization model applies |
Batch / File Upload APIs | 10–50 requests/min | Lower because payloads are large |
Mobile App APIs | 10–50 requests/sec per user/IP | Helps manage load and abuse |
High Throughput APIs | Up to 5000+ requests/sec (with scaling) | For eventing, telemetry, logs — with autoscaling backend |
⚙️ Throttling Thresholds (Soft Limits)
Trigger Condition | Action Taken |
80% of infra CPU/memory | Begin delaying requests (throttling) |
API RPS > baseline for N mins | Queue or reject non-critical requests |
DB or downstream latency spikes | Apply throttling to dependent services |
Example Values:
Start throttling at 1000 req/sec if the system can handle 1200 comfortably.
Queue requests for 50–200ms delay to absorb spikes.
Allow bursts for 1–2 seconds over threshold before throttling.
🎯 Azure-Specific (API Management / Gateway)
Azure API Management default example (per subscription/client):
xml
CopyEdit
<rate-limit-by-key calls="100" renewal-period="60" />
→ 100 requests per minute per subscription key
Burst limit (optional): Allow 100 requests instantly, then refill slowly (token bucket algorithm).
🧠 Best Practices
Always tier your clients: Free, Standard, Premium — each with its own rate limit.
Implement burst handling: Use token-bucket or leaky-bucket algorithms to allow short-term spikes.
Combine with retries: Clients should implement exponential backoff + jitter for 429/503 responses.
Throttle by dimension: user ID, IP, client ID, API path, etc.
🔧 Example (Internal Enterprise API Rate Limit Policy)
yaml
CopyEdit
Limit: 1000 requests per second per service Burst: Up to 1500 requests allowed in 1 second Throttle: Apply soft delay once traffic > 80% of average RPS for 2 mins
Comments