Menu

Alternate Exchanges

Overview

It is sometimes desirable to let clients handle messages that an exchange was unable to route (i.e. either because there were no bound queues our no matching bindings). Typical examples of this are

  • detecting when clients accidentally or maliciously publish messages that cannot be routed
  • "or else" routing semantics where some messages are handled specially and the rest by a generic handler

RabbitMQ's Alternate Exchange ("AE") feature addresses these use cases.

How to Define an Alternate Exchange

For any given exchange, an AE can be defined by clients using policies or the exchange's client-provoided options arguments ("x-args"). In the case where both policy and arguments specify an AE, the one specified in arguments overrules the one specified in policy.

Configuration Using a Policy

This is the recommended way of of defining alternate exchanges.

To specify an AE using policy, add the key 'alternate-exchange' to a policy definition and make sure that the policy matches the exchange(s) that need the AE defined. For example:

rabbitmqctl
rabbitmqctl set_policy AE "^my-direct$" '{"alternate-exchange":"my-ae"}'
rabbitmqctl (Windows)
rabbitmqctl set_policy AE "^my-direct$" "{""alternate-exchange"":""my-ae""}"

This will apply an AE of "my-ae" to the exchange called "my-direct". Policies can also be defined using the management plugin, see the policy documentation for more details.

Configuration Using Client-provided Arguments

This way of defining an alternate exchange is discouraged. Consider using a policy instead (see above).

When creating an exchange the name of an AE can be optionally supplied in the exchange.declare method's arguments table by specifying a key of 'alternate-exchange' and a value of type 'S' (string) containing the name.

When an AE has been specified, in addition to the usual configure permissions on the declared exchange, the user needs to have read permissions on that exchange and write permissions on the AE.

For example:

    Map<String, Object> args = new HashMap<String, Object>();
    args.put("alternate-exchange", "my-ae");
    channel.exchangeDeclare("my-direct", "direct", false, false, args);
    channel.exchangeDeclare("my-ae", "fanout");
    channel.queueDeclare("routed");
    channel.queueBind("routed", "my-direct", "key1");
    channel.queueDeclare("unrouted");
    channel.queueBind("unrouted", "my-ae", "");

In the above fragment of Java code we create a direct exchange 'my-direct' that is configured with an AE called 'my-ae'. The latter is declared as a fanout exchange. We bind one queue 'routed' to 'my-direct' with a binding key of 'key1', and a queue 'unrouted' to 'my-ae'.

How Alternate Exchanges Work

Whenever an exchange with a configured AE cannot route a message to any queue, it publishes the message to the specified AE instead. If that AE does not exist then a warning is logged. If an AE cannot route a message, it in turn publishes the message to its AE, if it has one configured. This process continues until either the message is successfully routed, the end of the chain of AEs is reached, or an AE is encountered which has already attempted to route the message.

For example if we publish a message to 'my-direct' with a routing key of 'key1' then that message is routed to the 'routed' queue, in accordance with the standard AMQP behaviour. However, when publishing a message to 'my-direct' with a routing key of 'key2', rather than being discarded the message is routed via our configured AE to the 'unrouted' queue.

The behaviour of an AE purely pertains to routing. If a message is routed via an AE it still counts as routed for the purpose of the 'mandatory' flag, and the message is otherwise unchanged.

Getting Help and Providing Feedback

If you have questions about the contents of this guide or any other topic related to RabbitMQ, don't hesitate to ask them on the RabbitMQ mailing list.

Documentation feedback is also very welcome on the list. If you'd like to contribute an improvement to the site, its source is available on GitHub.