Clean • Professional
Domain-Driven Design (DDD) is a software development approach that focuses on modeling software around the core business domain and its rules instead of technical layers like controllers, services, or databases.
The core idea of DDD is simple:
👉 Build software that reflects how the business actually works.
Introduced by Eric Evans, DDD is especially powerful for:
Instead of starting with frameworks or database tables, DDD starts with:
Domain-Driven Design is a way of designing software by deeply understanding the business domain and translating that understanding directly into code.
The goal is not just working software, but software that:

In large systems, most challenges are domain-related, not technical:
DDD addresses these challenges by ensuring:
DDD is built on three fundamental principles.

At the heart of DDD is the business domain—the real-world problem your software is designed to solve.
Instead of starting with technical concerns like databases or frameworks, DDD begins by deeply understanding the business itself.
Example – E-commerce Domain
In DDD, these are treated as core business concepts, not just database tables or API endpoints.
DDD emphasizes a shared and consistent language, known as Ubiquitous Language, used by everyone involved in the project:
This language appears everywhere:
Example Terms
📌 If a term doesn’t exist in the business, it usually doesn’t belong in the domain model.
A Bounded Context defines a clear boundary within which a specific domain model applies.
Example
📌 The same word can have different meanings in different contexts — and that’s valid.
Domain-Driven Design is built using a set of core building blocks that help model real-world business behavior accurately in code. These building blocks define how business concepts are represented, how data consistency is maintained, and how logic is organized.
Entities are objects that have a distinct identity that remains the same over time, even if their attributes change.
public class Customer {
private Long id;
private String name;
private String email;
}
Value Objects represent descriptive aspects of the domain and do not have an identity.
public class Address {
private final String street;
private final String city;
private final String zipCode;
}
✔ Common examples: Money, Address, DateRange
An Aggregate is a cluster of related entities and value objects treated as a single unit of consistency.
Example – Order Aggregate

Repositories provide access to aggregates while hiding persistence details from the domain layer.
public interface OrderRepository {
Order save(Order order);
Optional<Order> findById(Long id);
}
The domain layer never directly depends on database APIs like JPA, SQL, or MongoDB.
Services are used when business logic does not naturally belong to an entity or value object.
Types of Services
public class PaymentService {
public PaymentResult processPayment(Order order) {
return PaymentResult.success();
}
}
Services should be stateless and expressed in business language.
Domain Events represent something important that happened in the business.
public class OrderPlacedEvent {
private final Long orderId;
private final LocalDateTime createdAt;
}
Why Domain Events Matter
Factories handle complex object creation logic and ensure objects are always created in a valid state.
Why Use Factories
✔ Especially useful for aggregates with many invariants or creation rules.
| Layer | Purpose | What It Contains | Key Rules |
|---|---|---|---|
| Domain Layer | Core business logic and rules | Entities, Value Objects, Aggregates, Domain Services, Domain Events, Repository interfaces | Must be independent of frameworks and other layers |
| Application Layer | Orchestrates use cases and workflows | Application Services, Use Case Handlers, Commands, Transactions | Contains no business rules |
| Infrastructure Layer | Technical implementation details | Database access (JPA/JDBC), Messaging, External APIs, Repository implementations | Depends on Domain layer, never the reverse |
| Presentation Layer | Handles user interaction | REST Controllers, GraphQL APIs, UI components | Must stay thin and delegate to Application layer |

| DDD Layer | Role in DDD | How It Maps to Microservices | Example in a Microservice |
|---|---|---|---|
| Domain Layer | Contains core business rules and domain logic | Represents the business capability of the microservice | Order entity, Order aggregate, OrderPlacedEvent |
| Application Layer | Orchestrates use cases and workflows | Acts as the service use case coordinator | PlaceOrderUseCase, CheckoutService |
| Infrastructure Layer | Handles technical concerns | Provides database, messaging, and integrations | JPA repositories, Kafka producers, REST clients |
| Presentation Layer | Handles input and output | Exposes the service API | REST controllers, GraphQL resolvers |
Domain-Driven Design (DDD) aligns perfectly with microservices architecture because both focus on modeling software around business capabilities rather than technical layers. DDD helps define what a microservice should do, while microservices define how it runs and scales independently.
Mapping DDD Concepts to Microservices
| DDD Concept | Microservices Mapping |
|---|---|
| Domain | Represents a business capability handled by a microservice |
| Bounded Context | Each bounded context maps to one microservice, ensuring clear boundaries |
| Aggregate | Defines a consistency boundary within a microservice |
| Domain Event | Facilitates communication between services without tight coupling |
| Repository | Provides service-owned persistence, abstracting the database layer |
Each microservice:
Domain-Driven Design (DDD) turns technical workflows into business-readable processes, making systems easier to understand, maintain, and scale.

Without DDD (Technical Thinking)
OrderService.processOrder();
PaymentService.pay();
InventoryService.update();
With DDD (Business Thinking)
order.place();
payment.authorize();
inventory.reserve();
The Order Aggregate models an order as a business concept, ensuring consistency and proper encapsulation.
@Entity
public class Order {
@Id
private Long id;
private Long customerId;
@OneToMany(cascade = CascadeType.ALL)
private List<OrderLine> items = new ArrayList<>();
private LocalDateTime createdAt;
public void addItem(Long productId, int quantity) {
items.add(new OrderLine(productId, quantity));
}
}
public class OrderPlacedEvent {
private final Long orderId;
private final LocalDateTime orderTime;
}
publicclassOrderService {
privatefinal OrderRepository repository;
publicvoidplaceOrder(Order order) {
repository.save(order);
publishEvent(newOrderPlacedEvent(order.getId(), LocalDateTime.now()));
}
}
Use DDD When:
Avoid Heavy DDD When:
Domain-Driven Design (DDD) is not about tools or frameworks — it is about thinking in business terms.
DDD helps teams:
👉 If microservices define how you build systems, DDD defines what you build them around.