Queues and background workers
Create a queue, push messages, process them with workers, and use retries and the dead-letter queue.
A queue holds messages until a worker is ready to process them. Use a queue for order pipelines, calling a rate-limited outside service, webhook delivery that must not be lost, or anything where you want to see what is waiting, stuck or failed.
If you only want "run this in the background, don't block the caller", Background tasks (jobs) is simpler, because there is no queue to create and no worker to write.
How a queue behaves
- Your app sends a JSON message to a named queue.
- A worker receives it. The message is locked for a while (the visibility timeout) so two workers cannot take the same message.
- When the worker is done it acknowledges (acks) the message and it is removed.
- If the worker crashes or never acks, the message reappears after the visibility timeout and is tried again.
- If it fails more than the max retries, it moves to the dead-letter queue instead of retrying forever.
Create a queue
- In the sidebar, choose Queues & Workers, then + Create Queue.
- Enter a Queue Name (it is stored in lowercase).
- Optionally add a Description.
- Set Visibility Timeout (sec): how long a received message stays locked. The default is 30.
- Set Max Retries: attempts before dead-lettering. The default is 5.
- Optionally name a Dead-Letter Queue (optional) to receive messages that fail for good.
- Choose Create Queue.
The list shows each queue's Visibility Lock, Max Retries, Dead-Letter DLQ and Active / Done counts, with Inspect, Purge and Delete.
Inspect and test
Choose Inspect on a queue to open the Queue Inspector. Enqueue Test Message lets you set a Payload (JSON or text), a Delay (sec) and a Dedup ID, then Enqueue. Live Queue Messages shows each message's ID, status (PENDING, IN_FLIGHT or ACKED), attempts and payload, with Inspect and Ack. Execution Run Logs shows recent COMPLETED and DEAD_LETTER results, including any error.
Send, receive and ack from your code
With your secret key:
# 1. Push a message
curl -X POST https://api.pgbhub.app/api/v1/projects/my-project/queues/orders/send \
-H "Authorization: Bearer pgb_sec_..." -H "Content-Type: application/json" \
-d '{"payload": {"order_id": 4821}}'
# 2. A worker claims it
curl -X POST https://api.pgbhub.app/api/v1/projects/my-project/queues/orders/receive \
-H "Authorization: Bearer pgb_sec_..." -H "Content-Type: application/json" \
-d '{"max_messages": 1, "visibility_timeout": 30}'
# 3. Acknowledge when done
curl -X POST https://api.pgbhub.app/api/v1/projects/my-project/queues/orders/ack \
-H "Authorization: Bearer pgb_sec_..." -H "Content-Type: application/json" \
-d '{"message_id": "<id from receive>"}'
The TypeScript SDK has the same four steps: pgb.queues.send, receive, ack and nack (give a message back early, with an error).
When you send, delay_seconds holds the message back for later, and a deduplication_id stops the same message being added twice.
Good to know
- Delivery is at least once, so a message can arrive more than once. Make your worker safe to repeat.
- Purge removes every message in the queue, and Delete removes the queue itself.
- Queues can also be fed by actions and event rules, which is a clean way to react to something happening in your app.