Virtual Hosts — Isolation and Permissions
Table of Contents
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:
| Permission | Controls |
|---|---|
| configure | Which resource names the user can declare or delete (exchange-declare, queue-declare, queue-delete, etc.) |
| write | Which resource names the user can write to (basic.publish, queue-bind, queue-purge) |
| read | Which 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:
| Tag | Access |
|---|---|
| (none) | AMQP only — no management access |
management | View own vhost in management UI/API |
monitoring | View all vhosts in management UI/API |
administrator | Full management API access: manage users, vhosts, policies |
policymaker | Create policies but not manage users |
impersonator | Impersonate 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 gomessage-ttl: per-queue TTL for all messagesmax-length/max-length-bytes: queue size limitsha-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:
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.
Environment separation on a single broker:
/dev,/staging,/prodas vhosts (though separate brokers are usually better for production isolation).Multi-tenant SaaS: each tenant gets a vhost. Tenant data is isolated without needing separate infrastructure.
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.