Queues

Quickstart

Learn how to use Supabase Queues to add and read messages


This guide is an introduction to interacting with Supabase Queues via the Dashboard and official client library. Check out Queues API Reference for more details on our API.

Concepts

Supabase Queues is a pull-based Message Queue consisting of three main components: Queues, Messages, and Queue Types.

Pull-Based Queue

A pull-based Queue is a Message storage and delivery system where consumers actively fetch Messages when they're ready to process them - similar to constantly refreshing a webpage to display the latest updates. Our pull-based Queues process Messages in a First-In-First-Out (FIFO) manner without priority levels.

Message

A Message in a Queue is a json object that is stored until a consumer explicitly processes and removes it, like a task waiting in a to-do list until someone checks and completes it.

Queue types

Supabase Queues offers three types of Queues:

  • Basic Queue: A durable Queue that stores Messages in a logged table.

  • Unlogged Queue: A transient Queue that stores Messages in an unlogged table for better performance but may result in loss of Queue Messages.

  • Partitioned Queue (Coming Soon): A durable and scalable Queue that stores Messages in multiple table partitions for better performance.

Create Queues

To get started, navigate to the Supabase Queues Postgres Module under Integrations in the Dashboard and enable the pgmq extension.

On the Queues page:

  • Click Add a new queue button
  • Name your queue

What happens when you create a queue?

Every new Queue creates two tables in the pgmq schema. These tables are pgmq.q_<queue_name> to store and process active messages and pgmq.a_<queue_name> to store any archived messages.

A "Basic Queue" will create pgmq.q_<queue_name> and pgmq.a_<queue_name> tables as logged tables.

However, an "Unlogged Queue" will create pgmq.q_<queue_name> as an unlogged table for better performance while sacrificing durability. The pgmq.a_<queue_name> table will still be created as a logged table so your archived messages remain safe and secure.

Expose Queues to client-side consumers

Queues, by default, are not exposed over Supabase Data API and are only accessible via Postgres clients.

However, you may grant client-side consumers access to your Queues by enabling the Supabase Data API and granting permissions to the Queues API, which is a collection of database functions in the pgmq_public schema that wraps the database functions in the pgmq schema.

This is to prevent direct access to the pgmq schema and its tables (RLS is not enabled by default on any tables) and database functions.

To get started, navigate to the Queues Settings page and toggle on “Expose Queues via PostgREST”. Once enabled, Supabase creates and exposes a pgmq_public schema containing database function wrappers to a subset of pgmq's database functions.

Enable RLS on your tables in pgmq schema

For security purposes, you must enable Row Level Security (RLS) on all Queue tables (all tables in pgmq schema that begin with q_) if the Data API is enabled.

You’ll want to create RLS policies for any Queues you want your client-side consumers to interact with.

Grant permissions to pgmq_public database functions

On top of enabling RLS and writing RLS policies on the underlying Queue tables, you must grant the correct permissions to the pgmq_public database functions for each Data API role.

The permissions required for each Queue API database function:

OperationsPermissions Required
send send_batchSelect Insert
read popSelect Update
archive deleteSelect Delete

Enqueuing and dequeuing messages

Once your Queue has been created, you can begin enqueuing and dequeuing Messages.

Here's a TypeScript example using the official Supabase client library:


_44
import { createClient } from '@supabase/supabase-js'
_44
_44
const supabaseUrl = 'supabaseURL'
_44
const supabaseKey = 'supabaseKey'
_44
_44
const supabase = createClient(supabaseUrl, supabaseKey)
_44
_44
const QueuesTest: React.FC = () => {
_44
//Add a Message
_44
const sendToQueue = async () => {
_44
const result = await supabase.rpc('send', {
_44
queue_name: 'foo',
_44
message: { hello: 'world' },
_44
sleep_seconds: 30,
_44
})
_44
console.log(result)
_44
}
_44
_44
//Dequeue Message
_44
const popFromQueue = async () => {
_44
const result = await supabase.rpc('pop', { queue_name: 'foo' })
_44
console.log(result)
_44
}
_44
_44
return (
_44
<div className="p-6">
_44
<h2 className="text-2xl font-bold mb-4">Queue Test Component</h2>
_44
<button
_44
onClick={sendToQueue}
_44
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 mr-4"
_44
>
_44
Add Message
_44
</button>
_44
<button
_44
onClick={popFromQueue}
_44
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
_44
>
_44
Pop Message
_44
</button>
_44
</div>
_44
)
_44
}
_44
_44
export default QueuesTest