Skip to content

Return Types by Layer: Entities In, DTOs Out

  • The domain and infrastructure layers return domain objects:
    Entities or Projections — never application DTOs.
  • DTO shaping/massaging happens only in the Application layer.
  • Specifically, transformation into response DTOs happens inside a Responder that lives with the Action that owns the request.

LayerAllowed to ReturnForbidden to Return
ApplicationResponse DTOs, API resultsDomain entities directly, raw DB results
DomainEntities, value objects, domain results, command output shapesDTOs, controller-bound types, transport shapes
InfrastructureEntities, query projections, persistence modelsDTOs, request/response types, view models

  • ActionResponder objects exist to translate domain → response DTO
  • These responders are:
    • Transport-aware
    • Swagger-attached
    • Allowed to evolve without domain impact
    • Colocated with the action, not shared

This keeps:

  • domain code framework-agnostic
  • repositories pure data access
  • transaction scripts type owners of their inputs
  • responders owners of DTO output concerns

It also prevents:

  • circular dependencies
  • global types.ts junk drawers
  • accidental coupling to transport models

  • If a query shape is specialized for a use case → return a Projection
  • If a response shape is for API/UI → return a DTO from the responder
  • If a domain object shape changes → the DTO changes, but only at the boundary that consumes it

Entities and projections flow inward. DTOs only flow outward, and only from responders.