Skip to content

In this tutorial you start QueueBox with Docker Compose, insert one row into the outbox table, and watch QueueBox deliver that row to an HTTP receiver. At the end, the row is in state sent.

You need Git, Docker with the Compose plugin, and curl. The stack uses the ports 8080 and 5432 on your machine, so stop anything else that listens on them.

Clone the repository and start the Compose stack.

Terminal window
git clone https://github.com/alternayte/queuebox.git
cd queuebox
docker compose -f docker-compose.yml --env-file .env.example up -d --build

The stack runs three services:

Service What it does
postgres PostgreSQL 16. QueueBox creates its tables in it at startup.
queuebox QueueBox, built from the repository. It reads examples/queuebox.yml.
receiver A small HTTP server. It answers 200 and prints every request body it receives.

The first build compiles QueueBox, so it takes some time. Ask QueueBox whether it is ready:

Terminal window
curl http://localhost:8080/health

A ready instance answers with status 200 and a body that starts with {"status":"healthy". If curl cannot connect, wait a moment and send the request again.

Open examples/queuebox.yml. The configuration names one HTTP destination and a route to it:

# fragment
destinations:
webhook-api:
type: http
baseUrl: http://receiver:8080
path: /webhook
timeoutMs: 30000
routes:
- topicPattern: "order.*"
destination: webhook-api

A row whose topic matches order.* goes to webhook-api. QueueBox sends it as an HTTP POST to http://receiver:8080/webhook.

Your application sends a message with one INSERT into the outbox table. Run that insert through psql in the postgres container:

Terminal window
docker compose -f docker-compose.yml exec -T postgres psql -U queuebox -d queuebox <<'SQL'
BEGIN;
INSERT INTO outbox (topic, key, payload)
VALUES ('order.created', 'order-1001', '{"orderId":"1001","amount":42}');
COMMIT;
SQL

psql prints BEGIN, INSERT 0 1 and COMMIT. The row names three columns:

  • topic is order.created, so the route order.* matches it.
  • key is order-1001. The rows of one key arrive in insert order.
  • payload is the JSON body that the receiver gets.

In a real application, the same transaction also writes the business row, for example the order itself. Both rows commit together, or neither commits.

Read the log of the receiver:

Terminal window
docker compose -f docker-compose.yml logs receiver

The last line shows the delivery:

receiver-1 | receiver listening on 8080
receiver-1 | delivered POST /webhook {"amount":42,"orderId":"1001"}

The keys of the body are in a different order. PostgreSQL stores payload as JSONB, which keeps the content of a JSON object but not the order of its keys.

QueueBox polls the outbox every 100 milliseconds in this configuration, so the line appears at once. If the line is absent, run the command again.

Read the row back from the outbox table:

Terminal window
docker compose -f docker-compose.yml exec postgres psql -U queuebox -d queuebox \
-c "SELECT topic, key, state, attempt FROM outbox;"

The output shows the row in state sent:

topic | key | state | attempt
---------------+------------+-------+---------
order.created | order-1001 | sent | 0
(1 row)

attempt counts the failed deliveries. It is 0, because the receiver accepted the first delivery.

Stop the stack and delete its database volume:

Terminal window
docker compose -f docker-compose.yml down -v

You started QueueBox, wrote one outbox row, and saw QueueBox deliver it to an HTTP endpoint and mark it sent. QueueBox did the polling, the routing and the delivery. The application wrote one row.