Scheduled Commands
What is a Scheduled Command?
A scheduled command is a command that is dispatched for execution after a specified delay rather than immediately. This enables time-based workflows such as sending reminders, applying timeouts, or deferring actions until a later point.
Scheduled Commands in Bounda
Any command can be scheduled by adding a delay property when dispatching it. No changes to the command definition are required — scheduling is a dispatch-time concern.
await commands.sendReminder({
aggregateId: event.aggregateId,
delay: "1s",
});
Delay Formats
The delay property accepts a string with a number followed by a time unit:
| Format | Description | Example |
|---|---|---|
"<n>s" | Seconds | "30s" |
"<n>m" | Minutes | "5m" |
"<n>h" | Hours | "1h" |
"<n>d" | Days | "7d" |
Scheduling Adapter Configuration
Scheduled commands require a scheduling adapter configured in bounda.config.ts:
scheduling: {
type: "sqlite",
path: "./db/scheduler.db",
pollingIntervalMs: 100,
}
| Option | Description |
|---|---|
type | The storage backend for scheduled commands (e.g., "sqlite") |
path | File path for the scheduler database |
pollingIntervalMs | How often the scheduler checks for commands ready to execute |
Note: The
pollingIntervalMsvalue controls the precision of scheduled execution. A lower value means commands execute closer to their target time but increases polling overhead.
Common Usage Patterns
From Policies
Policies frequently schedule follow-up commands after reacting to an event:
import type { Policy } from "./+types/send-reminder-on-order-placed";
export async function handler({ event, commands }: Policy.HandlerArgs) {
await commands.sendReminder({
aggregateId: event.aggregateId,
delay: "24h",
});
}
From Process Managers
Process manager handlers use scheduled commands to implement timeouts and delayed steps:
import type { ProcessManager } from "./+types/on-order-placed";
export async function handler({ event, commands }: ProcessManager.HandlerArgs) {
await commands.sendWelcomeEmail({
aggregateId: event.aggregateId,
delay: "1m",
});
}
From Command Handlers
Commands can schedule other commands as part of their execution:
export async function handler({ command, events, commands }: Command.HandlerArgs) {
await commands.checkPaymentStatus({
aggregateId: command.aggregateId,
delay: "1h",
});
return events.orderPlaced({ aggregateId: command.aggregateId, ...command.payload });
}
Guidelines
- Choose a
pollingIntervalMsthat balances precision against resource usage. For most applications, 100-1000ms is a reasonable range. - Scheduled commands are persisted in the scheduler database, so they survive application restarts.
- The delay is measured from the time of dispatch, not from the triggering event’s timestamp.
- Keep delay durations reasonable for your use case. Very short delays (under 1 second) may behave like immediate execution depending on polling interval.
Related Concepts
- Commands — any command can be scheduled with a delay
- Policies — commonly schedule follow-up commands
- Process Managers — use scheduled commands for delayed workflow steps