Process Managers
What is a Process Manager?
A process manager orchestrates a multi-step workflow that spans multiple events over time. Unlike a policy, which reacts to a single event, a process manager tracks state across a sequence of events, coordinating actions until the workflow completes, times out, or fails.
Process manager handlers are invoked asynchronously by the event dispatcher, not inline with the command that emitted the triggering event.
Process Managers in Bounda
Process managers live inside domain/<aggregate>/processes/<process-name>/ as a folder containing a configuration file and individual event handler files.
domain/
order/
processes/
order-lifecycle/
index.ts
on-order-placed.ts
on-payment-received.ts
on-order-fulfilled.ts
on-order-lifecycle-timed-out.ts
Configuration
The index.ts file exports a config function that defines when the process starts, when it completes, and an optional timeout:
import type { ProcessManager } from "./+types/order-lifecycle";
export const config: ProcessManager.ConfigFunction = ({ events }) => ({
startedBy: [events.OrderPlaced],
completedBy: [events.OrderFulfilled],
timeout: "7d",
});
Configuration Options
| Option | Description |
|---|---|
startedBy | Array of event types that create a new process instance |
completedBy | Array of event types that mark the process as complete |
timeout | Duration after which the process is considered timed out (e.g., "7d", "24h") |
Event Handlers
Each event the process reacts to gets its own file named on-<event-name>.ts. The handler receives the event and a commands object for dispatching further actions:
import type { ProcessManager } from "./+types/on-order-placed";
export async function handler({ event, commands }: ProcessManager.HandlerArgs) {
await commands.sendWelcomeEmail({
aggregateId: event.aggregateId,
delay: "1m",
});
}
Handlers can dispatch commands immediately or with a delay using the delay property. See Scheduled Commands for supported delay formats.
Special Event Handlers
Process managers support two special handler files for lifecycle edge cases:
Timeout Handler
When a process exceeds its configured timeout, Bounda triggers the timeout handler:
import type { ProcessManager } from "./+types/on-order-lifecycle-timed-out";
export async function handler({ event, commands }: ProcessManager.HandlerArgs) {
await commands.cancelOrder({
aggregateId: event.aggregateId,
});
}
The file is named on-<process-name>-timed-out.ts.
Failure Handler
When a step in the process fails after exhausting retries, the failure handler is triggered:
import type { ProcessManager } from "./+types/on-order-lifecycle-failed";
export async function handler({ event, commands }: ProcessManager.HandlerArgs) {
await commands.flagForManualReview({
aggregateId: event.aggregateId,
});
}
The file is named on-<process-name>-failed.ts.
Process State
Bounda tracks process manager instances internally. Each instance records:
| Field | Description |
|---|---|
processId | Unique identifier for the process instance |
status | Current status: started, completed, timed_out, failed |
startedAt | Timestamp when the process was initiated |
aggregateId | The aggregate instance this process is associated with |
Dead Letter Queue
Like policies, process managers support DLQ configuration for handlers that fail after retrying:
processes: {
retry: {
retryStrategy: "exponential",
maxRetries: 3,
},
dlq: {
type: "sqlite",
path: "./db/processes-dlq.db",
},
}
Guidelines
- Use process managers when a workflow involves waiting for multiple events across time. For single event reactions, prefer policies.
- Always define a timeout. Processes that never complete consume resources and obscure system state.
- Include both timeout and failure handlers to ensure the system can recover gracefully from edge cases.
- Process managers should coordinate, not compute. Keep business logic in commands and let the process manager orchestrate the sequence.
Related Concepts
- Policies — for single-event reactions without state tracking
- Scheduled Commands — delaying command execution from process handlers
- Commands — process handlers dispatch commands to perform actions
- Eventual Consistency — how and when process manager handlers execute