The operations console for RabbitMQ

Your dead letters, handled before the 3 a.m. call.

The management UI configures your broker and tells you a queue holds 300 messages. Warren runs the traffic on it: what those messages are, why they died, who should have consumed them, and one audited click to put them back.

Self-hosted next to your broker. Works with RabbitMQ 3.x and 4.x, classic and quorum queues. The Community edition ships first; the waitlist gets the image on release day.

Warren · production · vhost /

Queues

14 dead letters
QueueMessagesConsumersDead-letters to
orders.dlqDLQ90
billing.invoice.deadDLQ50
orders.process34orders.dlx
shipping.label72

orders.dlq

9 of 9 shown
Message idLast deathOriginal routePayload
order-4700expired ×5 wait.5morders → order.created{"orderId":4700,"customer":"ACME…
order-4701expired ×5 wait.5morders → order.created{"orderId":4701,"customer":"ACME…
order-4702expired ×5 wait.5morders → order.created{"orderId":4702,"customer":"ACME…
order-4703rejected ×1 processorders → order.created{"orderId":4703,"customer":"Nort…
Replay messages
Selected in the table (3)
First 10 messages from the head of the queue
Original route from x-death
Queue · Exchange
Move 3 selected messages from “orders.dlq” to their original exchange and routing key. Death headers are stripped.

Replays

Audit log
WhenByFrom → ToReplayedStatus
just nowninaorders.dlq → original route3COMPLETED
Tue 09:14ops-botbilling.invoice.dead → billing.invoice12COMPLETED
Mon 17:02tomasorders.dlq → orders / order.retry0FAILED

Every replay: who, when, from where to where, per-message outcome, payload preview.

Replay completed3 replayed, 0 failed, 3 scanned
Dead-letter queues float to the top
Management UI says

orders.dlq · 9 messages ready

Nine orders from ACME failed with “No message” after five retries, and the consumer has been gone since 07:10. Here they are.

Your runbook says

rabbitmqadmin get … | jq … | rabbitmqadmin publish …

Select, replay to the original route, done. Death headers stripped so they get a fresh retry budget.

The postmortem asks

Who replayed what last night?

The audit log answers it. User, time, source, target, every message, every outcome.

Not another admin UI

The management console configures your broker. Warren runs the traffic on it.

You keep the management UI, and you should. Warren does not compete with it and does not touch its job. It answers the four questions the console cannot, in the order on-call asks them.

Management UI, rabbitmqctl, Terraform

Configure the broker

  • Declare exchanges, queues and bindings
  • Policies, limits, federation, shovels
  • Broker users and permissions
  • Cluster formation and node health
  • Counts and rates per queue

Stays as it is. Warren needs no configure permission and never declares, deletes or purges.

Warren

Operate the traffic

  • Read messages, payload and full death history
  • Search across payloads, ids and routing keys
  • Metrics history and alerting on the queues that matter
  • Replay, edit, reset retries, all with an audit trail
  • Roles and SSO so support can look and on-call can act

Reads through the management API, publishes over AMQP with a least-privilege user.

  1. 1Is something broken?

    Dead-letter counts on top, history charts, rules like “DLQ above 100 for 5 min” to Slack, Teams or a webhook.

  2. 2What exactly?

    Open the queue, read the messages, search for the order id the customer just gave you.

  3. 3Why?

    The x-death timeline: which queue rejected it, how often, when, and the retry counter that would bounce it again.

  4. 4What now?

    Replay to the original route, fix the payload first if needed, and let the audit log answer the postmortem.

Features

Built for the moment a queue turns red.

Warren reads the same broker your team already runs and adds the parts the management console leaves out: meaning, history, and a safe way to act.

See what actually died

Peek at messages without consuming them. Pretty JSON, headers, and the complete x-death history: which queue rejected it, how often, when.

expired · q.orders.wait.5m · ×5 · 10 Sep 07:11

Replay to the original route

Selected messages or the first N, back to the exchange and routing key they came from. Or to any queue or exchange you name.

publisher confirms · mandatory · unroutable = failed, not lost

Fix it before you send it

Edit payload and headers of a message in place. Drop the consumer's retry counter so the message gets a real second chance, not an instant bounce.

x-retry-count: 5 → 0 · x-warren-edited: true

An audit log people trust

Who replayed what, when, from where to where, and what happened to each message. Fingerprints link every entry back to the queue.

COMPLETED · PARTIAL · FAILED · per message

History and alerts

Every queue sampled around the clock. Charts from 15 minutes to 7 days. Rules like “DLQ above 100 for 5 min” notify Slack, Teams or any webhook.

MESSAGES_ABOVE · NO_CONSUMERS · GROWTH

Clusters, roles, SSO

Any number of clusters and vhosts in one place. Viewers read, operators replay, admins manage. Sign in with your OIDC provider.

Keycloak · Entra ID · Okta · local users
See it work

Five more things Warren does while your runbook is still loading.

Each preview is the real flow, drawn from the actual screens. No mock data that hides the messy parts.

Fix before you send

Reset the retry counter, drop the stack trace, replay.

A message that was rejected five times carries that history in its headers. Replay it untouched and the consumer gives up instantly. Warren shows the headers, strips the bookkeeping on one click, and lets you correct the payload while you are there.

x-retry-count 5 → removed · x-last-exception-* removed · payload edited · audit says so
Replay messages · orders.dlq · 1 selected
Headers
x-tenantacme
x-retry-count5
x-last-exception-typeAmqpRejectAndDontRequeue…
x-last-exception-messageNo message
x-last-exception-stacktrace2,847 chars
x-original-routing-keyorder.created
Edit headers before replay
Payload · application/json · 48,671 B
{ "orderId": 4700, "customer": "ACME-0", "currency": "EUR", "attachment": «base64, 48,212 chars» }
1 long value collapsed · show raw
Replay completed1 replayed · edited · headers and payload
History and alerts

Know about the pile-up before the customer does.

Warren samples every queue around the clock. A rule like “orders.dlq above 100 for five minutes” fires once, reaches Slack, Teams or any webhook with a link to the queue, and sends the all-clear when it recovers. No flood, no silence.

MESSAGES_ABOVE · NO_CONSUMERS · GROWTH · re-notify after 4 h
orders.dlq · production · history 1 h
RuleConditionChannelState
Orders DLQ growingmessages > 100 for 300 s#ops-alertsOK
Billing stuckno consumers, ready > 0#billingOK
Warren APP · 11:07
🔴 FIRING: Orders DLQ growing on production/orders.dlq: 143 messages (threshold 100, for 300s) · open queue
Sampling every 30 seconds
Clusters, roles, SSO

One Warren for every broker, and not everyone gets the replay button.

Switch between production, billing and staging in the top bar. Viewers browse and learn, operators replay, admins manage rules and users. Roles come from your identity provider or from local accounts.

VIEWER · OPERATOR · ADMIN · OIDC roles claim → Warren role
production · /
nina operator

Queues

14 dead letters
QueueMessagesConsumers
orders.dlqDLQ90
billing.invoice.deadDLQ50
orders.process34
shipping.label72
Every cluster and vhost in one place
Search

Find order 4711 in 200 dead letters before the customer finishes the sentence.

One field searches payload, message id, correlation id and routing key at once, and narrows the table as you type. Every entry in the audit log carries a fingerprint you can paste here to find that exact message again, weeks later.

payload · message id · correlation id · routing key · fingerprint prefix
Users and permissions

Give support the read access. Keep the replay button for on-call.

Three roles that build on each other: viewers browse queues, payloads and history, operators additionally replay and edit, admins additionally manage alerts and users. Create accounts in the UI, lock one in a second, or map roles from your identity provider's claims. Warren refuses to remove its last administrator.

local accounts · OIDC claim → role · bcrypt · last-admin guard
Users · local accounts
nina admin

Users

OnUsernameRolesLast login
ninaADMIN2 min ago
tomasOPERATORyesterday
supportVIEWER3 days ago
What each role may do
VIEWEROPERATORADMIN
Browse queues, payloads, history, audit
Replay, edit payload and headers
Alert rules and channels
Users and roles
New user
ViewerOperatorAdmin
••••••••••••
User sam createdOperator · changes apply at next sign-in
Accounts and roles live in Warren, not in a config file
Why messages come back

Warren reads the whole journey, not just the last stop.

A dead letter usually has a story. RabbitMQ writes it into headers nobody reads. Warren turns them into a timeline and tells you what a replay will actually do.

publishedorders → order.created10:58:02
rejected ×1orders.processNo message
waitedwait.1s → 10s → 1mx-retry-count 4
expired ×5orders.wait.5m11:05:41
parkedorders.dlquntil you act

Replaying this message as-is would send it straight back to the DLQ: the consumer reads x-retry-count: 5 and gives up. Warren shows you that header, lets you reset it in the replay dialog, and records that you did.

How replay works

No message is ever lost. Here is the exact mechanism.

Dedicated channel, confirms on

Warren opens its own AMQP channel with publisher confirms. Nothing is shared with your consumers.

Fetch without acknowledging

Messages are taken with basic.get and left unacknowledged, so each fetch returns the next one. Unselected messages are released back in place.

Publish, then confirm, then ack

A selected message is published with mandatory=true. Only after the broker confirms does Warren acknowledge the source. Unroutable publishes come back as failures.

Release everything else

What was not moved is requeued in its original position. Closing the channel releases the rest, even if Warren crashes mid-way.

At-least-once, stated plainly. If Warren dies between the broker's confirm and its own ack, that one message is delivered twice. That is the same promise RabbitMQ makes, and your consumers should be idempotent anyway. Warren says so in the dialog instead of pretending otherwise.
Self-hosted

Runs next to your broker. Your payloads never leave your network.

One container plus Postgres. Configure clusters with environment variables or a YAML file, put it behind your ingress, sign in with SSO. Air-gapped installations work: the licence is checked offline.

  • Docker image and Helm chart, versioned releases, Flyway migrations on upgrade
  • Reads through the management API, replays over AMQP with a least-privilege user
  • Metrics and audit stay in your Postgres, retention is yours to set
  • No telemetry, no phone-home, no third-party scripts
docker-compose.yml
# the broker you already run, plus Warren and its database
services:
  warren:
    image: ghcr.io/warren-dev/warren:1.0
    ports: ["8080:8080"]
    environment:
      WARREN_RABBIT_MANAGEMENT_URL: http://rabbitmq:15672
      WARREN_RABBIT_HOST: rabbitmq
      WARREN_RABBIT_USERNAME: warren
      WARREN_RABBIT_PASSWORD: ${RABBIT_PASSWORD}
      WARREN_DB_URL: jdbc:postgresql://postgres:5432/warren
      WARREN_OIDC_ISSUER_URI: https://login.example.com/realms/platform
  postgres:
    image: postgres:17-alpine

$ docker compose up -d   # then open http://localhost:8080
Pricing

Free to browse and replay. Pay when Warren runs your on-call.

The Community edition is open source and stays free. Pro is in development. Both are waitlist-only until release; early-access pricing shown.

CommunityWaitlist open
€0 forever, Apache 2.0
  • One cluster, one vhost
  • Browse dead letters with full x-death history
  • Replay to original route, queue or exchange
  • Payload and header editing
  • Audit log and local users

You get the image link the day it ships. Nothing else.

ProIn development
€149 per cluster / month, or €1,490 / year
  • Unlimited clusters and vhosts
  • Roles: viewer, operator, admin
  • OIDC single sign-on
  • Metrics history and alerting to Slack, Teams, webhooks
  • Priority support, offline licence

Early-access customers lock in this price. We reply personally.

FAQ

Questions operators ask first.

Is Warren a replacement for the management UI?

No, and it is not trying to be. The management UI configures the broker and will keep doing that. Warren is for the people who run the traffic on it: reading messages, finding out why they died, alerting, replaying, and proving afterwards what was done. Most teams have both open.

Will Warren ever declare queues or edit policies?

No, by design. A tool that can replay production messages should not also be able to reshape the broker. Keeping Warren read-plus-publish is what lets you give it to a wider circle than the admin UI.

Does Warren change my broker configuration?

No. It reads queues, bindings and messages through the management API and publishes over AMQP. It never declares, deletes or purges anything.

What permissions does the RabbitMQ user need?

The management tag plus read and write on the vhosts you configure. Configure permission is not required.

Does peeking at messages have side effects?

RabbitMQ marks peeked messages as redelivered. That is a property of the broker and is visible to consumers as a flag; the messages stay in place and in order.

Which RabbitMQ versions are supported?

3.13 and 4.x, classic and quorum queues. Streams are read-only for now.

Where is my data?

In your network. Warren stores replay audit entries, queue metrics and users in your Postgres. Payload previews in the audit log are capped at 2 KB and can be turned off.

Get started

Be first in line when Warren ships.

One e-mail on release day with the image and the compose file. Then it is three commands to your first replay.

Community first, Pro follows. No newsletter, no sharing of your address.