Version v1.0 · dotnet
Scheduling & Cron
How recurring scheduling works, including supported 5-field and 6-field cron formats.
Scheduling & Cron
DurableStack recurring scheduling is cron-driven.
Each recurring job stores its schedule definition, and the scheduler materializes due runs into the run queue.
How scheduling works
At runtime:
- Recurring job definitions are initialized/upserted at startup.
- Scheduler checks for due recurring jobs.
- For each due job, DurableStack enqueues a run and computes the next occurrence.
- Catch-up behavior is controlled by
options.Recurring.CatchUpPolicy.
The same job can still be manually enqueued through IDurableStackClient.
Supported cron formats
DurableStack supports both:
- 5-field cron:
minute hour day-of-month month day-of-week - 6-field cron:
second minute hour day-of-month month day-of-week
Examples:
- 5-field:
*/5 * * * * - 6-field:
*/20 * * * * *
Any other field count is invalid.
Common examples
- Every minute:
* * * * * - Every 5 minutes:
*/5 * * * * - Every hour at minute 0:
0 * * * * - Every day at 02:00:
0 2 * * * - Weekdays at 08:30:
30 8 * * 1-5 - First day of month at midnight:
0 0 1 * * - Every 20 seconds (6-field):
*/20 * * * * *
Attribute examples
using DurableStack.Core.Abstractions;
using DurableStack.Hosting.DependencyInjection;
[DurableJob(Name = "report-hourly")]
[RecurringJob("0 * * * *", TimeZone = "UTC")]
public sealed class HourlyReportJob : IDurableJob
{
public Task ExecuteAsync(JobContext context, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
[DurableJob(Name = "heartbeat-every-20-seconds")]
[RecurringJob("*/20 * * * * *", TimeZone = "UTC")]
public sealed class SubMinuteHeartbeatJob : IDurableJob
{
public Task ExecuteAsync(JobContext context, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
Catch-up policy interaction
SkipMissed(default): jumps to the next future slot after downtime.CatchUp: materializes missed slots incrementally until current time.
Use SkipMissed for most production workloads unless strict missed-slot replay is required.
Time zones
Cron expressions are evaluated in the RecurringJob(TimeZone = "...") IANA zone.
- Default zone is
UTC. - Windows time zone IDs are not supported.
For more detail, see Time Zones.
Practical guidance
- Prefer 5-field cron for normal business schedules.
- Use 6-field cron only when sub-minute cadence is truly required.
- Keep
AllowConcurrentRuns = falseunless overlap is intentional. - Validate cron expressions in tests for critical schedules.