Queues
Durable message queues: send work, read it with a visibility timeout, archive or delete it, dead-letter what keeps failing, and let a function consume it.
A queue keeps messages until something processes them. Producers send JSON messages (optionally delayed); consumers read them, which hides each message for a visibility timeout, and archive or delete it when the work is done. If a consumer crashes, the message simply becomes visible again. With max reads, a message that keeps failing moves to a dead-letter queue. The API mirrors Supabase Queues (pgmq): send, send_batch, read, pop, archive, delete, set_vt, purge, metrics.
#Create a queue and send messages
sov queues create emails-dead
sov queues create emails --vt 60 --max-reads 5 --dlq emails-dead
sov queues send emails '{"to": "ada@example.com", "template": "welcome"}'
sov queues send emails '{"to": "bob@example.com"}' --delay 300
sov queues metrics emails#Let a function consume a queue
Bind a deployed function and Sovaria hands it batches of messages through the background job queue. A run that returns acknowledges its batch (archives it, or deletes it with ack: "delete"); a run that throws hands the messages back with a short backoff, and max_reads sends a message that keeps failing to the dead-letter queue. Process each message idempotently by msg_id.
sov queues update emails --consumer send-email --batch 10 --concurrency 2#Who can use a queue
- The project team, with the queues.read permission (list, metrics, look at messages) or queues.write (create, send, read, archive, delete, purge — reading hides messages, so it is a write).
- Service keys and your functions (their own keys).
- App users and the anon key: send only, and only to a queue whose owner turned on app send (
app_send: true). Use it when the app enqueues work for the backend; nobody can read a queue from the app. - Queues belong to the environment they were made in; every change is audited.
#Plans
| Free | Pro | Ultra | Team | Enterprise | |
|---|---|---|---|---|---|
Queues per project (queues.max_queues) | 3 | 25 | 100 | 250 | 1,000 |
Messages sent per month (queues.messages_month) | 100,000 (then stops) | 2,000,000 | 10,000,000 | 50,000,000 | 200,000,000 |
Largest message (queues.max_message_bytes) | 16 KB | 256 KB | 256 KB | 1 MB | 1 MB |
Stored per project (queues.storage_bytes) | 50 MB | 2 GB | 10 GB | 50 GB | 200 GB |
Archived / dead messages kept (queues.retention_days) | 1 day | 7 days | 14 days | 30 days | 30 days |
Paid plans bill messages beyond the allowance at $0.40 per million. Consumer runs count as function invocations. Large payloads: store them in a document or a file and send the id. See Plan limits.
#Compared with Supabase Queues
| Sovaria | Supabase Queues (pgmq) | |
|---|---|---|
| send / read / pop / archive / delete / set_vt / purge / metrics | Yes | Yes |
| Dead-letter queue after N reads | Built in | Do it yourself |
| A function consumes the queue | Built in (batches, concurrency, backoff) | Write a cron + Edge Function poller |
| Delay | Per send | Per send |
| Client-side sends | Opt-in per queue, send only | Through RLS on the queue tables |
| Console | Metrics, browse waiting / archived / dead, send, settings | Browse and send |
#Coming from Firebase or Supabase?
| Platform | What this is called there |
|---|---|
| Firebase | Cloud Tasks |
| Supabase | Supabase Queues (pgmq) |
| Sovaria | Queues |
Moving an existing app? Migrate from Supabase or Firebase imports users (with their passwords), data, files and rules.