How to set up message queues for asynchronous sending

Message queuing is an interesting tool that can help us create scalable websites or web services. A message queue allows applications to communicate asynchronously by sending messages to each other.



Message queuing is an interesting tool that can help us create scalable websites or web services. A message queue allows applications to communicate asynchronously by sending messages to each other.

At a high level, message queuing is pretty simple. A process, called the Producer, publishes Messages to a Queue, where they are stored until a Consumer process is ready to consume them.

Publishing messages to a message broker is a very fast operation, and we can leverage this to speed up our web services. We can delegate some tasks to background processes by making our web service publish a message to a queue instead. We can then have background consumer processes consume the messages and perform the delegated tasks as needed.

In this guide, we’ll be using RabbitMQ as a message broker. We’ll integrate RabbitMQ into a sample Flask application to defer sending mail to a background process. The application, Flaskr, may look familiar if you’ve previously completed the Flask Tutorial.

Let’s take a look at our signup view function:

Currently, the view function checks the database to make sure an account with that email address doesn’t already exist and then adds the new user to the database. The view then immediately sends a welcome email message to the user before finishing the request.

There are a couple of issues with this view that we can improve with a message queue. We don’t need to make the user wait for a response while we send the welcome email. It would be better if we can respond to the user as soon as possible. We also want a way to retry sending the welcome email if for some reason we’re unable to do it on the first try.

First, let’s run an instance of RabbitMQ in a Docker container:

Now let’s add some code to initialize a queue when our application starts:

We’re declaring a queue called “welcome_queue” that we’ll use to send messages to workers with the email address where the welcome email needs to be sent.

Next, we can update our signup view to publish a message to the queue instead of sending the welcome email.

Now we can write our worker code. The cool thing about using a message queue is that the worker process can run anywhere. It can run on dedicated worker servers, or maybe alongside your web service. This is what a simple worker script would look like:

We’re almost done! We’ve successfully decoupled sending our welcome email from the web service. Now the only thing missing is for us to retry sending the welcome email in case it fails to send for some reason. One clever way to add retry logic to your application is to use a dead letter queue.

We’ll add a second queue, the “retry_queue”, which we’ll use to temporarily place a message if we ever encounter an email send error. The messages in the retry queue will have an expiration date some time in the future. We’ll configure RabbitMQ such that when a message expires it will be placed back in our welcome queue ready to be picked up by a worker to attempt to send the email again:

And that’s it! We’ve successfully introduced asynchronous sending into our application using RabbitMQ. To download the full working example source code repository, check out my github repo.

Get more guides like this by subscribing to the blog. You’ll get an update each week with the latest posts from the Mailgun team. And if you’re not yet using Mailgun to send, receive, and track your application’s emails, you should sign up below!

Sign Up

It's easy to get started. And it's free.

See what you can accomplish with the world’s best email delivery platform.

Related readings

DigitalChalk leverages Mailgun for transactional email notifications

This post was written and contributed by Jon Wilkinson, Software Engineer at DigitalChalk...

Read more

What toasters and distributed systems might have in common

A few months ago we released automatic IP Warm Up, but we never got to talk about how it’s implemented. Today, we’re going to peek...

Read more

What is parallel programming, and how can I use it?

We’re here to discuss parallel programming, but we want to set the scene with burritos to make the topic easier to digest. If you had to make 100 burritos for a potluck party, it...

Read more

Popular posts

Email inbox.

Build Laravel 10 email authentication with Mailgun and Digital Ocean

When it was first released, Laravel version 5.7 added a new capability to verify user’s emails. If you’ve ever run php artisan make:auth within a Laravel app you’ll know the...

Read more

Mailgun statistics.

Sending email using the Mailgun PHP API

It’s been a while since the Mailgun PHP SDK came around, and we’ve seen lots of changes: new functionalities, new integrations built on top, new API endpoints…yet the core of PHP...

Read more

Statistics on deliverability.

Here’s everything you need to know about DNS blocklists

The word “blocklist” can almost seem like something out of a movie – a little dramatic, silly, and a little unreal. Unfortunately, in the real world, blocklists are definitely something you...

Read more

See what you can accomplish with the world's best email delivery platform. It's easy to get started.Let's get sending
CTA icon