Ferrite schedules future work on durable Queue state. A restart does not erase the due time, and a worker crash returns an unacknowledged lease for redelivery.
Schedule delayed work
Use delayed queue publication for reminders, expirations, retry backoff, and one-time future actions. Store a domain record and publish the schedule intent with a stable idempotency key. When the job becomes visible, re-read the domain record before applying the effect.
let job = ReminderJob { booking_id, scheduled_for_ms };
reminders
.publish_at(&serde_json::to_vec(&job)?, scheduled_for_ms)
.await?;
The fe-cal application uses this pattern for expiring slot holds and sending
booking reminders. The booking state remains authoritative; a late or repeated
job cannot resurrect a cancelled booking.
Recurring schedules
Represent a recurring schedule as durable state plus the next due occurrence. After successfully applying one occurrence, atomically advance the next due time and publish the next job. This avoids an always-on timer process and makes missed or duplicated execution observable.
Failure behavior
- Unacknowledged jobs are leased again after expiry.
- Attempt budgets move exhausted work to a dead-letter queue.
- Idempotency prevents a repeated lease from duplicating the domain effect.
- The worker checks current state so a stale reminder becomes a no-op.
See Queues for leases and dead letters, and Workflows for multi-step orchestration.