---
title: "Self-hosting Queen"
description: "Deploy and operate Queen: one binary, one PostgreSQL, and the operational detail that matters."
---

> Documentation Index
> Fetch the complete documentation index at: https://queenmq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-hosting Queen

A Queen deployment is one process and one database. The broker is a single
stateless Rust binary (crate `queen`, binary `queen`) that serves
HTTP on port 6632 and keeps every byte of state in PostgreSQL. There is no
broker-local data directory to back up, no coordination service, no sidecar, and
no message file format on disk.

That is the whole required inventory. Everything else on this page is optional,
and each optional piece is off or inert until you configure it.

## What a deployment is made of

| Piece | Required? | What it is |
| --- | --- | --- |
| `queen` broker | Yes | One process. Stateless. Scales to 1–3 identical replicas. |
| PostgreSQL | Yes | The only source of truth: messages, offsets, dedup index, queue config, DLQ. |
| Schema | Applied for you | The DDL and 34 stored-procedure files are compiled into the binary and re-applied idempotently at every boot, under an advisory lock. No migration step, no extensions. |
| Dashboard | Bundled | The SPA is compiled into the binary with `rust_embed` and served from the router's fallback. There is no static-directory override. |
| `queenctl` | Bundled in the image | The operator CLI, on `PATH` inside the published container with `QUEEN_SERVER` pre-set. |
| Disk spool | On by default | Pushes are appended to `FILE_BUFFER_DIR` when PostgreSQL is unreachable, and replayed when it comes back. |
| Mesh | Optional, inert alone | Framed TCP between replicas, carrying best-effort hints only. A single broker with no peers binds nothing. |
| JWT authentication | Optional, **off** | `JWT_ENABLED=false` by default: the middleware is a transparent pass-through. |
| TLS | Not provided | The broker has no HTTPS listener. Terminate TLS in front of it. |
| `queen_proxy` | Optional | A separate binary: multi-tenant gateway with its own PostgreSQL, API keys, quotas, rate limits and metering. |

## What the broker deliberately does not do

Read this list before you put a broker anywhere a client can reach it.

- **No TLS listener.** `rustls` is linked in, but only as a *client*: for
  PostgreSQL connections and for fetching a JWKS document. Nothing in the broker
  accepts an HTTPS connection. TLS termination is a reverse proxy's job, or
  `queen_proxy`'s.
- **No CORS layer.** There is no `Access-Control-*` handling anywhere in the
  request path, so a browser cannot call the broker cross-origin.
- **No authentication by default.** With `JWT_ENABLED` unset, every route is
  served to every caller, including `/api/v1/system/*` (maintenance mode) and
  `/internal/*`, which are classified `Admin` when authentication *is* on. A
  broker on a routable address with default configuration is fully
  administrable by anyone who can reach it.
- **No rate limiting and no quotas.** The broker has no 429 path at all. Request
  admission control is `queen_proxy`'s job.
- **No leader.** Every replica serves every route. Only background maintenance
  is leader-gated, by PostgreSQL advisory locks, and the election is per cycle.

## The four things that surprise operators

Each of these is explained in full on the page that owns it; they are collected
here because they are the ones that get discovered the hard way.

> **Caution**
>
> `/health` performs a real database round-trip and answers **503** when
> PostgreSQL is unreachable. Wiring it to a Kubernetes *liveness* probe means a
> database blip restarts every broker, which defeats the disk spool that exists
> precisely to ride out that blip. Use it as a startup and readiness probe, and
> give liveness nothing that touches the database. See
> [Kubernetes](/selfhost/kubernetes).

> **Caution**
>
> The mesh port must be firewalled. Post-handshake frames are unauthenticated
> JSON, and the frame set includes `MAINTENANCE_MODE_SET`. This is a requirement,
> not a hardening tip. See [High availability](/selfhost/ha).

> **Caution**
>
> A malformed or wrong-length `QUEEN_ENCRYPTION_KEY` logs one warning and
> **disables encryption**. Queues flagged `encryptionEnabled` then store
> plaintext and their pushes still succeed. Check the boot `config: security`
> block for `encryption_key=<set:64 chars>`.

> **Caution**
>
> `POST /api/v1/configure` is a **full replace**. A key you omit is reset to its
> default, including `dedupWindowSeconds`, which returns to 3600. Always send
> the complete option set you intend the queue to have.

## Start here

- [Deploy a broker](/selfhost/deploy) — Docker and from source: the image contents, the environment variables that matter, and verification steps that actually prove it works.
- [PostgreSQL](/selfhost/postgres) — Version, privileges, why a direct connection is required, pool sizing, and the server settings that matter for this workload.
- [Configuration](/selfhost/configuration) — How the broker reads its environment, the strict boolean parser, the boot-time effective-config block, and the handful of knobs worth touching.
- [High availability](/selfhost/ha) — 1–3 replicas against one PostgreSQL, what the mesh carries and what it does not, and why the mesh port must be firewalled.
- [Upgrades](/selfhost/upgrade) — Idempotent schema re-apply, rolling replicas, what happens to in-flight leases, and why 0.16 is not a data migration.
- [Kubernetes](/selfhost/kubernetes) — A complete reference manifest written for this broker, with probes that are not coupled to the database.

## The rest of this section

The pages above get a broker running and keep it running. The remaining pages in
this section's sidebar go deeper on single subjects, and each one is worth
reading before you rely on the behaviour it describes:

- **Security**: trust boundaries, JWT algorithms and JWKS key discovery,
  broker-to-PostgreSQL TLS, and at-rest payload encryption.
- **Observability**: the log's periodic `rates` and `sizes` blocks, the metrics
  endpoints, and why `/metrics/prometheus` is not a per-tenant surface.
- **Probes and restarts**: health semantics, SIGTERM draining, and rolling
  restarts.
- **Durability**: surviving a PostgreSQL outage with the disk spool and
  maintenance mode.
- **Retention**: what the maintenance cycle deletes, and how disk grows if you
  never turn retention on.
- **Backup**: `pg_dump`, because the database is the whole state.
- **Dashboard**: what the bundled SPA shows.
- **Multi-tenant**: building your own multi-tenant service on `queen_proxy`, with
  tenants, API keys, quotas, metering, isolation, and the broker's
  `QUEEN_TENANCY_HEADER`.

For what the broker actually exposes on the wire, and every environment variable
with the default the code applies, see [Reference](/reference). For the
measured runs behind any performance claim, see [Benchmarks](/benchmarks).

Source: https://queenmq.com/selfhost/index.mdx
