Split message queues
By default, every message in Shopware PaaS Native goes to the single async transport defined in config/packages/operator.yaml. Long-running messages, such as indexing, can delay time-critical messages such as order confirmation emails. You can route selected messages to an additional transport so they are processed independently.
Why not edit operator.yaml
The async transport and the rest of the platform configuration come from the shopware/k8s-meta package. operator.yaml is managed by its Symfony Flex recipe, so changes to it are overwritten when the recipe is updated. Define additional transports and routing in a separate file instead. Symfony merges all files in config/packages/, so the new transport is added next to the async transport from operator.yaml.
Example: dedicated mail queue
Create config/packages/paas_messenger.yaml:
framework:
messenger:
transports:
mail:
dsn: "%env(MESSENGER_TRANSPORT_DSN)%"
options:
stream: messages_mail
consumer: "%env(MESSENGER_CONSUMER_NAME)%"
routing:
'Symfony\Component\Mailer\Messenger\SendEmailMessage': mailThis configuration:
- Adds a
mailtransport that reusesMESSENGER_TRANSPORT_DSN, so it connects to the same Valkey instance as theasynctransport. - Sets its own stream
messages_mail, so mail messages are stored separately from themessagesstream used byasync. - Reuses
MESSENGER_CONSUMER_NAME, which the platform sets for every worker, so each worker replica gets a unique consumer name. - Routes
SendEmailMessageto themailtransport instead ofasync. All other messages keep going toasync.
WARNING
Use a new, unique stream name for each additional transport. Without the stream option, the transport falls back to messages and shares the stream with async.
Adding routes versus overriding routes
How you route a message depends on how Shopware already routes it:
- Routed by class name: Shopware core routes
SendEmailMessagetoasyncby its class name. Aframework.messenger.routingentry for the same class replaces that route, as in the mail example above. - Routed by interface: Shopware routes every message that implements
AsyncMessageInterfacetoasync. Aframework.messenger.routingentry for such a message class is added to the interface route, so the message is sent to both transports and processed twice. Useshopware.messenger.routing_overwriteinstead, as described in Routing overwrites.
Adding more queues
For example, to move import and export messages to their own queue, add a transport with its own stream name. ImportExportMessage implements AsyncMessageInterface, so route it with routing_overwrite:
framework:
messenger:
transports:
mail:
dsn: "%env(MESSENGER_TRANSPORT_DSN)%"
options:
stream: messages_mail
consumer: "%env(MESSENGER_CONSUMER_NAME)%"
export:
dsn: "%env(MESSENGER_TRANSPORT_DSN)%"
options:
stream: messages_export
consumer: "%env(MESSENGER_CONSUMER_NAME)%"
routing:
'Symfony\Component\Mailer\Messenger\SendEmailMessage': mail
shopware:
messenger:
routing_overwrite:
'Shopware\Core\Content\ImportExport\Message\ImportExportMessage': exportFor details on routing, see the Symfony Messenger documentation.
Verify the configuration
Run the following commands locally to inspect the merged transports and routing:
bin/console debug:config framework messenger
bin/console debug:config shopware messengerAfter deployment, open an exec session and run bin/console messenger:stats to see the number of pending messages per transport.