Event-driven NestJS State Machine
Business state management with zero dependencies, no vendor lock-in, no infrastructure constraints — just your entities and their transitions.
Why NestflowJS?
A modern workflow engine that gets out of your way and lets you focus on business logic
State Machine Engine
Define workflows with states, transitions, and events. Built-in support for final states, idle states, and failure handling.
Serverless Optimized
Built for AWS Lambda with automatic timeout handling, batch processing, and graceful shutdown. Minimal cold start overhead.
Durable Execution
Checkpoint and replay execution with the Durable Lambda Adapter. Survive timeouts and resume exactly where you left off.
Fully Type-Safe
Full TypeScript support with comprehensive type definitions. Catch workflow configuration errors at compile time, not runtime.
Tree-Shakable
Subpath exports ensure minimal bundle sizes. Import only what you need for faster cold starts in serverless environments.
Retry & Error Handling
Built-in retry with exponential backoff and jitter. Handle transient failures gracefully with configurable @WithRetry policies.
Define, Transit, Done
Define workflows with decorators, transit states with a clean type-safe API
import { Workflow, OnEvent, Entity, Payload } from 'nestflow-js/core';@Workflow({ name: 'OrderWorkflow', states: { finals: ['delivered', 'cancelled'], idles: ['pending_payment'], failed: 'cancelled', }, transitions: [ { event: 'PAYMENT_RECEIVED', from: ['pending_payment'], to: 'processing' }, { event: 'SHIP_ORDER', from: ['processing'], to: 'shipped' }, { event: 'CONFIRM_DELIVERY', from: ['shipped'], to: 'delivered' }, { event: 'CANCEL', from: ['pending_payment', 'processing'], to: 'cancelled' }, ], entityService: 'entity.order',})export class OrderWorkflow { @OnEvent('PAYMENT_RECEIVED') async onPayment(@Entity() order, @Payload() payload) { order.paidAt = new Date(); return order; }}import { OrchestratorService } from 'nestflow-js/core';@Injectable()export class OrderService { constructor(private orchestrator: OrchestratorService) {} async processPayment(orderId: string, payload: PaymentDto) { const result = await this.orchestrator.transit({ event: 'PAYMENT_RECEIVED', urn: orderId, payload, attempt: 0, }); // result.status: 'final' | 'idle' | 'continued' | 'no_transition' return result; }}