Java Omnibus
OOAD & Architecture / Domain-Driven Design / Domain Services
DDD Domain Services Modeling Java
Tactical DDD

Domain services are useful when important domain behavior does not belong naturally to one entity or value object.

DDD encourages rich domain objects, but not every business rule fits neatly inside one entity. Some rules span multiple concepts or need domain logic that is still not just application orchestration. Domain services exist for those cases.

Why This Topic Matters

Why it matters in real Java systems

Fraud scoring, cross-order eligibility checks, or shipment promise calculations may involve multiple domain concepts. Putting that logic in a controller is wrong. Putting it arbitrarily inside one entity may also be wrong. Domain services create a legitimate home for such behavior.

Core Explanation

The main design idea

A domain service expresses domain logic that does not sit naturally on one entity or value object. It should still use domain language and remain focused on business rules, not technical orchestration. That distinction is what separates it from an application service.

If a service mostly coordinates repositories, gateways, transactions, and notifications, it is probably an application service. If it mainly expresses business policy spanning several domain concepts, it may be a domain service.

Concept Breakdown

Key ideas to keep in mind

Concept

Good fit

Business logic spanning multiple domain objects without a natural single owner.

Concept

Bad fit

Workflow coordination and infrastructure access that belong in the application layer.

Concept

Main discipline

Keep the service in domain language, not framework or orchestration language.

Decision hint

Decision hint

Ask this: is the logic mainly about business meaning, or mainly about coordinating a use case? If it is about meaning, a domain service may fit. If it is about coordination, it is likely an application service.
Java Example

Java example in the Order Management domain

Java example: a domain service for shipment promise calculation
package org.javaomnibus.ecommerce.domain;

public final class ShipmentPromiseService {
    public ShipmentPromise calculate(Order order, InventorySnapshot inventorySnapshot) {
        if (inventorySnapshot.isAvailable(order)) {
            return ShipmentPromise.standard();
        }
        return ShipmentPromise.delayed();
    }
}
Code Walkthrough

Step by step

  1. The logic is business-oriented and expressed in domain terms.
  2. It spans multiple concepts but does not look like workflow orchestration.
  3. That makes a domain service a reasonable home.
  4. The difference from an application service is one of responsibility, not just naming.
Real-World Usage

Where this helps in practice

  • Policy calculations spanning multiple aggregates or domain concepts
  • Rules that do not belong to controllers or application orchestration
  • Keeping rich domain logic out of generic helper classes
Trade-Offs

Trade-offs and when to be careful

  • Domain services are useful, but they can become dumping grounds if the team avoids hard modeling decisions.
  • Too many domain services may indicate the entities are too weak or the boundaries are unclear.
Common Mistakes

Frequent mistakes to watch for

  • Putting application orchestration into a class called a domain service
  • Using domain services as a default home for all business logic
  • Keeping the service full of infrastructure calls and framework concerns
  • Ignoring the possibility that a value object or aggregate should own the rule instead
Related Pages

Related concepts


What To Read Next