This tutorial builds a saga orchestrator in NestJS from scratch — covering module structure, persistence with TypeORM, step execution with dependency injection, compensation handling, and a REST API for triggering and monitoring sagas. NestJS's module system and DI container make it a natural fit for structuring saga step implementations as injectable services.
Project Setup
Step 1: Database Entities
Define the saga state and step records as TypeORM entities.
Step 2: Saga Step Interface
Step 3: Saga Store Service
Step 4: Saga Orchestrator Service
Step 5: Order Saga Implementation
Create concrete step implementations as NestJS injectable services.
Need a second opinion on your system design architecture?
I run free 30-minute strategy calls for engineering teams tackling this exact problem.
Book a Free CallStep 6: Order Saga Service
Wire the steps together into a saga definition.
Step 7: Controller
Step 8: Module Configuration
Step 9: Monitoring Endpoint
Step 10: Testing
Conclusion
NestJS's dependency injection system maps naturally to saga step implementations. Each step is an injectable service with its own dependencies (inventory service, payment service, shipping service), and the DI container wires everything together at module composition time. This gives you testable steps with mock injection, clean separation of saga orchestration from business logic, and the ability to share services across multiple saga definitions.
The TypeORM entity with @VersionColumn provides optimistic locking for saga state updates without custom SQL. The orchestrator saves state after every step completion, enabling crash recovery by resuming from the last persisted step. Combined with idempotent step implementations, this makes the saga resilient to orchestrator restarts.
For production deployments, add a health check endpoint that queries for stale sagas (running status with updatedAt older than the maximum expected saga duration) and integrate with NestJS's built-in logger for structured log output. The monitoring controller provides the operational visibility needed to diagnose stuck or failed sagas without database access.