Queues and Background Tasks in PHP: How to Speed Up Your Site and Not Lose Data

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to prevent your PHP site from "freezing" on long operations?

\n\n

Have you ever waited 30 seconds for a site to send a confirmation email? Or watched a page "hang" while generating a PDF report? In the PHP world, where each request is typically executed synchronously, such tasks can ruin the user experience. But there is a proven solution — queues and background tasks. They allow you to move "heavy" work behind the scenes and instantly show the user: "Your request has been accepted!".

\n\n

In this article, we will break down how to organize queues in PHP using popular tools: RabbitMQ, Redis, and Gearman. You will see real code examples, learn how to avoid common mistakes, and be able to implement background processing on your project today.

\n\n

Why are queues needed in PHP?

\n\n

PHP traditionally works in a "request-response" model. But when it comes to operations that take longer than 1-2 seconds (sending emails, image processing, generating reports, webhooks), the user faces timeouts or simply gets bored watching a spinner. Queues solve this problem radically:

\n\n
    \n
  • Instant response — the user immediately gets a response, and the heavy task goes to the background.
  • \n
  • Scalability — you can run dozens of workers in parallel without changing the code.
  • \n
  • Reliability — if a worker "crashes", the task remains in the queue and will be executed later.
  • \n
  • Load balancing — peak loads are smoothed out through buffering.
  • \n
\n\n

Let's see how to implement this in practice using three of the most popular approaches.

\n\n

1. Queues on Redis: easy and fast

\n\n

Redis is not just a cache. Thanks to its data structures (lists, sets) and the Pub/Sub mechanism, it is ideal for simple queues. If you already have Redis on your server, this is the fastest way to implement background tasks without installing additional services.

\n\n

Example: email newsletter queue with Redis

\n\n

Suppose after a user registers, you need to send a welcome email. Instead of calling mail() inside the controller, we simply put the task into the queue.

\n\n

Step 1. Adding a task to the queue (producer):

\n\n
<?php\n// producer.php\n$redis = new Redis();\n$redis->connect('127.0.0.1', 6379);\n\n$task = json_encode([\n    'type' => 'welcome_email',\n    'user_id' => 42,\n    'email' => 'user@example.com',\n    'created_at' => time()\n]);\n\n// RPUSH adds an element to the end of the list\n$redis->rPush('email_queue', $task);\necho "Task added to queue\\n";\n?>
\n\n

Step 2. Worker that processes tasks (consumer):

\n\n
<?php\n// worker.php\n$redis = new Redis();\n$redis->connect('127.0.0.1', 6379);\n\necho "Worker started, waiting for tasks...\\n";\n\nwhile (true) {\n    // BLPop blocks execution until an element appears\n    $taskData = $redis->blPop('email_queue', 5); // timeout 5 sec\n    \n    if ($taskData) {\n        $task = json_decode($taskData[1], true);\n        \n        echo "Processing task: {$task['type']} for {$task['email']}\\n";\n        \n        // Simulating sending an email\n        sleep(2);\n        \n        // Here is the real logic: mail(), SMTP, etc.\n        echo "Email sent to user {$task['user_id']}\\n";\n    }\n}\n?>
\n\n

Launch:

\n

The worker is started in the background (via nohup or Supervisor):

\n
php worker.php &
\n\n

Now, when a user registers, the controller calls producer.php and immediately returns a response, while the worker calmly processes the emails. Redis guarantees that the task will not be lost, even if the worker temporarily crashes.

\n\n

2. RabbitMQ: the industry standard

\n\n

If your project is growing

Blogs

Book Recommendations