Ferrite Docs

Queues

Distribute durable work with leases, delayed delivery, attempt budgets, dead-letter queues, and checkpointed consumers.

View as Markdown

Ferrite Queues deliver work to competing consumers without losing a message when a process exits. A consumer holds a time-bounded lease and acknowledges only after the domain effect is durable.

Declare and consume a queue

{
  "services": [{ "name": "emails", "primitive": "queue" }],
  "applications": [{
    "name": "email-worker",
    "artifact_key": "apps/email-worker@v1",
    "artifact_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
    "bindings": [
      { "handle": "emails", "kind": "queue", "service": "emails" }
    ]
  }]
}
let mut emails = ctx.queue("emails")?;
loop {
    let Some(lease) = emails.poll_wait(1_000).await? else { continue };
    send_email_idempotently(&lease.payload).await?;
    emails.ack(lease.token).await?;
}

If the process exits before ack, the lease expires and another consumer can receive the work. Your effect must therefore be idempotent.

Delay and retry work

Delayed publish makes a message visible at a future timestamp. Use it for reminders, reservation expiry, and backoff. Attempt budgets bound repeated failure; exhausted work moves to a dead-letter queue where you can inspect and redrive it deliberately.

Scale consumers

ferrite dev --instances 3
ferrite dev --instances 3 --chaos 5

The first command runs three competing consumers. The second repeatedly kills them so you can verify redelivery and idempotency before production.

Delivery semantics

Ferrite makes the queue decision durable and duplicate-safe. It cannot make an arbitrary external side effect exactly once. Persist a provider event ID or idempotency record, use the provider’s idempotency key when available, and acknowledge only after you can prove the effect.

Continue with Cron Jobs and Workflows.