Repository navigation
Scheduling
Stateflows core supports declarative scheduling through TimeEvent types. A State Machine or Activity declares a timed event in its model; Stateflows registers it when the source state or accepting node becomes active and removes it when that source is no longer active. Core scheduling is tied to model elements and TimeEvent derivatives, not a general API for imperatively scheduling arbitrary event payloads.
The hosting runtime monitors pending trigger times and delivers events when they are due. For example, the Orleans runtime uses Orleans reminders to wake scheduled Behaviors.
All built-in time events are in Stateflows.Common. The types in the Delay and Interval folders can be used in State Machine transitions or Activity event-accepting nodes; this shared catalog is not specific to either behavior model.
DelayEvent types fire once. IntervalEvent derives from RecurringEvent; these timers are registered again after delivery while their source state or accepting node remains active. Event times are UTC. Daily and weekly events use UTC calendar boundaries, not the host's local time zone.
| Event | Schedule |
|---|---|
AfterOneMinute |
Next UTC minute boundary. |
AfterFiveMinutes |
Next five-minute UTC boundary. |
AfterTenMinutes |
Next ten-minute UTC boundary. |
AfterFifteenMinutes |
Next fifteen-minute UTC boundary. |
AfterThirtyMinutes |
Next half-hour UTC boundary. |
AfterOneHour |
Next UTC hour boundary; subclasses can override Hours to change the hour count. |
AfterTwelveHours |
Next UTC 00:00 or 12:00 boundary. |
AfterOneDay |
Next UTC midnight. |
AfterOneWeek |
Seven days after a calculated UTC weekday boundary; subclasses can override the weekday. This is normally the following named weekday, but activation on Sunday with the default Monday can skip to the Monday after next. |
AfterOneMonth |
Implementation caveat: currently calculates the first day of the current month at 00:00 UTC, not one month later. |
The minute and hour types round the delay start down to their applicable boundary before adding the interval. AfterOneDay rounds down to midnight and adds one day, so it expires at the next midnight rather than 24 hours after registration. AfterOneWeek is calendar-week based rather than exactly seven days from the activation time.
| Event | Schedule |
|---|---|
EveryOneMinute |
At each UTC minute boundary. |
EveryFiveMinutes |
At each five-minute boundary. |
EveryTenMinutes |
At each ten-minute boundary. |
EveryFifteenMinutes |
At each fifteen-minute boundary. |
EveryThirtyMinutes |
At each half-hour boundary. |
EveryOneHour |
At each UTC hour boundary. |
EveryTwelveHours |
Every twelve hours from the current UTC hour boundary. |
EveryOneDay |
Daily at 00:00 UTC by default; subclasses can choose a time of day. |
EveryOneWeek |
Weekly at 00:00 UTC on Monday; subclasses can choose another weekday. |
EveryOneMonth |
Implementation caveat: currently calculates the first day of the current month at 00:00 UTC, not the next month. |
EveryMonday, EveryTuesday, EveryWednesday, EveryThursday, EveryFriday, EverySaturday, EverySunday
|
Weekly at 00:00 UTC on the named weekday. |
AtEveryMidnight |
Daily at 00:00 UTC. |
AtEveryNoon |
Daily at 12:00 UTC. |
AtEvery3AM, AtEvery6AM, AtEvery9AM
|
Daily at the named UTC clock time. |
AtEvery12AM |
Implementation caveat: currently calculates 12:00 UTC (noon), not midnight. |
AtEvery3PM, AtEvery6PM, AtEvery9PM
|
Daily at the named UTC clock time. |
AtEvery12PM |
Implementation caveat: currently calculates 00:00 UTC (midnight), not noon. |
AfterOneMonth and EveryOneMonth call DateTime.AddMonths(1) without using its returned value. Because DateTime is immutable, both currently resolve to the first day of the current month rather than the next month; since that time is usually already past when activated, the timer can become immediately due. Do not rely on these two built-ins for monthly timing until corrected; use a custom event or the Scheduling extension instead.
Use a TimeEvent derivative as a transition trigger. The trigger is registered while its source state is active and cleared when that state is exited or the transition consumes it. Any predefined type above can be used as the trigger.
using Stateflows.Common;
public sealed class PaymentTimeout : TimeEvent
{
protected override DateTime GetTriggerTime(DateTime startedAt)
=> startedAt.AddMinutes(15);
}In a State Machine definition:
.AddState("AwaitingPayment", state => state
.AddTransition<PaymentTimeout>("Expired")
)Recurring triggers are registered again while the source state remains active; one-shot delay events are consumed once. See Transitions.
Activities can accept a TimeEvent derivative with AddAcceptEventAction<TEvent>, or represent it explicitly with AddTimeEventAction<TTimeEvent>. The timer is registered while the accepting node is active and cleared when that node is deactivated. The same predefined types listed above are available here.
.AddAcceptEventAction<PaymentTimeout>(
async c => await payments.ExpireAsync(orderId, c.CancellationToken),
node => node.AddControlFlow<FinalNode>())Use AddTimeEventAction<TTimeEvent> when the Activity should contain a time-event action node:
.AddTimeEventAction<PaymentTimeout>(
async c => await payments.ExpireAsync(orderId, c.CancellationToken),
node => node.AddControlFlow<FinalNode>())A recurring timer can be re-registered after delivery while the eligible accepting node remains active; otherwise it is a one-time registration. See Accept Event Action Node and Time Event Action Node.
For imperative scheduling of arbitrary event payloads without declaring a timed model element, use the separate Scheduling extension.
Home page Support Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0. © by Mikołaj Milewski, 2026
Overview
Installation
Runtimes
Orleans runtime
Concepts
Events and Structural Events
Messaging Patterns
Validation
Scheduling
Observability
Behaviors
Behavior Values
Dependency Injection
Behavioral Groups
State Machines
Concepts
State Identity
In-State Event Deferrals
Evaluation of Transitions
Exception Handling
Building blocks
Regions
States
State
Composite State
Orthogonal State
Final State
Pseudostates
Choice
Junction
Fork
Join
History
Transitions
Transition
Default Transition
Internal Transition
Activities
Concepts
Exception Handling
Implicit Fork and Join
Tokens
Building blocks
Nodes
Action Node
Decision Node
Merge Node
Initial Node
Final Node
Input Node
Output Node
Fork Node
Join Node
Accept Event Action Node
Send Event Action Node
Publish Event Action Node
Time Event Action Node
Data Store Node
Structured Activity Node
Iterative Activity Node
Parallel Activity Node
Flows
Data Flow
Control Flow
Actions
Entities
Fields
Mutations
Projections
Extensions
ClearScript
FluentValidation
JSON definitions
Minimal APIs
OneOf
OpenTelemetry
PlantUML
Scheduling