top of page

DDD in Microservices World

  • Writer: Anand Nerurkar
    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:

  1. Customer Onboarding / KYC

  2. Loan Application Submission

  3. Credit Evaluation

  4. Risk Assessment

  5. Loan Approval

  6. Loan Disbursement

  7. 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)

  1. Documentation:

    • Publish rate limits and retry policies in API docs (e.g., Swagger + portal).

  2. Onboarding Process:

    • Explain rate limiting and throttling policies upfront during API client onboarding.

  3. Support Guidance:

    • Include detailed error messages with retry-after headers.

    • Provide monitoring dashboards or usage reports for API clients.

  4. 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

  1. Always tier your clients: Free, Standard, Premium — each with its own rate limit.

  2. Implement burst handling: Use token-bucket or leaky-bucket algorithms to allow short-term spikes.

  3. Combine with retries: Clients should implement exponential backoff + jitter for 429/503 responses.

  4. 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

 
 
 

Recent Posts

See All
Ops Efficiency 30 % improvement

how did you achieve 30 % operational efficiency Achieving 30% operational efficiency in a BFSI-grade, microservices-based personal...

 
 
 

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
  • Facebook
  • Twitter
  • LinkedIn

©2024 by AeeroTech. Proudly created with Wix.com

bottom of page