DEV Community

Jose Escrich
Jose Escrich

Posted on

Orchestrating Complex Processes in Node.js with @jescrich/nestjs-workflow

Modern backend systems are no longer simple request/response pipelines.
They orchestrate payments, onboarding, document validation, long-running tasks, integrations with external vendors, and multi-step processes that must never end in partial failure.

And yet… most Node.js applications still try to manage this complexity with:

giant service classes

boolean flags in the database

magic strings like "pending" | "processing" | "done"

ad-hoc Saga implementations

hand-rolled state machines

That’s why I built nestjs-workflow — a lightweight, declarative workflow engine for NestJS that helps you structure multi-step business processes with clarity, resiliency, and observability.

🚀 Why nestjs-workflow?

Because every real system eventually needs workflows.

When you’re building microservices, event-driven systems, or anything that depends on external APIs, you need:

State transitions (from “received” → “validated” → “processed” → “completed”)

Retries & compensation when external calls fail

Idempotency

Persistence of state

Visibility into where the process is stuck

In enterprise systems (fintech, ecommerce, LOS/OMS integrations, KYC flows, etc.), this becomes even more important.

nestjs-workflow gives you all of that without turning your project into a distributed-systems PhD.

🧩 A Declarative Workflow, Not a Mess

Here’s what a workflow looks like with the library:

@Workflow()
export class OnboardingWorkflow extends WorkflowBase {
definition = {
id: 'onboarding',
initial: 'received',
states: {
received: {
on: {
VALIDATE: 'validating',
},
},
validating: {
invoke: async (ctx) => this.validateUser(ctx),
on: {
SUCCESS: 'completed',
FAILURE: 'failed',
},
},
failed: {},
completed: {},
},
};
}

Clean. Explicit. Testable.
Your workflow logic is the source of truth, not scattered across your services.

🔌 Plugged Into NestJS the Right Way

nestjs-workflow integrates seamlessly:

✔️ Providers & Dependency Injection

Inject services, repositories, and external clients directly into your workflow.

✔️ Persistence Layer

Use memory, Redis, SQL, or your own implementation.

✔️ Event Emitters

React to workflow transitions, notify other services, or publish Kafka messages.

✔️ Hooks for Observability

Perfect for platforms like Datadog, New Relic, or WHAWIT.

⚙️ Real-World Example: A Payment Flow
await this.workflowService.send('payment', orderId, 'AUTHORIZE');

Behind the scenes:

State moves from created → authorizing

The workflow calls an external PSP

If it fails, retries happen

If it still fails, compensation logic runs

Workflow transitions to failed

Your system stays consistent

This is the power of structured orchestration.

🏢 Designed From Real Enterprise Problems

I originally built this library after hitting the same issues repeatedly while building:

event-driven ecommerce platforms

financial onboarding pipelines

data ingestion engines

vendor adapter layers

long-lived loan origination flows (LOS)

background processors for Kafka/Flink

Node.js needed something opinionated but flexible — a workflow engine that Team Leads and Architects could adopt without a massive learning curve.

nestjs-workflow is intentionally simple, predictable, and battle-tested in production environments.

📦 Explore the Examples

If you want to see real, runnable use cases, check the examples repo:

👉 https://github.com/jescrich/nestjs-workflow

👉 (Examples moved here) https://github.com/jescrich/nestjs-workflow

You’ll find:

Saga examples

E2E workflows

External service orchestration

Error-handling patterns

Kafka + workflow patterns

Complex state machines with branching logic

🎯 Final Thoughts

If your NestJS application has:

business processes with multiple steps

integrations that may fail or require retries

state transitions

workflows that need transparency

or just too much chaos in service layers…

…then you’ll benefit from nestjs-workflow.

It gives teams a clean, maintainable way to orchestrate complexity, brings structure to long-running processes, and avoids the hidden traps of “just manually coding it.”

If you build something with it, tag me — I’m always curious to see how others push workflow engines to new places.

Top comments (0)