A Queen node is one process and one directory. It serves the HTTP API, the dashboard and its metrics on port 6632, keeps everything it knows in its data directory, and needs nothing else running beside it: no database and no coordinator. One node is enough for development and for a good share of production loads, and when you need failover, a cluster is the same binary three or five times.
Start it
docker run --platform linux/amd64 -d --name queen -p 6632:6632 \
-v queen-data:/var/lib/queen/raft \
ghcr.io/queen-mq/queen:latestservices:
queen:
image: ghcr.io/queen-mq/queen:latest
ports: ["6632:6632"]
volumes:
- queen-data:/var/lib/queen/raft
stop_grace_period: 60s
volumes:
queen-data:git clone https://github.com/queen-mq/queen && cd queen
(cd app && npm ci && npm run build) # the dashboard, Node 24; it lands in server/webapp/dist
cd server && cargo build --release # Rust 1.88 or later; embeds the dashboard
QUEEN_RAFT_DIR=./data ./target/release/queencurl -s localhost:6632/health{"status":"healthy","engine":"raft","version":"2.0.0-beta.6","raft":{"role":"leader","leader":true,"term":1,"applied":0,"commit":0,"lag":0,"storageReady":true,"clusterVersion":3,"kinds":3}}The dashboard is at http://localhost:6632/, and the image carries the CLI, so
docker exec -it queen queenctl status works out of the box (queenctl).
Pin a version tag in production; latest moves.
The settings a first node needs
| Variable | Default | What it does |
|---|---|---|
PORT |
6632 |
The HTTP port: API, dashboard, /health, metrics |
QUEEN_BIND_ADDR |
0.0.0.0 |
The host the port binds. A host only; a value with a port stops the boot |
QUEEN_RAFT_DIR |
/var/lib/queen/raft |
The data directory. Put it on a persistent volume |
QUEEN_RAFT_DISK_HIGH_PCT, QUEEN_RAFT_DISK_LOW_PCT |
85, 80 |
Above the high mark, writes that grow storage answer 507 storage_full; they resume below the low one |
JWT_ENABLED |
false |
The broker’s own authentication. Off, every route answers any caller (security) |
QUEEN_ENCRYPTION_KEY |
unset | 64 hex characters: payload encryption for the queues that ask for it |
LOG_LEVEL, QUEEN_LOG_JSON |
info, false |
Log verbosity, and one JSON object per line |
QUEEN_SERVER_ID |
HOSTNAME |
The node’s name in the dashboard and the logs |
Booleans accept true/false, 1/0, yes/no and on/off, and any other value stops the boot with
the variable’s name, so a typo never quietly becomes a default. The node prints its effective
configuration at boot, one line per area with secrets masked, which is the first thing to read
when a setting does not seem to apply:
INFO boot: config: storage data_dir=/var/lib/queen/raft ready_lag_ms=2000 disk_high_pct=85.0 disk_low_pct=80.0 planner_queue_depth=1024
INFO boot: config: auth enabled=false algorithm=HS256 secret=<unset> public_key=<unset> jwks_url= issuer= audience= clock_skew_s=30 skip_paths=["/health", "/metrics/prometheus", "/metrics", "/"]Every variable is in configuration.
The data directory
Everything the node knows is under QUEEN_RAFT_DIR, on one volume. The queue logs in qlog/ hold
the message payloads, written and fsynced once. store/data.mdb is the embedded ordered store:
queues, partitions, consumer positions, leases, KV, timers, the dedup index and, with the
proxy on, its tenants, users and API-key hashes. A single node keeps its
replication log in log/; a cluster node keeps its vote and membership in raft/ instead.
local.db and dash.db are this node’s own metrics history and dashboard rows.
Never delete files inside the data directory to free space. A missing queue-log file is not detected at boot, so the node comes up and serves holes. Grow the volume instead.
What one node survives
| Event | What happens |
|---|---|
| kill -9, a crash, out of memory | Restart it on the same directory. Every acknowledged write is there, because a write is answered only after its fsync |
| Power loss | The same |
| The process is down | Nothing is served. Clients get connection errors and retry |
| The disk is lost | Everything is lost, unless you restore a snapshot of the volume (backups and restore) |
| The disk passes 85% | Writes that grow storage answer 507, while reads, acks and deletes keep working |
Ephemeral queues live in memory, and on a single node any restart empties them, graceful or not, because there is no other node to hand them to. A declared ephemeral queue comes back configured. In a cluster, a node that stops gracefully hands its ephemeral partitions to the others first (ephemeral queues).
Upgrade it
Stop the node with SIGTERM and start the new image on the same directory:
docker stop -t 60 queen && docker rm queen
docker run --platform linux/amd64 -d --name queen -p 6632:6632 -v queen-data:/var/lib/queen/raft \
ghcr.io/queen-mq/queen:<new-version>On SIGTERM the node stops accepting connections and lets the requests in flight finish. A parked
long-poll pop is one of them and can wait 30 seconds by default, so give the stop a minute. A
release never misreads data written by a newer one: a node whose directory belongs to a cluster
that writes a format above what the build reads refuses to start and says so (run a release that reads it ... never an older one).
Limits
One node is not highly available. While its process is down nothing is served, and its disk is the only copy; for failover, run three or five nodes.
A single node started with the defaults does not grow into a cluster in place. It runs the local replicator, and the cluster’s replicator refuses a directory the local one wrote, so moving to a cluster is a cutover: start the cluster beside the node, move the producers, let the consumers drain the old node, then move them.
A 2.0 node does not read a 1.x PostgreSQL database, so coming from 1.x is the same cutover. The broker’s port is plain HTTP; TLS is on the proxy’s listener or in front of the node (security).
The rest of this section
- Run a cluster: three or five nodes as one Raft cluster, starting from the
tested Compose file in
deploy/compose/three-node/, with quorum, failures and rolling upgrades. - Kubernetes: the StatefulSet, its volumes, probes and upgrades.
- Tenants, API keys and quotas: the proxy inside the broker and its control plane.
- Security: which port serves what, authentication, the raft token, TLS and encryption at rest.
- Monitoring: the dashboard,
/health, the metrics and the log lines worth an alert. - Recovery: what to do when a node, a disk or the majority is gone.