A queue lets one flow drop off work and move on, while another flow picks it up when it can. In Mule you have two: the VM connector, whose queues live inside the app, and Anypoint MQ, a cloud broker that any app can reach. Both get the work done; they differ in what survives a crash and in who decides when a message is really finished.
This lesson keeps the orders app. post-order takes the order, and booking it at the warehouse becomes somebody else's job. Each diagram plays by itself while it's on screen. The buttons change the story; the arrows step through it.
Hand off the work, or wait for it
The VM connector gives an app its own queues. VM Publish puts the message in a queue and returns straight away. A VM Listener in another flow takes it, with 4 consumers working in parallel by default. The publishing flow gets no notice of how the work went.
When you do need the answer, VM Publish Consume puts the message in the queue and waits for a reply on a temporary reply-To queue, 5 seconds by default. If the receiving flow fails, the caller gets VM:PUBLISH_CONSUMER_FLOW_ERROR. If nobody answers in time, VM:QUEUE_TIMEOUT.
post-order hands an order to process-order through the VM queue orders. With VM Publish, post-order answers the client at once and never hears whether process-order succeeded or failed. With VM Publish Consume, post-order waits for the reply on a temporary reply-To queue: it gets process-order's result as its payload, or VM:PUBLISH_CONSUMER_FLOW_ERROR when process-order fails.
flow post-order
- HTTP ListenerPOST /orders
- VM Publishqueue: orders
flow post-order
- HTTP ListenerPOST /orders
- VM Publish Consumequeue: orders
flow process-order
- VM Listenerqueue: orders
- HTTP Requestwarehouse API
- Loggerbooked
VM queue and caller
- orders
empty
- caller
waiting
Run Publish with process-order failing and watch the caller row: "answered, unaware". That's the deal with fire-and-forget. If someone has to hear about a failure, process-order must report it itself.
Transient or persistent
A VM queue is transient unless you say otherwise. Transient queues are held in memory: fast, and not reliable if the system crashes. A persistent queue is written to disk on a single runtime, or kept in the memory grid when the runtime is part of a cluster. It's slower, and the data you publish has to be serializable.
Three orders wait in the VM queue orders when the Mule runtime crashes. With a transient queue, held in memory, the queue is empty after the restart and the three orders are lost. With a persistent queue, stored on disk or in the cluster's memory grid, the orders are still there after the restart and the VM Listener processes them.
one Mule app
- VM Publishpost-order
- VM queueorders
- VM Listenerprocess-order
VM queue
- orders
3 messages
- storage
memory (transient, the default)
Two limits to know before you count on this. Persistent VM queues aren't available on CloudHub 2.0 or Runtime Fabric. And VM queues are visible only to the components that use the same VM configuration, so two different apps can share one only through a shared domain, which means running on premises.
Anypoint MQ: the queue lives outside the app
Anypoint MQ queues live in the cloud, outside every app. One app publishes, another subscribes, and they can be deployed, scaled and restarted on their own schedules. Apps that aren't Mule can use it too, over REST.
The key idea is the acknowledgement. When the Subscriber takes a message, the message goes in flight: other consumers can't see it, but it isn't deleted. An ACK deletes it. A NACK puts it back in the queue to be delivered again. The acknowledgement mode decides who sends which.
- AUTO, the Subscriber's default: ACK when the flow ends without an error, NACK when it fails.
- IMMEDIATE, the Consume operation's default: ACK as soon as the message is received, before your flow has done anything.
- MANUAL: your flow calls ACK or NACK itself, with the message's ack token.
The order-api app publishes an order to the Anypoint MQ queue orders, and the fulfilment app's Subscriber takes it. In AUTO mode a successful flow acknowledges and deletes the message; a failing flow nacks it back into the queue, it is delivered again, and after the tenth failed delivery Anypoint MQ moves it to the dead-letter queue orders-dlq. In IMMEDIATE mode the message is acknowledged and deleted on arrival, so when the flow fails the order is gone and never redelivered.
app order-api
- Anypoint MQ Publishqueue: orders
Anypoint MQ, outside both apps
- Queueorders · DLQ after 10
- Queueorders-dlq
app fulfilment · flow on-order
- Anypoint MQ Subscriberqueue: orders
- HTTP Requestwarehouse API
Anypoint MQ
- orders
1 in queue · 0 in flight
- orders-dlq
empty
- attributes
—
IMMEDIATE with a failing flow is the one to remember. The message was deleted before the flow ran, so nothing redelivers it and the dead-letter queue never sees it. AUTO is safer, but it brings a question of its own: what if the flow is slow?
A slow consumer gets the message twice
The lock on an in-flight message has a time limit: the acknowledgement timeout. The connector uses 2 minutes when you don't set one, and a queue allows up to 12 hours. If the flow is still running when the lock expires, the message goes back to the queue, and another consumer can take it.
The fulfilment app runs two replicas that subscribe to the orders queue, with a 2-minute acknowledgement timeout. When an order takes 30 seconds, replica 1 acknowledges it in time and it is deleted. When an order takes 3 minutes, the lock expires at 2 minutes, the message returns to the queue, replica 2 takes it with a delivery count of 2, and both replicas process the same order.
fulfilment · replica 1 · flow on-order
- Anypoint MQ Subscriberqueue: orders
- HTTP Requestwarehouse API
fulfilment · replica 2 · flow on-order
- Anypoint MQ Subscriberqueue: orders
- HTTP Requestwarehouse API
Anypoint MQ
- orders
0 in queue · 1 in flight
- lock
2 min left
- attributes
Delivery Count: 1
So with the 3-minute order, the same booking runs twice. That isn't a bug in Anypoint MQ: standard queues deliver at least once and the docs say a message is occasionally delivered more than once anyway. Set the timeout above your slowest run, and make the work safe to repeat, for example by checking the order id before booking.
VM or Anypoint MQ
The docs don't put the two side by side, but what they say about each points one way.
- VM queues are for work inside one app: passing messages between flows instead of a Flow Reference, spreading work across a cluster, or apps in the same domain on premises.
- Anypoint MQ is for work between apps, and for apps with different life cycles or maintenance windows. A standard queue holds unlimited messages of up to 10 MB each, for up to two weeks.
- On CloudHub 2.0 and Runtime Fabric there's no persistent VM queue, so anything that must survive a restart goes through Anypoint MQ.
Check yourself
Three questions on what you just ran. Pick an answer to see why.
post-order uses VM Publish, and process-order fails on the warehouse call. What does post-order see?
Answer
Nothing. VM Publish returns as soon as the message is in the queue and gets no notice of the outcome. Only Publish Consume waits for the receiving flow.
A Subscriber in IMMEDIATE mode takes an order, and the flow fails. Where is the order now?
Answer
Nowhere. IMMEDIATE acknowledges the message on arrival, so Anypoint MQ deleted it before the flow failed and doesn't redeliver it.
An order takes 3 minutes to process, and the acknowledgement timeout is 2 minutes. What can happen?
Answer
It's delivered again. When the lock expires the message returns to the queue, another consumer can take it, and the same order is processed twice.
Where the facts come from
Every claim in this lesson was checked against the MuleSoft documentation:
- VM Connector, its reference, and the publish and listen, publish and get a response and across apps examples
- Reliability patterns, transaction management and shared resources
- Anypoint MQ overview, queues, the glossary and the FAQ
- The Anypoint MQ connector's ACK and NACK, Subscriber and Consume pages
Two things I left out on purpose. What a full VM queue does depends on maxOutstandingMessages, and the docs disagree on what its default of 0 means. And no Mule 4 page says what happens to a VM message when a listener without a transaction fails. Next up is Anypoint MQ exchanges: one publish, several queues. If a lab does something Mule wouldn't, tell me. The contact links are right below.
Plain text: queues.md · All tracks