How to copy messages to another queue on RabbitMQ?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Copying messages from one RabbitMQ queue to another is not a built-in queue-to-queue command in the way people often expect. RabbitMQ is designed around exchanges routing messages to queues, not around duplicating queue contents after the fact. The right solution depends on whether you want to duplicate future messages, migrate existing queued messages once, or bridge queues continuously between brokers.
For Future Messages, Fix the Routing
If the real goal is "send the same message to two queues from now on," do not copy messages out of a queue at all. Route them to both queues from the exchange.
For example, with a fanout exchange:
That is the cleanest design because the message is duplicated at publish time rather than copied later by operational tooling.
For Existing Messages, Consume and Republish
If messages are already sitting in the source queue, a simple one-time migration tool is often easiest. The safe pattern is:
- consume from the source queue
- publish to the destination queue
- acknowledge the source message only after the destination publish succeeds
Example with pika:
This keeps the message in the source queue until the republish succeeds. That matters if you are trying to avoid accidental loss.
Use Shovel for Operational Copying
RabbitMQ Shovel is a good operational tool when you want to move or forward messages continuously without writing code. It can read from one queue or broker and republish to another destination.
Shovel is especially useful for:
- broker-to-broker forwarding
- temporary migrations
- cross-environment bridging
It is a better fit than a custom script when the job is long-lived or needs operational visibility. For a one-time local copy, a small consumer script is often simpler.
Avoid the HTTP API for Bulk Copying
RabbitMQ’s management HTTP API has a /get endpoint, but it is primarily an administrative or debugging tool, not the normal way to bulk copy queue contents.
Why it is a poor default:
- it is easy to fetch messages in the wrong ack mode
- it is not efficient for large transfers
- it encourages manual copying logic outside normal AMQP workflows
If you do use it, pay very close attention to whether messages are requeued or acknowledged. A wrong setting can drain the source queue unexpectedly.
Be Clear About "Copy" Versus "Move"
This topic often hides an important requirement question.
If you want a copy:
- source messages must stay available after the operation
- destination gets duplicates
If you want a move:
- source can be acknowledged and drained
- destination becomes the new owner
The sample consumer above behaves like a controlled move, because it eventually acknowledges the source. A true copy requires leaving the source message in place or republishing future messages through exchange routing instead.
Common Pitfalls
The most common mistake is assuming a queue is the right place to duplicate traffic. In RabbitMQ, duplication is usually an exchange-routing concern, not a queue concern.
Another problem is acknowledging the source message before the destination publish has been confirmed. That creates a real message-loss window.
Developers also often forget that queue-level behavior such as TTL, dead-lettering, and max-length policies belongs to the destination queue, not to the copied message stream itself. Republishing into a new queue can therefore behave differently from the original.
Finally, avoid management API /get for high-volume migrations unless you have a very specific reason. AMQP consumers or Shovel are the better default tools.
Summary
- For future duplication, bind multiple queues to the same exchange instead of copying after enqueue.
- For existing messages, use a consumer that republishes and only then acknowledges the source.
- Use RabbitMQ Shovel when you need an operational forwarding or migration tool.
- Be explicit about whether you want a copy or a move.
- Avoid bulk queue copying through the management HTTP API unless the scope is small and deliberate.
Related reading
- How to count number of records (message) in the topic using kafka-python
- How to create a delayed queue in RabbitMQ?
- How to create a kafka consumer group in Golang?
- How to Create a Kafka Consumer Record from a String to build Junit test case
- How to correctly save instance state of Fragments in back stack?
- How to correctly shut down Python RQ worker processes dynamically?
- How to create a Kafka Topic using Confluent.Kafka .Net Client
- How to create a list of topics in Apache Kafka using single command

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.