Skip to main content
  1. AMQP 0-9-1: The Complete Protocol/

Virtual Hosts — Isolation and Permissions

Virtual Hosts — Isolation and Permissions #

A virtual host (vhost) is a named namespace within an AMQP broker. Every exchange, queue, and binding exists within a specific vhost. Two queues with the same name in different vhosts are completely independent — they share no state, no bindings, and no consumers. A connection attaches to exactly one vhost, specified in connection.open.

Vhosts are the isolation boundary in AMQP. They serve two purposes: namespace separation (preventing name collisions between teams or applications) and permission control (restricting what a given user can do).

The Default Vhost #

Every RabbitMQ broker has a default vhost: /. Most introductory examples connect to /. In a small deployment with a single application, the default vhost is usually sufficient.

The / naming is a convention from RabbitMQ’s design, not an AMQP spec requirement. Any string can be a vhost name; / just happens to be the default.

Vhost Isolation #

Within a vhost, all names are shared. Across vhosts, names are independent:

Vhost /app1:
  exchange: 'events'    → queue: 'order-events'
  exchange: 'commands'  → queue: 'order-commands'

Vhost /app2:
  exchange: 'events'    → queue: 'user-events'   (different queue, same name)
  exchange: 'commands'  → queue: 'user-commands'

Connection A (vhost=/app1):
  Can see: /app1 exchanges and queues
  Cannot see: /app2 exchanges and queues (don't exist from this connection's view)

Vhost isolation is enforced at the protocol level. A connection attached to /app1 cannot declare or consume from exchanges and queues in /app2. There is no way to publish a message from one vhost to another within AMQP — cross-vhost messaging requires the Shovel or Federation plugins (RabbitMQ-specific).

Creating and Managing Vhosts #

Vhosts are not created via the AMQP protocol. They are an administrative operation, performed via:

  • RabbitMQ management HTTP API: PUT /api/vhosts/{vhost}
  • rabbitmqctl add_vhost {vhost}
  • RabbitMQ management UI
# Create vhost named /payments
rabbitmqctl add_vhost /payments

# Delete vhost (deletes all exchanges, queues, bindings within it)
rabbitmqctl delete_vhost /payments

# List vhosts
rabbitmqctl list_vhosts

There is no AMQP method for vhost creation. A client that connects to a non-existent vhost receives connection.close with reply-code 404.

The Permission Model #

RabbitMQ’s permission model operates at the vhost level. Each user is granted access to a vhost with three independent permission sets, each expressed as a regular expression:

PermissionControls
configureWhich resource names the user can declare or delete (exchange-declare, queue-declare, queue-delete, etc.)
writeWhich resource names the user can write to (basic.publish, queue-bind, queue-purge)
readWhich resource names the user can read from (basic.consume, basic.get, queue-unbind)

Permissions are granted per (user, vhost) pair:

# Grant user 'app-producer' access to vhost /payments
# configure: nothing (app cannot declare resources)
# write: can publish to any exchange
# read: nothing (app cannot consume)
rabbitmqctl set_permissions -p /payments app-producer "" ".*" ""

# Grant user 'app-consumer' read-only access
rabbitmqctl set_permissions -p /payments app-consumer "" "" ".*"

# Grant user 'app-admin' full access
rabbitmqctl set_permissions -p /payments app-admin ".*" ".*" ".*"

Regular expression matching: the permission regex is matched against the resource name. ".*" matches anything. "^orders\." matches only names starting with orders.. An empty string "" matches nothing — the user has no permissions for that category.

Permission evaluation at operation time: permissions are not cached. Every AMQP operation that requires a permission check evaluates the regex against the resource name at the time of the operation. A permission change takes effect for the next operation, not just the next connection.

Tags: Management vs Application Users #

Beyond the per-vhost permissions, RabbitMQ users have tags that grant access to the management API:

TagAccess
(none)AMQP only — no management access
managementView own vhost in management UI/API
monitoringView all vhosts in management UI/API
administratorFull management API access: manage users, vhosts, policies
policymakerCreate policies but not manage users
impersonatorImpersonate other users (rare)
# Create application user (AMQP only)
rabbitmqctl add_user app-producer password
rabbitmqctl set_user_tags app-producer  # no tags

# Create admin user with management access
rabbitmqctl add_user admin password
rabbitmqctl set_user_tags admin administrator

The guest user that ships with RabbitMQ has administrator tag and full access to /always change or disable this in production.

Vhost-Level Policies #

RabbitMQ policies are a powerful extension to the vhost model: they apply configuration to exchanges and queues matching a name pattern, without requiring the client to redeclare the entities.

# Apply a dead-letter policy to all queues starting with 'work.'
rabbitmqctl set_policy -p /payments "work-dlx" "^work\." \
  '{"dead-letter-exchange":"dlx"}' \
  --apply-to queues

Policies can set:

  • dead-letter-exchange / dead-letter-routing-key: where rejected/expired messages go
  • message-ttl: per-queue TTL for all messages
  • max-length / max-length-bytes: queue size limits
  • ha-mode / ha-params: classic mirroring parameters (pre-3.8 HA)
  • quorum-initial-group-size: quorum queue initial size

The key advantage: policies apply without the client knowing. A new queue named work.orders automatically gets the dead-letter-exchange policy applied. No code change required.

When to Use Multiple Vhosts #

Use multiple vhosts when:

  1. Multiple independent applications share one broker: each application gets its own vhost. Name collisions are impossible; a bug in one application cannot consume another’s messages.

  2. Environment separation on a single broker: /dev, /staging, /prod as vhosts (though separate brokers are usually better for production isolation).

  3. Multi-tenant SaaS: each tenant gets a vhost. Tenant data is isolated without needing separate infrastructure.

  4. Permission boundaries: if two applications need genuinely different access control, separate vhosts enforce the boundary cleanly.

Do not use separate vhosts for:

  • Performance isolation: vhosts share the broker’s resources (CPU, memory, network). Heavy load in one vhost affects others. Use separate broker clusters for performance isolation.
  • Geographic separation: vhosts do not have network topology. Use Federation or Shovel for cross-datacenter messaging.

The Shovel Plugin: Cross-Vhost Messaging #

RabbitMQ’s Shovel plugin can forward messages from a queue in one vhost to an exchange in another vhost (or another broker):

rabbitmqctl set_parameter shovel my-shovel \
  '{
    "src-protocol": "amqp091",
    "src-uri": "amqp://localhost/%2Fapp1",
    "src-queue": "source-queue",
    "dest-protocol": "amqp091",
    "dest-uri": "amqp://localhost/%2Fapp2",
    "dest-exchange": "target-exchange"
  }'

Shovel runs as a consumer on the source queue and a publisher to the destination exchange. It is a RabbitMQ-specific feature, not part of the AMQP 0-9-1 spec.

Connection to a Vhost #

At the client level, connecting to a specific vhost is done in connection.open. In most client libraries, the vhost is specified in the connection URL or parameters:

# pika: connect to vhost /payments
import pika
connection = pika.BlockingConnection(
    pika.ConnectionParameters(
        host='localhost',
        virtual_host='/payments',
        credentials=pika.PlainCredentials('app-producer', 'password')
    )
)

# URL form
connection = pika.BlockingConnection(
    pika.URLParameters('amqp://app-producer:password@localhost/%2Fpayments')
)

Note: the / in a vhost name must be URL-encoded as %2F in AMQP URIs. The default vhost / becomes %2F in the URL, or is omitted (defaults to /).

Summary #

Virtual hosts provide namespace and permission isolation within a single AMQP broker. Each vhost is an independent container for exchanges, queues, and bindings. Permissions are granted per (user, vhost) pair with configure/write/read regex rules. Policies extend vhost-level configuration to matching resources without client-side declarations. Multiple vhosts suit multi-application or multi-tenant deployments; for performance isolation, separate broker clusters are needed.