siliceum

Message queue naming conventions: a practical guide

You open your RabbitMQ management console on a Monday morning. 247 queues are listed. Some are called orders, others team3-prod-notifs, others test_queue_final_v2. Which one is in production? Which one can you safely delete? Nobody knows.

Without naming conventions, a shared broker becomes a minefield. This article proposes a reusable template, adapted to the constraints of RabbitMQ, Kafka and AWS SQS, so that every queue name is self-documenting.

Queue, topic, exchange?

In this article, message queue refers to the generic concept: a RabbitMQ queue, a Kafka topic or an SQS queue. The naming convention applies to all of these objects, even though their mechanics differ.

Why standardize naming

In an enterprise context, the message broker is often a shared resource across domains. Multiple applications—sometimes multiple teams—publish and consume messages on the same cluster.

Without an explicit convention, each team invents its own format. The result?

  • Grafana dashboards are unreadable: impossible to filter by team or domain
  • An incident at 2 AM on queue_notif_3 doesn’t tell you who owns it
  • Test queues pile up and never get cleaned

A structured naming convention, even a lightweight one, solves these problems the same way DNS structures domain names: with readable, hierarchical segments.

  • Observability: a structured name integrates directly into dashboards and alerts
  • Incident response: the name identifies the team, domain and environment at a glance
  • Multi-team governance: every team follows the same format without heavy coordination
  • Automation: cleanup scripts, dashboards and alerting can parse queue names

If you’ve ever experienced an incident on a shared broker, you know the first minute is critical. A 99.9% SLA leaves only 43 minutes of downtime per month: every second spent figuring out “whose queue is this?” is a second lost.

Anatomy of a good name

An effective queue name is composed of ordered segments, separated by a delimiter. Each segment carries a specific piece of information.

Environment

The first segment immediately distinguishes production queues from test queues.

Typical values: prod, staging, uat, dev, e2e.

Shared broker without environment prefix

If your broker is shared across environments (which is common in development), the absence of an environment prefix is the number one cause of messages sent to the wrong place. This segment is not optional.

Owner

The name of the entity responsible for the queue: the one to contact when something goes wrong. Two common approaches:

  • By team: team-payments, team-logistics. Advantage: clear ownership for incident response, stable even as applications evolve.
  • By application: billing-service, shipping-api. Advantage: direct traceability in logs and metrics, more precise when multiple applications coexist within the same team.

The key is to pick one model and stick with it. Avoid unstable names: a person (jean-bob-queue), a temporary project or a sprint name.

Domain

The business domain the queue belongs to: booking, invoicing, notification, inventory.

This segment lets you visually group queues by business context in the broker console.

Entity

The business entity concerned by the messages: order, shipment, payment, user.

This segment, often overlooked, distinguishes queues within the same domain. Without it, prod.team-payments.invoicing.events.v1 doesn’t tell you which events are flowing through.

Domain vs entity

The domain represents the functional scope (invoicing), the entity represents the specific business object (invoice, credit-note). If your domain contains only one entity, you can merge both segments.

Pattern

The usage pattern of the queue:

  • events: business events (publish/subscribe)
  • commands: commands destined for a specific consumer
  • retry: messages waiting for a new attempt
  • dlq: dead letter queue, the cemetery of failed messages
  • buffer: buffer queue to absorb load

Version

The message contract version: v1, v2.

Queues carry messages that follow a specific data structure. It’s an API. If a breaking change occurs (field removed, format changed), the version must change.

Schema registry

If you use a schema registry (Confluent, AWS Glue), the version in the queue name designates the major version of the contract. Compatible evolutions (adding optional fields) don’t require a new queue.

The complete template

<environment>.<owner>.<domain>.<entity>.<pattern>.<version>

Concrete examples:

Queue nameMeaning
prod.team-payments.invoicing.invoice.events.v1Invoice events in production, payments team
staging.team-logistics.shipping.shipment.commands.v1Shipping commands in staging
prod.team-payments.invoicing.invoice.dlq.v1Dead letter queue for invoice events
prod.team-marketing.notification.email.buffer.v2Email notification buffer queue, v2
dev.team-platform.monitoring.alert.events.v1Alerting events in development

Adapting the convention to your broker

The template above is a generic model. Each broker imposes its own constraints: separator, maximum length, allowed characters. Here’s how to adapt it.

RabbitMQ

RabbitMQ uses . as the natural separator in routing keys, making the template directly compatible. The limit is 255 bytes (UTF-8 encoded) for a queue name. In practice, with pure ASCII names (letters, digits, ., -), one character equals one byte, so the limit is effectively 255 characters.

Routing keys and wildcards

RabbitMQ routing keys support the wildcards * (one segment) and # (zero or more segments). Your naming convention must be consistent with your routing rules: prod.team-payments.invoicing.* should match all invoicing queues for the payments team in production.

Kafka

Kafka accepts both . and - as separators. The limit is 249 characters for a topic name. Note: consumer groups also need a naming convention.

Suggestion for consumer groups: <application>.<topic-name> lets you immediately identify which application consumes which topic.

Kafka consumer groups

The consumer group name appears in lag metrics. A structured name (app-billing.prod.team-payments.invoicing.invoice.events.v1) makes it easier to alert on consumption lag.

AWS SQS

SQS uses - as a separator (. is allowed but unconventional). The limit is 80 characters, which forces brevity.

For FIFO queues, the .fifo suffix is mandatory and counts toward the 80-character limit.

80 characters is short

With SQS, prefer consistent abbreviations: prd instead of prod, pay instead of payments. Document these abbreviations in your ADR or team wiki.

Comparison table

BrokerSeparatorMax lengthSpecifics
RabbitMQ.255 bytesWildcards * # on routing keys
Kafka. or -249 charsConsumer group needs naming too
AWS SQS-80 charsFIFO = .fifo mandatory

Common pitfalls

Even with a template, certain mistakes keep coming back.

  • Unstable owner name: avoid names of people, temporary projects or sprints. Whether you choose a team or application name, it must be canonical and durable
  • Inconsistent casing: Team-Payments here, team_payments there. Pick kebab-case and stick with it
  • Transient information in the name: sprint-42-test-queue means nothing in 6 months
  • No environment prefix: the queue order-events exists in prod and dev? Good luck debugging
  • Name too long for the broker: test the length before deploying, especially on SQS (80 chars)
The 2 AM test

Before validating a queue name, ask yourself this question: could a colleague who doesn’t know the project understand this queue at 2 AM, in the middle of an incident? If the answer is no, the name needs rework.

What about automated tests?

When running integration tests, you often need to create queues on the fly. Each execution needs its own queues to avoid collisions between parallel tests.

The solution: add a UID as suffix. Prefer a short, readable UID (execution context + test identifier + timestamp) over a full 36-character UUID.

e2e.team-payments.invoicing.invoice.events.v1.runner-1.test-13.20250127T1112

The problem: these temporary queues accumulate. Without a cleanup mechanism, you can end up with thousands of orphaned queues.

12,000 orphaned queues

On a real project, we discovered over 12,000 orphaned test queues on a RabbitMQ cluster. The cleanup took a full day. An automatic mechanism would have prevented this debt.

Each broker offers cleanup mechanisms:

  • RabbitMQ: the x-expires argument automatically deletes a queue after a period of inactivity (e.g. 1 hour)
  • Kafka: the retention policy (default 7 days) can be reduced for test topics
  • AWS SQS: no native TTL on the queue itself, but a cleanup script based on the date in the name works well
  • Universal fallback: a cron job that lists queues prefixed with e2e. and deletes those older than 24h

If you run realistic load tests, the volume of temporary queues can be even higher. Automate cleanup from the start.

Formalize and enforce

A convention that isn’t enforced is a convention that doesn’t exist. Here’s how to make it durable.

ADR over wiki: document the convention in an Architecture Decision Record versioned with the code. A wiki gets lost; an ADR in the Git repository stays visible and maintained.

CI validation: a regex in your CI pipeline can reject non-compliant names before deployment.

Validation regex example

^(prod|staging|uat|dev|e2e)\.[a-z0-9-]+\.[a-z0-9-]+\.[a-z0-9-]+\.(events|commands|retry|dlq|buffer)\.(v[0-9]+)$

This regex validates the 6-segment format. Adapt it to your needs: add patterns, allow optional segments, or adjust environment values.

Queue catalog: a YAML or JSON file in your repository that lists all declared queues, with their owner and description. This catalog can feed your dashboards and alerts.

If you use an artifact promotion approach, the queue catalog can follow the same lifecycle as your artifacts: declared in dev, promoted to staging, then to production.

TL;DR

  • Structure names with ordered segments: <env>.<owner>.<domain>.<entity>.<pattern>.<version>
  • Adapt separator and length to your broker’s constraints (. for RabbitMQ/Kafka, - for SQS)
  • Pick a stable owner: team or application, it doesn’t matter, but the name must be canonical and durable
  • Always prefix the environment: a shared broker without prefix is an incident waiting to happen
  • Automate cleanup for test queues with x-expires, retention policies or cron jobs
  • Formalize in an ADR and validate with a CI regex so the convention survives turnover

Need an outside perspective?

Naming conventions, broker governance, event-driven architecture: we help tech teams structure their asynchronous messaging. Let’s talk.

Photo de Cédric CHARIERE FIEDLER

Written by

Cédric CHARIERE FIEDLER

Web & API Architect – Reliability, Performance, QA

View profile