About serverpod-scheduling
A Serverpod skill for scheduling database-backed calls to run later or at a specified UTC time. It covers generated, type-safe scheduling and configuration for execution across a cluster.
Key features
- 01Delayed and scheduled-time calls
- 02Database-backed persistence across restarts
- 03Cluster-wide single execution claims
- 04Generated type-safe API
- 05Execution and concurrency settings
Use cases
- 01Run work after a delay
- 02Schedule work for a UTC time
- 03Keep scheduled tasks through restarts
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ serverpod/ serverpod --skill serverpod-schedulingAfter installing, type/serverpod-schedulingin Claude Code to confirm it loaded.
Details
From the project READMEServerpod Scheduling (Future Calls)
Future calls run at a specified time, are stored in the database, and survive restarts. Each call is claimed for one execution across the cluster. Future calls require database support; execution is started by monolith/maintenance roles, not serverless role.
Defining a future call
class ExampleFutureCall extends FutureCall {
Future<void> doWork(Session session) async {
// Work here.
}
Future<void> doOtherWork(Session session, MyModel data) async {
// Work with data.
}
}
Run serverpod generate for the type-safe API on pod.futureCalls.
Supported parameter types
The same types as for endpoint methods, listed in Serverpod Endpoints.
Scheduling
// Delay
await pod.futureCalls
.callWithDelay(const Duration(hours: 1))
.example.doWork();
// At specific time (UTC)
await pod.futureCalls
.callAtTime(DateTime.utc(2026, 1, 1))
.example.doOtherWork(myModel);
// With identifier (for cancellation)
await pod.futureCalls
.callWithDelay(const Duration(hours: 1), identifier: 'my-job-id')
.example.doWork();
// Recurring task from `Duration` interval with an optional start time
await pod.futureCalls
.callRecurring()
.every(const Duration(hours: 1), start: DateTime.now())
.example.doWork();
// Recurring task from `cron` expression
await pod.futureCalls
.callRecurring()
.cron("0 * * * *")
.example.doWork();
await pod.futureCalls.cancel('my-job-id'); // Cancels all with that identifier
Handle failures inside the call and reschedule if the work must eventually succeed.
Configuration
futureCall:
enabled: true # SERVERPOD_FUTURE_CALL_ENABLED (default true)
executionEnabled: true # SERVERPOD_FUTURE_CALL_EXECUTION_ENABLED
concurrencyLimit: 5 # SERVERPOD_FUTURE_CALL_CONCURRENCY_LIMIT (default 1, <1 maps to unlimited and is not recommended)
scanInterval: 2000 # SERVERPOD_FUTURE_CALL_SCAN_INTERVAL (ms, default 5000)
futureCallExecutionEnabled: false only stops execution; calls can still be scheduled. futureCall.enabled: false disables future calls entirely: no future call manager is created and serverpod generate omits the pod.futureCalls getter. The value must match across all run-mode config files, or generation fails.
Keep future calls idempotent. A call should tolerate retries or restarts without duplicating irreversible side effects.