Skip to main content

Service layer pattern

Business logic and orchestration: how we keep controllers thin and centralize domain behavior.

Overview

The service layer holds business logic and coordinates data access. Controllers (see stack controller-layer) delegate to services; services inject and use the repository-layer for persistence and use shared types/serialization for responses.

Backend

  • Technology: NestJS injectable services (see stack rule framework). Services are registered in modules and injected where needed.
  • Responsibilities: Validate and orchestrate use cases; call the repository layer for data; transform results (e.g. with plainToInstance from shared DTOs) before returning to controllers. Configuration (e.g. AppConfigService) is injected in services when needed at runtime.
  • Integration: Uses repository-layer (Prisma Client) for data access. Uses pattern serialization (class-transformer) to map ORM results to shared DTOs. Other modules (e.g. mailing) inject their services into the service layer for cross-cutting behavior (e.g. sending email).

Implementation

The boilerplate uses standard NestJS providers: each feature module exposes one or more services that controllers inject. Services inject PrismaService (or the repository abstraction) and optionally AppConfigService, MailingService, etc. They return domain data or DTOs; the response interceptor (see pattern responses) wraps success responses. No separate “application service” vs “domain service” split unless a project introduces it.

References

  • Stack: framework (NestJS), controller-layer (caller), configuration (AppConfigService in services).
  • Pattern: repository-layer (data access), serialization (transforming results).