/ Docs

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:

FormatDescriptionExample
"<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,
}
OptionDescription
typeThe storage backend for scheduled commands (e.g., "sqlite")
pathFile path for the scheduler database
pollingIntervalMsHow often the scheduler checks for commands ready to execute

Note: The pollingIntervalMs value 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 pollingIntervalMs that 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.
  • Commands — any command can be scheduled with a delay
  • Policies — commonly schedule follow-up commands
  • Process Managers — use scheduled commands for delayed workflow steps