alarm(alarmInfo) handler. Alarms are the way to do deferred work without an external scheduler.
There is one alarm per actor instance, not per method or per key. Setting it again replaces the previous time.
Set and Handle
Delivery Contract
AlarmInfo:
- At-least-once delivery. Plan for the handler to run more than once for the same scheduled time. Make writes idempotent — re-check state in
storagebefore applying effects (as theSessionexample above does), or record a done-marker keyed by the scheduled time. - A failed run is redelivered 3 times, about a second apart. If the handler throws (or exceeds its time budget), the platform re-fires it with
retryCountincremented — 4 attempts total, then the alarm is deleted (getAlarm()returnsnull). There is no signal when that happens. - A failing handler loses its alarm — don’t use
throwas your retry mechanism. Three retries a second apart won’t outlast a real outage. If the deferred work must happen, make the handler tolerate its own errors: catch, record, and re-arm withsetAlarmat a backoff you choose. - Use
info.isRetryto branch. On retry, log it, treat the work as best-effort, or skip already-completed steps.
Patterns
TTL / expiry
Set the alarm when you create the row; on fire, check the row is still expired and delete it. If the row was touched since, reset the alarm instead.Retry backoff
If your method kicks off a flaky external call, set an alarm to retry later; on fire, attempt again and either succeed or set a new alarm with a longer backoff.Session timeout
SeeSession.touch above — every interaction pushes the alarm out by the idle window; the alarm only fires if no one touches the session in time.
Coalesced drain
Because there’s only one alarm per instance, you can use it as a “flush trigger”: set it on the first write, and when it fires, drain the queue and clear it. Subsequent writes during the window just append to the queue.Limits
- One alarm per actor instance. If you need multiple timers, keep a queue in
storageand use the single alarm to drive a scheduler loop. whenis ms since epoch. Don’t pass seconds. Firing precision is about one second — don’t schedule sub-second work with it.- No recurring flag. If you want periodic work, set the next alarm at the end of your
alarmhandler. - The handler has a time budget.
alarm()runs under its own wall-clock cap — larger than the 30-second method budget, on the order of minutes, but still bounded. A run that exceeds it counts as a failure and is redelivered. deleteAll()does not clear the alarm. Keys and the alarm are separate; a pending alarm still fires afterdeleteAll(), and a handler that re-arms itself will keep running against empty state. To decommission an actor:deleteAlarm()first, thendeleteAll().
Next Steps
- Runtime API —
ActorStorage,ActorContext,AlarmInfo - Quick Start — Scaffold, deploy, and curl an Account actor
- Shared Actors — Reach one actor from many functions