RabbitMQ
Message Queue
Data Publishing
File Processing
Programming

Publish multiple messages to RabbitMQ from a file

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Publishing multiple RabbitMQ messages from a file usually means reading the file incrementally, turning each record into a message body, and sending those messages through one channel. The basic loop is easy, but reliable publishing needs a little more than for line in file: basic_publish(...).

In practice, you should think about file format, message durability, and what should happen if publishing fails halfway through the file.

A Simple Line-by-Line Publisher

If the file contains one message per line, a straightforward publisher looks like this.

python
1import pika
2
3connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
4channel = connection.channel()
5channel.queue_declare(queue="jobs", durable=True)
6
7with open("messages.txt", "r", encoding="utf-8") as fh:
8    for line in fh:
9        body = line.strip()
10        if not body:
11            continue
12
13        channel.basic_publish(
14            exchange="",
15            routing_key="jobs",
16            body=body,
17            properties=pika.BasicProperties(delivery_mode=2),
18        )
19
20connection.close()

This is enough for many scripts:

  • it reuses one connection
  • it reuses one channel
  • it skips empty lines
  • it marks messages as persistent

Why One Connection and One Channel Matter

A common beginner mistake is opening a new connection for every message. That is much slower and adds unnecessary overhead.

The normal pattern is:

  1. connect once
  2. declare the queue or exchange once
  3. publish all messages
  4. close once at the end

RabbitMQ performs much better when you treat the connection as a long-lived resource rather than something you recreate in each loop iteration.

Publishing Structured Data

Many files are CSV or JSON rather than plain free-form text. In those cases, serialize deliberately instead of sending raw Python objects.

Example with JSON lines:

python
1import json
2import pika
3
4connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
5channel = connection.channel()
6channel.queue_declare(queue="jobs", durable=True)
7
8with open("payloads.jsonl", "r", encoding="utf-8") as fh:
9    for line in fh:
10        item = json.loads(line)
11        body = json.dumps(item).encode("utf-8")
12
13        channel.basic_publish(
14            exchange="",
15            routing_key="jobs",
16            body=body,
17            properties=pika.BasicProperties(
18                content_type="application/json",
19                delivery_mode=2,
20            ),
21        )
22
23connection.close()

Setting content_type is not required by RabbitMQ itself, but it is useful metadata for consumers.

Handle Failures Deliberately

If publishing thousands of messages, you need to decide what happens when one fails.

A minimal structure is:

python
1import pika
2
3try:
4    connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
5    channel = connection.channel()
6    channel.queue_declare(queue="jobs", durable=True)
7
8    with open("messages.txt", "r", encoding="utf-8") as fh:
9        for line_number, line in enumerate(fh, start=1):
10            body = line.strip()
11            if not body:
12                continue
13            channel.basic_publish(exchange="", routing_key="jobs", body=body)
14except Exception as exc:
15    print("publishing failed:", exc)
16finally:
17    try:
18        connection.close()
19    except Exception:
20        pass

For stronger guarantees, publisher confirms are worth adding so the script knows whether the broker accepted each message.

Batch Input and Flow Control

Reading the file line by line is usually better than loading the whole file into memory.

That matters when:

  • the input file is large
  • messages are generated continuously
  • you need predictable memory usage

If throughput becomes important, you can move beyond the simplest script and add publisher confirms, batching strategy, or asynchronous publishing. But for most administrative tasks, the line-by-line pattern is the right foundation.

Common Pitfalls

The biggest mistake is opening and closing a RabbitMQ connection for every line in the file. That hurts performance badly.

Another common issue is assuming durable queues alone make the whole workflow reliable. Durable queues help, but message durability and publish acknowledgement strategy matter too.

People also send structured data without serialization or metadata, which makes the consumer side more fragile than it needs to be.

Finally, avoid reading an entire huge file into memory unless you truly need random access. Streaming the file is simpler and safer.

Summary

  • Open one RabbitMQ connection and one channel for the whole file.
  • Read the file incrementally and publish each record as a message.
  • Mark queues and messages durable when persistence matters.
  • Serialize structured data explicitly, usually as JSON.
  • Add failure handling and consider publisher confirms for stronger guarantees.
  • Prefer streaming large files instead of loading everything at once.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track 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.

Practice system design

All Rights Reserved.