Skip to main content
Version: 4.0

Virtual Hosts

Introduction

RabbitMQ is multi-tenant system: connections, exchanges, queues, bindings, user permissions, policies and some other things belong to virtual hosts, logical groups of entities. If you are familiar with virtual hosts in Apache or server blocks in Nginx, the idea is similar.

There is, however, one important difference: virtual hosts in Apache are defined in the configuration file; that's not the case with RabbitMQ: virtual hosts are created and deleted using rabbitmqctl or the HTTP API instead.

Logical and Physical Separation

Virtual hosts provide logical grouping and separation of resources. Separation of physical resources is not a goal of virtual hosts, although certain resources can be limited for individual virtual hosts.

For example, resource permissions in RabbitMQ are scoped per virtual host. A user doesn't have global permissions, only permissions in one or more virtual hosts. User tags can be considered global permissions but they are an exception to the rule.

Therefore when talking about user permissions it is very important to clarify what virtual host(s) they apply to.

Virtual Hosts and Client Connections

A virtual host has a name. When an AMQP 0-9-1 client connects to RabbitMQ, it specifies a vhost name to connect to. If authentication succeeds and the username provided was granted permissions to the vhost, connection is established.

Connections to a vhost can only operate on exchanges, queues, bindings, and so on in that vhost. "Interconnection" of e.g. a queue and an exchange in different vhosts is only possible when an application connects to two vhosts at the same time. For example, an application can consume from one vhost then republishes into the other. This scenario can involve vhosts in different clusters or the same cluster (or a single node). RabbitMQ Shovel plugin is one example of such application.

Creating a Virtual Host

A virtual host can be created using CLI tools or an HTTP API endpoint.

A newly created vhost will have a default set of exchanges but no other entities and no user permissions. For a user to be able to connect and use the virtual host, permissions to it must be granted to every user that will use the vhost, e.g. using rabbitmqctl set_permissions.

Using CLI Tools

A virtual host can be created using rabbitmqctl's add_vhost command which accepts virtual host name as the only mandatory argument.

Here's an example that creates a virtual host named qa1:

rabbitmqctl add_vhost qa1

Using HTTP API

A virtual host can be created using the PUT /api/vhosts/{name} HTTP API endpoint where {name} is the name of the virtual host

Here's an example that uses curl to create a virtual host vh1 by contacting a node at rabbitmq.local:15672:

curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/vh1

Bulk Creation and Pre-provisioning

Virtual host creation involves a blocking cluster-wide transaction. Each node has to perform a number of setup steps which are moderately expensive. In practice it can take up to a few seconds for a virtual host to be created.

When a number of virtual hosts is created in a loop, CLI and HTTP API clients can outpace the actual rate of virtual host creation and experience timeouts. If that's the case operation timeout should be increased and delays should be introduced between operations.

Definition export and import is the recommended way of pre-configuring many virtual hosts at deployment time.

Virtual Host Metadata

Virtual hosts can have metadata associated with them:

  • A description
  • A set of tags
  • Default queue type configured for the virtual host

All these settings are optional. They can be provided at virtual host creation time or updated later.

Using CLI Tools

The rabbitmqctl add_vhost command accepts a virtual host name as well as a number of optional flags.

Here's an example that creates a virtual host named qa1 with quorum queues for default queue type, a description and two tags:

rabbitmqctl add_vhost qa1 --description "QA env 1" --default-queue-type quorum

rabbitmqctl update_vhost_metadata can be used to update all or some of the metadata values demonstrated above:

rabbitmqctl update_vhost_metadata qa1 --description "QA environment for issue 1662" --default-queue-type quorum --tags qa,project-a,qa-1662

To inspect virtual host metadata, use rabbitmqctl list_vhosts and provide the additional column(s):

rabbitmqctl -q --formatter=pretty_table list_vhosts name description tags default_queue_type

Using HTTP API

The PUT /api/vhosts/{name} HTTP API endpoint accepts a number of optional keys.

Here's an example that uses curl to create a virtual host qa1 by contacting a node at rabbitmq.local:15672. Quorum queues will be used for default queue type, a description and two tags:

curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/qa1 \
-H "content-type: application/json" \
--data-raw '{"description": "QA environment 1", "tags": "qa,project-a", "default_queue_type": "quorum"}'

can be used to update all or some of the metadata values demonstrated above:

curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/qa1 \
-H "content-type: application/json" \
--data-raw '{"description": "QA environment for issue 1662", "tags": "qa,project-a,qa-1662", "default_queue_type": "quorum"}'

Virtual host metadata is returned by the GET /api/vhosts/{name} endpoint:

curl -u userename:pa$sw0rD -X GET http://rabbitmq.local:15672/api/vhosts/qa1

Default Queue Type (DQT)

When a client declares a queue without explicitly specifying its type using the x-queue-type header, a configurable default type is used. The default can be overridden by specifying it in virtual host metadata (see above):

rabbitmqctl add_vhost qa1 --description "QA environment 1" --default-queue-type quorum --tags qa,project-a

Supported queue types are:

  • "quorum"
  • "stream"
  • "classic"

The default is only effective for new queue declarations; updating the default will not affect queue type of any existing queues or streams because queue type is immutable and cannot be changed after declaration.

Starting with RabbitMQ 3.13.4, for queues that were declared without an explicitly set queue type, the effective virtual host default will be injected into the queue properties at definition export time.

Node-wide Default Queue Type (Node-wide DQT)

Starting with RabbitMQ 3.13.4, instead of configuring the same default queue type for every virtual host in the cluster, a node-wide default can be set using rabbitmq.conf:

# supported values are: quorum, stream, classic, or a custom queue type module name
default_queue_type = quorum

When both the virtual host DQT and the node-wide DQT are set, the virtual host one will take precedence.

Migration to Quorum Queues: a Way to Relax Queue Property Equivalence Checks

Queue property equivalence check for queue type can be relaxed using a boolean setting, quorum_queue.property_equivalence.relaxed_checks_on_redeclaration, makes it possible to relax queue property equivalence checks for quorum queues.

Specifically, when a quorum queue is redeclared and the client-provided type is set to "classic", this setting will help avoid a channel exception, making it easier to migrate to quorum queues step by step, without upgrading all applications in a short period of time.

# this setting is meant to be used during transitionary periods when
# RabbitMQ default queue type is changed but not all applications have been
# updated yet
quorum_queue.property_equivalence.relaxed_checks_on_redeclaration = true

Deleting a Virtual Host

A virtual host can be deleted using CLI tools or an HTTP API endpoint.

Deleting a virtual host will permanently delete all entities (queues, exchanges, bindings, policies, permissions, etc) in it.

Using CLI Tools

A virtual host can be deleted using rabbitmqctl's delete_vhost command which accepts virtual host name as the only mandatory argument.

Here's an example that deletes a virtual host named qa1:

rabbitmqctl delete_vhost qa1

Using HTTP API

A virtual host can be deleted using the DELETE /api/vhosts/{name} HTTP API endpoint where {name} is the name of the virtual host

Here's an example that uses curl to delete a virtual host vh1 by contacting a node at rabbitmq.local:15672:

curl -u userename:pa$sw0rD -X DELETE http://rabbitmq.local:15672/api/vhosts/vh1

Limits

In some cases it is desirable to limit the maximum allowed number of queues or concurrent client connections in a vhost. As of RabbitMQ 3.7.0, this is possible via per-vhost limits.

These limits can be configured using rabbitmqctl or HTTP API.

Configuring Limits Using rabbitmqctl

rabbitmqctl set_vhost_limits is the command used to define vhost limits. It requires a vhost parameter and a JSON document of limit definitions.

Configuring Max Connection Limit

To limit the total number of concurrent client connections in vhost vhost_name, use the following limit definition:

rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 256}'

To block client connections to a vhost, set the limit to a zero:

rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 0}'

To lift the limit, set it to a negative value:

rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": -1}'

Configuring Max Number of Queues

To limit the total number of queues in vhost vhost_name, use the following limit definition:

rabbitmqctl set_vhost_limits -p vhost_name '{"max-queues": 1024}'

To lift the limit, set it to a negative value:

rabbitmqctl set_vhost_limits -p vhost_name '{"max-queues": -1}'

Virtual Hosts and STOMP

Like AMQP 0-9-1, STOMP includes the concept of virtual hosts. See the STOMP guide for details.

Virtual Hosts and MQTT

Unlike AMQP 0-9-1 and STOMP, MQTT doesn't have the concept of virtual hosts. MQTT connections use a single RabbitMQ host by default. There are MQTT-specific convention and features that make it possible for clients to connect to a specific vhosts without any client library modifications. See the MQTT guide for details.