Practical guide

How to process background jobs with RabbitMQ

Email, imports, or file generation do not need to keep a visitor waiting. Pass the work to the background and return a response straight away.

15 minutes · PHP application

First, the short version

What is RabbitMQ for?

RabbitMQ passes work between parts of an application. One part creates a message and puts it in a message queue. Another part picks it up and processes it later.

The sender is often called a producer. The worker is a consumer. The important part is that the web request does not wait for the slow work.

Get ready

What you need first

Before you begin, choose one small job. Sending a confirmation email is a good example.

  • RabbitMQ running locally or as a managed service.
  • A place in the application where the job starts, for example after an order is created.
  • A separate process for the consumer. It needs to run after you close the browser.
  • A clear way to see both success and failure. At first, a log and a simple test are enough.

Step 1

Split the work into a message and processing

Start with the smallest change. Let the web request create a message and move the heavy work to a consumer.

1. Choose one slow job

  1. Start with work that does not have to finish before the user receives a response. An email or an image preview is a good choice.
  2. Do not put a whole order or sensitive data into the message. An item ID and job type are usually enough.
  3. The consumer can load the current data from the application using that ID.

2. Send the message after saving data

  1. First save the change safely in the database. Only then create the queue message.
  2. The message should say only what the consumer needs to do, such as “send the email for order 123”.
  3. Assume the message can arrive more than once. The consumer must check before doing the same thing twice.

3. Run the consumer

  1. The consumer runs outside the web request and waits for the next message.
  2. In Symfony Messenger, the command below is a common way to start it. Change async to match your transport name.
  3. On a server, run it through a process manager. Locally, keep it open in a separate terminal.
php bin/console messenger:consume async -vv

Step 2

Check that the job really runs in the background

Do not stop at a page without an error. Check the whole journey of the message.

  1. Create one safe test job

    Trigger an action that sends the message. The web response should not wait for the work itself to finish.

  2. Watch the consumer

    Use its output or log to confirm it picked up and completed the message. If it cannot see it, look between the producer and the queue.

    php bin/console messenger:consume async -vv
  3. Check the result

    Check a real outcome: a sent email, generated file, or changed record. This shows that the consumer did not finish only half the work.

If something goes wrong

Common problems

Messages grow in the queue but nothing happens

The consumer is probably not running, has stopped, or listens to another queue. First check its log and the transport name in your configuration.

A job runs twice

Message delivery can be repeated. Add a check that the job is not already complete. The idempotence principle helps here.

The consumer stops on one faulty message

Record the error, configure sensible retries, and separate the faulty message from normal ones. Do not retry it forever; rules for retry help with the next attempt.

The web page still waits just as long as before

Check that you are not doing the heavy work before sending the message. The web request should create the message and return a response, not send the email itself.

Done

The first job no longer has to slow down the web.

RabbitMQ can now take over slow work. Add more jobs gradually and check the full path for each one first.

Request a call

I will call you on the next working day between 9:00 and 17:00.

You can also call me directly.

+420 605 181 728

Leave your phone number and send a callback request.

By sending, you agree to processing your data in order to handle your request.