A job class that knows which queue it belongs on has made a deployment decision at the point of definition, and changing it means editing the class.
framework:
messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
failed: 'doctrine://default?queue_name=failed'
routing:
'AppMessageSendReceipt': async
'AppMessageRebuildReport': async
# anything unrouted is handled synchronously, immediately
Unrouted messages being handled synchronously is the behaviour that makes local development pleasant and is a trap in production — a message nobody remembered to route runs inline and the request gets slower for no visible reason. The DSN in an environment variable means the same code runs against Redis locally and RabbitMQ in production with no conditional anywhere. Routing by interface rather than by class is supported and is how a whole category of message gets moved at once.