laravelmastery
SnippetsArticlesSeriesNews

All series

Series · Overview

Queues in production

10 lessons1 hr 35 minAdvancedFreeQueues

Retries, backoff, batching and idempotent jobs, so background work keeps running when things go wrong.

By the end, paying for an order returns in milliseconds, the work behind it survives timeouts, duplicates and crashes, and Horizon shows you all of it.

Video

This series follows one order from the request that accepts it to the worker that finishes it. The request records the order and dispatches the work. The job has to be safe to retry. Horizon is how you see that work once it is running for real.

Each lesson is a page. Mark it as read when you have tried the idea, then use Next. The last lesson points at the next series, and this overview stays one link away.

MarkOrderPaid.phpPHP
class MarkOrderPaid implements ShouldQueue
{
    use Queueable;

    public function __construct(public int $orderId)
    {
    }

    public function handle(): void
    {
        $order = Order::query()->findOrFail($this->orderId);

        $order->forceFill(['status' => 'paid'])->save();
    }
}

The constructor holds an id, not the card. handle() loads the order and writes the status. The lessons after this one add the retry, the lock, and the check that makes a second run harmless.

The series follows order 1042 from the request to the supervisor.

01 The lessons

  • Keep the request short. Record the order, dispatch the job, and redirect before the provider answers.
  • The job class. Pass the order id, and keep card numbers out of the payload Horizon will show.
  • Dispatch from actions, not controllers. Put the dispatch next to the decision about the order.
  • Retries, backoff and timeouts. Pause between attempts, and make Redis wait longer than the job is allowed to run.
  • Failed jobs you can replay. Read the exception, then retry once the cause is fixed.
  • Unique jobs and WithoutOverlapping. Drop a useless second dispatch, or make it wait its turn.
  • Batches and then(). Mark the invoice sent only when the PDF and the email have both succeeded.
  • Make the job safe to run twice. Return when this attempt already landed, so a retry does not charge the card again.
  • Horizon in production. Supervise the Redis workers, and terminate them on deploy so they load the new code.

Part 1 of 3 · Hand the work off

Keep the request short, the job class, dispatch from actions.

  1. Keep the request short
  2. The job class
  3. Dispatch from actions, not controllers

Part 2 of 3 · When it goes wrong

Retries, failed jobs, unique jobs and WithoutOverlapping, batches.

  1. Retries, backoff and timeouts
  2. Failed jobs you can replay
  3. Unique jobs and WithoutOverlapping
  4. Batches and then()

Part 3 of 3 · Run it for real

Safe to run twice, Horizon in production.

  1. Make the job safe to run twice
  2. Horizon in production

Where the series leaves you

Order 1042 has a path you can point at.

  • The request returns before the provider answers.
  • The job payload is the order id and the attempt.
  • Retries wait, then stop.
  • The idempotent handle() leaves the order paid once.
  • The Horizon supervisor lists the payments queue.

Faking the queue in Test-driven Laravel is how you prove the job was pushed.

On this page

  • The lessons
  • Hand the work off
  • When it goes wrong
  • Run it for real
  • Where the series leaves you

Queues in production

  • 1 Overview

Hand the work off

  • 2 Keep the request short
  • 3 The job class
  • 4 Dispatch from actions, not controllers

When it goes wrong

  • 5 Retries, backoff and timeouts
  • 6 Failed jobs you can replay
  • 7 Unique jobs and WithoutOverlapping
  • 8 Batches and then()

Run it for real

  • 9 Make the job safe to run twice
  • 10 Horizon in production

Queues in production

Lessons

  1. 01Overview

Hand the work off

  1. 02Keep the request short
  2. 03The job class
  3. 04Dispatch from actions, not controllers

When it goes wrong

  1. 05Retries, backoff and timeouts
  2. 06Failed jobs you can replay
  3. 07Unique jobs and WithoutOverlapping
  4. 08Batches and then()

Run it for real

  1. 09Make the job safe to run twice
  2. 10Horizon in production

Get the Friday email

One snippet and the week’s Laravel news, in your inbox every Friday morning. Unsubscribe whenever you like.

laravelmastery

Practical Laravel learning for working developers, made in the UK.

Learn

  • Snippets
  • Articles
  • Series

Stay current

  • News
  • Friday email
  • RSS feed

Company

  • About
  • Privacy
  • Terms
© 2026 Laravel Mastery. Independent and not affiliated with Laravel Holdings Inc.Designed and built by Half Shell Studios

We remember the videos you watch, where you left off, and which series lessons you mark as read, against this connection’s address. Nothing is stored until you agree.