Message queues let services communicate asynchronously — a producer publishes a message and moves on immediately, while a consumer processes it whenever it’s ready, decoupling the two in time as well as space.
import pika
# Producer: publish a message and don't wait for it to be processed
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='email_notifications', durable=True)
channel.basic_publish(
exchange='',
routing_key='email_notifications',
body='{"to": "user@example.com", "subject": "Order confirmed"}',
properties=pika.BasicProperties(delivery_mode=2) # persist to disk
)
connection.close()
# Consumer: processes messages whenever it's ready, independently
def callback(ch, method, properties, body):
send_email(body)
ch.basic_ack(delivery_tag=method.delivery_tag) # confirm processing succeeded
channel.basic_consume(queue='email_notifications', on_message_callback=callback)
channel.start_consuming()
Why This Matters
If the email service is slow or temporarily down, the order-placing request doesn’t wait for it — the message sits safely in the queue until a consumer is ready. This decoupling also naturally smooths out traffic spikes: a burst of 10,000 orders queues up messages that get processed steadily, rather than overwhelming the email service all at once.