Edit in GitHubLog an issue

Configure message queues

The message queue topology is an Adobe Commerce and Magento Open Source feature that can be added to existing modules.

Configuring the message queue topology involves creating and modifying the following configuration files in the <module>/etc directory:

Use cases

Depending on your use case, you can create and configure communication.xml along with one or more of the following files:

  • Publish messages to an existing queue created by a third-party system—Configure the queue_publisher.xml file only.

  • Consume messages from an existing queue—Configure the queue_consumer.xml file only.

  • Define a local queue and consume messages published by a third-party system—Configure both the queue_topology.xml and queue_consumer.xml files.

communication.xml

The <module>/etc/communication.xml file defines aspects of the message queue system that all communication types have in common. Adobe Commerce supports AMQP, STOMP, and database connections.

Example

The following sample defines two synchronous topics. The first topic is for RPC calls. The second uses a custom service interface.

Copied to your clipboard
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd">
<topic name="synchronous.rpc.test" request="string" response="string">
<handler name="processRpcRequest" type="Magento\TestModuleSynchronousAmqp\Model\RpcRequestHandler" method="process"/>
</topic>
<topic name="magento.testModuleSynchronousAmqp.api.serviceInterface.execute" schema="Magento\TestModuleSynchronousAmqp\Api\ServiceInterface::execute">
<handler name="processRemoteRequest" type="Magento\TestModuleSynchronousAmqp\Model\RpcRequestHandler" method="process"/>
</topic>
</config>

topic element

Topic configuration is flexible in that you can switch the transport layer for topics at deployment time. These values can be overwritten in the env.php file.

The name parameter is required. The topic definition must include either a request or a schema. Use schema if you want to implement a custom service interface. Otherwise, specify request. If request is specified, then also specify response if the topic is synchronous.

ParameterDescription
name
A unique string identifier for the topic. Use a series of period-separated strings, with the leftmost being most general and each subsequent string narrowing the scope. For example, cat.white.feed and dog.retriever.walk. Wildcards are not supported in communication.xml.
request
Specifies the data type of the topic.
response
Specifies the format of the response. This parameter is required if you are defining a synchronous topic. Omit this parameter if you are defining an asynchronous topic.
schema
The interface that describes the structure of the message. The format must be <module>\Api\<ServiceName>::<methodName>.

handler element

The handler element specifies the class where the logic for handling messages exists and the method it executes.

ParameterDescription
name
A string that uniquely defines the handler. The name can be derived from the topic name if the handler is specific to the topic. If the handler provides more generic capabilities, name the handler so that it describes those capabilities.
type
The class or interface that defines the handler.
method
The method this handler executes.
disabled
Determines whether this handler is disabled. The default value is false.

See Handler processing.

queue_consumer.xml

The queue_consumer.xml file contains one or more consumer elements:

Example

Copied to your clipboard
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/consumer.xsd">
<consumer name="basic.consumer" queue="basic.consumer.queue" handler="LoggerClass::log"/>
<consumer name="synchronous.rpc.test" queue="synchronous.rpc.test.queue" handler="LoggerClass::log"/>
<consumer name="rpc.test" queue="queue.for.rpc.test.unused.queue" consumerInstance="Magento\Framework\MessageQueue\BatchConsumer"/>
<consumer name="test.product.delete" queue="queue.for.test.product.delete" handler="Magento\Queue\Model\ProductDeleteConsumer::processMessage" maxMessages="200" maxIdleTime="180" sleep="60" onlySpawnWhenMessageAvailable="0"/>
</config>

consumer element

AttributeDescription
name (required)
The name of the consumer.
queue (required)
Specifies the queue name to send the message to.
handler
Specifies the class and method that processes the message. The value must be specified in the format <Vendor>\Module\<ServiceName>::<methodName>. See Handler processing.
consumerInstance
The class name that consumes the message. The default value is Magento\Framework\MessageQueue\Consumer.
connection
For explicit values, use amqp, stomp, or db. If omitted, the connection is resolved automatically. See Connection resolution.
maxMessages
Specifies the maximum number of messages to consume.
maxIdleTime
Defines the maximum waiting time in seconds for a new message from the queue. If no message was handled within this period of time, the consumer exits. The default value is null.
sleep
Specifies time in seconds to sleep before checking if a new message is available in the queue. The default value is null which equals 1 second.
onlySpawnWhenMessageAvailable
Boolean value (1 or 0 only) that identifies whether a consumer should be spawned only if there is available message in the related queue. The default value is null.

queue_topology.xml

The queue_topology.xml file defines the message routing rules and declares queues and exchanges. It contains the following elements:

  • exchange
  • exchange/binding (optional)
  • exchange/arguments (optional)
  • exchange/binding/arguments (optional)

Example

Copied to your clipboard
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/topology.xsd">
<exchange name="magento-topic-based-exchange1">
<binding id="topicBasedRouting2" topic="anotherTopic" destination="topic-queue1">
<arguments>
<!-- Optional: additional arguments are processed if specified -->
<argument name="argument1" xsi:type="string">value</argument>
</arguments>
</binding>
<arguments>
<argument name="alternate-exchange" xsi:type="string">magento-log-exchange</argument>
</arguments>
</exchange>
<exchange name="magento-topic-based-exchange2" type="topic" connection="db">
<binding id="topicBasedRouting1" topic="#" destinationType="queue" destination="topic-queue2"/>
<arguments>
<argument name="alternate-exchange" xsi:type="string">magento-log-exchange</argument>
</arguments>
</exchange>
</config>

exchange element

AttributeDescription
name (required)
A unique ID for the exchange.
type
Specifies the type of exchange. Currently, the only value supported is topic.
connection
For explicit values, use amqp, stomp, or db. If omitted, the connection is resolved automatically. See Connection resolution.
durable
Boolean value indicating whether the exchange is persistent. Non-durable exchanges are purged when the server restarts. The default value is true.
autoDelete
Boolean value indicating whether the exchange is deleted when all queues have finished using it. The default is false.
internal
Boolean value. If set to true, the exchange may not be used directly by publishers, but only when bound to other exchanges. The default is false.

binding element

The binding element is a subnode of the exchange element.

AttributeDescription
id (required)
A unique ID for this binding.
topic (required)
The name of a topic. You can specify an asterisk (*) or pound sign (#) as wildcards. These are described below the table.
destinationType
The default value is queue.
destination (required)
Identifies the name of a queue.
disabled
Determines whether this binding is disabled. The default value is false.

Example topic names that include wildcards:

PatternDescriptionExample matching topicsExample non-matching topics
*.*.*
Matches any topic that contains three segments (two periods)
mytopic.createOrder.success, mytopic.updatePrice.item1
mytopic.createOrder, mytopic.createOrder.success.true
#
Matches any topic name.
mytopic, mytopic.createOrder.success, this.is.a.long.topic.name
Not applicable
mytopic.#
Matches any topic name that begins with mytopic and has a period afterward.
mytopic.success, mytopic.createOrder.error
new.mytopic.success
*.Order.#
There must be one string before .Order. There can be any number of strings (including 0) after that.
mytopic.Order, mytopic.Order.Create, newtopic.Order.delete.success
mytopic.Sales.Order.Create

arguments element

The arguments element is an optional element that contains one or more argument elements. These arguments define key/value pairs that are passed to the broker for processing.

Each argument definition must have the following parameters:

AttributeDescription
name
The parameter name.
type
The data type of the value.

The following illustrates an arguments block:

Copied to your clipboard
<arguments>
<argument name="warehouseId" xsi:type="int">1</argument>
<argument name="carrierName" xsi:type="string">USPS</argument>
</arguments>

queue_publisher.xml

The queue_publisher.xml file defines which connection and exchange to use to publish messages for a specific topic. It contains the following elements:

  • publisher
  • publisher/connection

Example

For RabbitMQ (AMQP):

Copied to your clipboard
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/publisher.xsd">
<publisher topic="magento.testModuleSynchronousAmqp.api.serviceInterface.execute" disabled="true" />
<publisher topic="asynchronous.test">
<connection name="amqp" exchange="magento" disabled="false"/>
<connection name="db" exchange="exch1" disabled="true"/>
</publisher>
</config>

For ActiveMQ Artemis (STOMP):

Copied to your clipboard
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/publisher.xsd">
<publisher topic="magento.testModuleSynchronousAmqp.api.serviceInterface.execute" disabled="true" />
<publisher topic="asynchronous.test" queue="async.test.queue">
<connection name="stomp" disabled="false"/>
<connection name="db" disabled="true"/>
</publisher>
</config>

publisher element

AttributeDescription
topic (required)
The name of the topic.
queue
For ActiveMQ Artemis (STOMP), specifies the queue name when it differs from the topic name.
disabled
Determines whether this queue is disabled. The default value is false.

connection element

The connection element is a subnode of the publisher element. Only one enabled connection can be defined for a publisher at any given time. If you omit the connection element, the connection is resolved automatically and magento is used as the exchange. See Connection resolution.

AttributeDescription
name
The connection name. For explicit values, use amqp, stomp, or db. If you omit the connection element, the connection is resolved automatically.
exchange
The name of the exchange to publish to. The default system exchange name is magento.
disabled
Determines whether this queue is disabled. The default value is false.

Connection resolution

Connection names are resolved dynamically based on the message queue deployment configuration in env.php. If you don't explicitly specify a connection, the system automatically selects the appropriate one.

Automatic resolution

The system checks env.php for message queue configuration:

  • If AMQP (RabbitMQ) is configured, the amqp connection is used
  • If STOMP (ActiveMQ Artemis) is configured, the stomp connection is used
  • Otherwise, the database (db) connection is used

Explicit connection values

When specifying a connection explicitly, use one of these values:

Connection typeValueNotes
RabbitMQ
amqp
For AMQP connections in queue_consumer.xml, the value must match the connection attribute in queue_topology.xml.
ActiveMQ Artemis
stomp
Requires Adobe Commerce or Magento Open Source 2.4.5 or later. Use ANYCAST addressing mode for point-to-point message delivery and load balancing across multiple consumers.
Database
db
MySQL-based queue storage. Used as fallback when no message broker is configured.

Handler processing

A handler is a class and method that processes a message. You can define a handler in two places:

  • In the <handler> element of the module's communication.xml file
  • In the handler attribute of the module's queue_consumer.xml file

The following conditions determine which handler is executed:

  • If the consumer in queue_consumer.xml does not have a consumerInstance defined, the system uses the default consumer: Magento\Framework\MessageQueue\Consumer. In this case, if the <consumer> element contains the handler attribute, it is used and the <handler> element in communication.xml is ignored.
  • If the consumer in queue_consumer.xml has a consumerInstance defined, the specific consumer implementation defines how the handler is used.

The following table shows how the built-in consumers process handlers:

Class nameHandler in communication.xml executed?Handler in queue_consumer.xml executed?
Magento\Framework\MessageQueue\Consumer
Only if not defined in queue_consumer.xml
Yes, if exists
Magento\Framework\MessageQueue\BatchConsumer
Only if not defined in queue_consumer.xml
Yes, if exists
Magento\AsynchronousOperations\Model\MassConsumer
Yes, if exists
Yes, if exists

Consumer spawning behavior

Two settings control when consumers spawn and exit: onlySpawnWhenMessageAvailable and consumers-wait-for-messages. Both help reduce server resource usage, but they work differently.

SettingScopeBehavior
onlySpawnWhenMessageAvailable
Per-consumer or global
Checks for messages before spawning. Only creates a consumer process if messages exist in the queue.
consumers-wait-for-messages
Global only
Always spawns a consumer. When set to false, the consumer exits immediately if no messages are available. Because this option is a global option, it cannot be configured separately for each consumer.

The key difference between the two settings: onlySpawnWhenMessageAvailable prevents unnecessary process creation, while consumers-wait-for-messages creates a process that immediately terminates if the queue is empty.

Configuration

Set onlySpawnWhenMessageAvailable globally in app/etc/env.php:

Copied to your clipboard
'queue' => [
'only_spawn_when_message_available' => 1
]

The default global value is 1. To override for a specific consumer, set the onlySpawnWhenMessageAvailable attribute in queue_consumer.xml. The per-consumer setting takes priority over the global setting.

  • Infrequent consumers—Combine onlySpawnWhenMessageAvailable with maxIdleTime. The consumer spawns only when needed and terminates after a period of inactivity.
  • Resource optimization—Combine the global only_spawn_when_message_available setting with consumers-wait-for-messages set to false. Consumers run only when messages exist and exit when the queue is empty.

env.php Configuration

The message queue connection configuration is defined in the app/etc/env.php file. When connection elements are omitted from queue_consumer.xml, queue_publisher.xml, and queue_topology.xml files, the system automatically uses the connection configured in env.php.

Example configurations

For RabbitMQ (AMQP) only:

Copied to your clipboard
return [
// ... other configuration
'queue' => [
'amqp' => [
'host' => 'localhost',
'port' => '5672',
'user' => 'guest',
'password' => 'guest',
'virtualhost' => '/'
],
'consumers_wait_for_messages' => 1
]
];

For ActiveMQ Artemis (STOMP) only:

Copied to your clipboard
return [
// ... other configuration
'queue' => [
'stomp' => [
'host' => 'localhost',
'port' => '61613',
'user' => 'admin',
'password' => 'admin'
],
'consumers_wait_for_messages' => 1
]
];

For MySQL (Database) only:

Copied to your clipboard
return [
// ... other configuration
'queue' => [
'consumers_wait_for_messages' => 1
]
// Database connection uses existing 'db' configuration
];

When multiple connection types are configured:

If you have both AMQP and STOMP configured, you must specify default_connection to indicate which one the system should use:

Copied to your clipboard
return [
// ... other configuration
'queue' => [
'amqp' => [
'host' => 'localhost',
'port' => '5672',
'user' => 'guest',
'password' => 'guest',
'virtualhost' => '/'
],
'stomp' => [
'host' => 'localhost',
'port' => '61613',
'user' => 'admin',
'password' => 'admin'
],
'default_connection' => 'amqp', // Required when multiple connections exist
'consumers_wait_for_messages' => 1
]
];

The default_connection value can be db, amqp, or stomp. When only one connection type is configured in env.php, the system automatically uses that connection and default_connection is not required. If queue/default_connection is specified, that connection is used for all message queues unless a specific connection is defined in a module's queue_topology.xml, queue_publisher.xml, or queue_consumer.xml file.

ActiveMQ Artemis (STOMP) support

Updating queue.xml

See Migrate message queue configuration for information about upgrading from Adobe Commerce and Magento Open Source 2.0 or 2.1.

  • Privacy
  • Terms of Use
  • Do not sell or share my personal information
  • AdChoices
Copyright © 2026 Adobe. All rights reserved.