---
title: WorkflowModule
description: NestJS module that builds workflow bundles and registers the workflow controller.
docs_index: /llms.txt
lastUpdated: 2026-10-20
type: reference
summary: Import WorkflowModule.forRoot() in your AppModule to enable workflows in a NestJS app.
prerequisites:
  - /docs/getting-started/nestjs
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

NestJS module that provides workflow functionality. It builds the workflow bundles on module initialization (`onModuleInit`) and registers the [`WorkflowController`](/docs/api-reference/workflow-nest/workflow-controller) that serves the workflow runtime routes.

## Usage

Add `WorkflowModule.forRoot()` to the `imports` array of your root module.

```typescript title="src/app.module.ts" lineNumbers
import { Module } from "@nestjs/common";
import { WorkflowModule } from "workflow/nest"; // [!code highlight]

@Module({
  imports: [WorkflowModule.forRoot()], // [!code highlight]
})
export class AppModule {}
```

If your NestJS project compiles to CommonJS via SWC, pass `moduleType` and `distDir` so the builder can rewrite imports in the generated bundles:

```typescript title="src/app.module.ts" lineNumbers
import { Module } from "@nestjs/common";
import { WorkflowModule } from "workflow/nest";

@Module({
  imports: [
    WorkflowModule.forRoot({
      moduleType: "commonjs", // [!code highlight]
      distDir: "dist", // [!code highlight]
    }),
  ],
})
export class AppModule {}
```

## API signature

### Static methods

#### `forRoot(options?)`

Configures the module and returns a NestJS `DynamicModule` registered as `global`. It provides the resolved options under the `WORKFLOW_MODULE_OPTIONS` token, and (unless `skipBuild` is set) creates a [`NestLocalBuilder`](/docs/api-reference/workflow-nest/nest-local-builder) that builds the workflow bundles when the module initializes.

#### `forRootAsync(options)`

Same as `forRoot`, with the options produced by a factory so they can come from other providers.

```typescript title="src/app.module.ts" lineNumbers
WorkflowModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    basePath: config.get("API_PREFIX"),
  }),
});
```

| Parameter    | Type                                                                   | Description                                                     |
| ------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------- |
| `imports`    | `unknown[]`                                                            | Optional. Modules whose exported providers the factory injects. |
| `inject`     | `unknown[]`                                                            | Optional. Providers passed to `useFactory`, in order.           |
| `useFactory` | `(...args) => WorkflowModuleOptions \| Promise<WorkflowModuleOptions>` | Returns the module options.                                     |

### Parameters

| Parameter | Type                    | Description                              |
| --------- | ----------------------- | ---------------------------------------- |
| `options` | `WorkflowModuleOptions` | Optional. Configures the workflow build. |

#### WorkflowModuleOptions

Extends [`NestBuilderOptions`](/docs/api-reference/workflow-nest/nest-local-builder#nestbuilderoptions): all builder options are accepted, plus `skipBuild`:

| Option                 | Type                                                      | Default                                         | Description                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------------- | --------------------------------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `skipBuild`            | `boolean`                                                 | `true` when `VERCEL` is set, else `false`       | Skip building workflow bundles on startup. The bundles must already exist; startup fails with an explicit error if they do not.                                                                                                                                                                                                                                                                                |
| `basePath`             | `string`                                                  | adopted from `app.setGlobalPrefix()`            | Route prefix the workflow endpoints are served under, applied to generated callback and webhook URLs. Set it when a reverse proxy mounts the app on a sub-path NestJS cannot see.                                                                                                                                                                                                                              |
| `manageWorldLifecycle` | `boolean`                                                 | `false`                                         | Start the target World's background workers with the app and close them on shutdown. Required for self-hosted Worlds, which otherwise never pick up runs.                                                                                                                                                                                                                                                      |
| `preloadBundles`       | `boolean`                                                 | `false` when `VERCEL` is set, else `true`       | Load the generated bundles during startup instead of on the first request. On Vercel, dedicated functions serve the bundles, so there is nothing to preload.                                                                                                                                                                                                                                                   |
| `bypassBodyParser`     | `boolean`                                                 | `true`                                          | Keep the application's body parsers away from `.well-known/workflow/v1`, so queue deliveries are not rejected by Express's 100 KB limit and signed webhook bodies stay byte-exact. The application's own routes are untouched. On Fastify, where the body limit is enforced per instance rather than per route, nothing is patched and a limit low enough to reject deliveries is reported at startup instead. |
| `workingDir`           | `string`                                                  | `process.cwd()`                                 | Working directory for the NestJS application.                                                                                                                                                                                                                                                                                                                                                                  |
| `dirs`                 | `string[]`                                                | `['src']`                                       | Directories to scan for workflow files.                                                                                                                                                                                                                                                                                                                                                                        |
| `outDir`               | `string`                                                  | `'.nestjs/workflow'` (relative to `workingDir`) | Output directory for generated workflow bundles.                                                                                                                                                                                                                                                                                                                                                               |
| `watch`                | `boolean`                                                 | `false`                                         | Deprecated and ignored. Watch mode is not implemented for this builder. Use `nest start --watch`, which re-runs the startup build.                                                                                                                                                                                                                                                                             |
| `moduleType`           | `'es6' \| 'commonjs'`                                     | `'es6'`                                         | SWC module compilation type. Set to `'commonjs'` if your NestJS project compiles to CommonJS (CJS) through SWC.                                                                                                                                                                                                                                                                                                |
| `distDir`              | `string`                                                  | `'dist'`                                        | Directory where NestJS compiles `.ts` source files to `.js` (relative to `workingDir`). Used when `moduleType` is `'commonjs'`. Should match the `outDir` in your `tsconfig.json`.                                                                                                                                                                                                                             |
| `sourcemap`            | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` (dev) / `false` (prod)               | Controls source maps on generated workflow bundles. Defaults to `'inline'` in development and `false` in production. Can also be set via the `WORKFLOW_SOURCEMAP` environment variable.                                                                                                                                                                                                                        |

### Returns

`forRoot()` and `forRootAsync()` return a `DynamicModule` to include in the `imports` array of your root module.

## Injecting the resolved options

Both factories export the resolved options under `WORKFLOW_MODULE_OPTIONS`:

```typescript title="src/some.service.ts" lineNumbers
import { Inject, Injectable } from "@nestjs/common";
import {
  WORKFLOW_MODULE_OPTIONS,
  type WorkflowModuleOptions,
} from "workflow/nest";

@Injectable()
export class SomeService {
  constructor(
    @Inject(WORKFLOW_MODULE_OPTIONS)
    private readonly options: WorkflowModuleOptions
  ) {}
}
```

The older `WORKFLOW_OPTIONS` token resolves to the same value and is kept for compatibility.

## Lifecycle

| Hook                    | Behaviour                                                                                                                                                                                                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `onModuleInit`          | Takes the application's body parsers off the workflow routes (unless `bypassBodyParser` is `false`), reconciles the base path against `app.setGlobalPrefix()`, builds the bundles (or verifies they exist when `skipBuild` is set), optionally starts the World, and preloads the bundles. |
| `onApplicationShutdown` | Closes the World when `manageWorldLifecycle` is set. Call `app.enableShutdownHooks()` so this runs on a signal.                                                                                                                                                                            |

> `WorkflowModule` reads NestJS's global prefix and HTTP adapter through the
> injector, which only works while a single copy of `@nestjs/core` is installed.
> With two copies the injection tokens differ, prefix handling and the
> body-parser bypass both stop working, and a warning is logged at startup.

> Workflows and steps run outside the NestJS injector, so providers cannot be injected into `"use workflow"` or `"use step"` code. See [NestJS dependency injection is not available in workflows and steps](/docs/getting-started/nestjs#nestjs-dependency-injection-is-not-available-in-workflows-and-steps).

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)