Laravel Queue Backpressure &amp; Dead-Letter Strategies | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Laravel Queues at Scale: Backpressure, Overflow Routing, and Dead-Letter Strategies        On this page       1. [  The Problem Nobody Talks About ](#the-problem-nobody-talks-about)
2. [  Detecting Backpressure Before It Hurts ](#detecting-backpressure-before-it-hurts)
3. [  Overflow Routing: Shedding Load Gracefully ](#overflow-routing-shedding-load-gracefully)
4. [  Structured Dead-Letter Handling ](#structured-dead-letter-handling)
5. [  Step 1 — Capture rich context on failure ](#step-1-capture-rich-context-on-failure)
6. [  Step 2 — Replay from the dead-letter store ](#step-2-replay-from-the-dead-letter-store)
7. [  Combining the Pieces ](#combining-the-pieces)
8. [  Takeaways ](#takeaways)

  ![Laravel Queues at Scale: Backpressure, Overflow Routing, and Dead-Letter Strategies](https://cdn.msaied.com/221/40080cae015b9b54cba4e665a16dbe7e.png)

  #laravel   #queues   #reliability   #scalability  

 Laravel Queues at Scale: Backpressure, Overflow Routing, and Dead-Letter Strategies 
=====================================================================================

     17 Jun 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   The Problem Nobody Talks About  ](#the-problem-nobody-talks-about)
2. [  02   Detecting Backpressure Before It Hurts  ](#detecting-backpressure-before-it-hurts)
3. [  03   Overflow Routing: Shedding Load Gracefully  ](#overflow-routing-shedding-load-gracefully)
4. [  04   Structured Dead-Letter Handling  ](#structured-dead-letter-handling)
5. [  05   Step 1 — Capture rich context on failure  ](#step-1-capture-rich-context-on-failure)
6. [  06   Step 2 — Replay from the dead-letter store  ](#step-2-replay-from-the-dead-letter-store)
7. [  07   Combining the Pieces  ](#combining-the-pieces)
8. [  08   Takeaways  ](#takeaways)

 The Problem Nobody Talks About
------------------------------

Most Laravel queue tutorials stop at `php artisan queue:work` and a basic Horizon config. That works fine until your queue depth spikes to 50 000 jobs and workers start thrashing, retrying aggressively, and hammering your database. The real craft is in *backpressure*, *overflow routing*, and *dead-letter handling*.

---

Detecting Backpressure Before It Hurts
--------------------------------------

Backpressure means your producers are outpacing your consumers. The earliest signal is queue depth. Poll it on a schedule and react before workers drown:

```php
// app/Console/Commands/MonitorQueueDepth.php
public function handle(Queue $queue): void
{
    $depth = $queue->size('default');

    if ($depth > 10_000) {
        // Emit a metric, fire an alert, or flip a feature flag
        Cache::put('queue:backpressure', true, now()->addMinutes(5));
        Log::warning('Queue backpressure detected', ['depth' => $depth]);
    } else {
        Cache::forget('queue:backpressure');
    }
}

```

Schedule this every minute. Pair it with a Horizon metric or a Prometheus exporter so your alerting fires *before* users notice.

---

Overflow Routing: Shedding Load Gracefully
------------------------------------------

When backpressure is active, route lower-priority work to a slower `overflow` queue instead of blocking the primary one. A middleware on the job itself is the cleanest place to enforce this:

```php
// app/Jobs/Middleware/OverflowRouter.php
class OverflowRouter
{
    public function handle(object $job, callable $next): void
    {
        if (Cache::get('queue:backpressure') && method_exists($job, 'onQueue')) {
            // Re-dispatch to overflow and bail out of current attempt
            dispatch($job)->onQueue('overflow');
            return;
        }

        $next($job);
    }
}

```

Attach it selectively to non-critical jobs:

```php
public function middleware(): array
{
    return [new OverflowRouter];
}

```

In Horizon, give `overflow` a single slow worker so it drains without competing for resources:

```php
// config/horizon.php
'overflow' => [
    'connection' => 'redis',
    'queue' => ['overflow'],
    'balance' => 'simple',
    'processes' => 1,
    'tries' => 3,
],

```

---

Structured Dead-Letter Handling
-------------------------------

Laravel's `failed_jobs` table is a graveyard, not a strategy. Treat it as a first-class queue by wrapping failure logic in a dedicated handler.

### Step 1 — Capture rich context on failure

```php
// app/Jobs/Concerns/RecordsFailureContext.php
trait RecordsFailureContext
{
    public function failed(Throwable $e): void
    {
        DeadLetterEntry::create([
            'job_class' => static::class,
            'payload' => $this->toDeadLetterPayload(),
            'exception' => $e->getMessage(),
            'failed_at' => now(),
        ]);
    }

    abstract protected function toDeadLetterPayload(): array;
}

```

### Step 2 — Replay from the dead-letter store

```php
// app/Console/Commands/ReplayDeadLetters.php
public function handle(): void
{
    DeadLetterEntry::whereNull('replayed_at')
        ->chunkById(100, function ($entries) {
            foreach ($entries as $entry) {
                $job = new $entry->job_class(...$entry->payload);
                dispatch($job)->onQueue('overflow');
                $entry->update(['replayed_at' => now()]);
            }
        });
}

```

This gives you a controlled, auditable replay path instead of blindly running `queue:retry all`.

---

Combining the Pieces
--------------------

The full flow looks like this:

1. A scheduled command monitors queue depth every minute.
2. When depth exceeds a threshold, a cache flag signals backpressure.
3. Non-critical jobs detect the flag via middleware and re-dispatch to `overflow`.
4. Jobs that exhaust retries write structured records to `dead_letter_entries`.
5. An operator-triggered command replays dead letters through `overflow` at a controlled rate.

---

Takeaways
---------

- **Poll queue depth** on a schedule; don't wait for Horizon alerts alone.
- **Job middleware** is the right abstraction for overflow routing — it keeps the logic out of your business code.
- **Dead-letter tables** with rich context beat the default `failed_jobs` table for replay and auditing.
- **Overflow queues** with a single worker act as a pressure valve without dropping work.
- **Chunk-based replay** prevents a flood of retries from re-triggering the same backpressure you just escaped.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-queues-at-scale-backpressure-overflow-routing-and-dead-letter-strategies&text=Laravel+Queues+at+Scale%3A+Backpressure%2C+Overflow+Routing%2C+and+Dead-Letter+Strategies) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-queues-at-scale-backpressure-overflow-routing-and-dead-letter-strategies) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Why not just increase worker count to handle backpressure?        Adding workers helps up to the point where your database or downstream services become the bottleneck. Beyond that, more workers increase contention and can make things worse. Overflow routing buys time without adding load to already-saturated resources. 

      Q02  Is there a risk of a job being dispatched twice with the OverflowRouter middleware?        Yes, if the middleware re-dispatches and then throws before returning, the original job may retry. Guard against this by catching dispatch exceptions and marking the job as released rather than failed, or by making your jobs idempotent using a unique ID stored in cache. 

      Q03  Can this pattern work with database queues instead of Redis?        Yes. Queue depth via `Queue::size()` works with the database driver. The overflow and dead-letter patterns are driver-agnostic. Redis is preferred at scale because depth queries are O(1) rather than a COUNT on a large table. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![PhpStorm 2026.2 Released: Laravel Tool Window, PHP 8.5 Pipe Operator, and AI Agents](https://cdn.msaied.com/505/151a0bba66cc27064e090e69e55d7c92.png) PhpStorm JetBrains PHP 8.5 

### PhpStorm 2026.2 Released: Laravel Tool Window, PHP 8.5 Pipe Operator, and AI Agents

PhpStorm 2026.2 ships a dedicated Laravel tool window with Artisan, error logs, and Laravel Cloud tabs, plus P...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 3 Aug 2026     3 min read  

  Read    

 ](https://msaied.com/articles/phpstorm-20262-released-laravel-tool-window-php-85-pipe-operator-and-ai-agents) [ ![Laravel Doctor: Diagnose Your Laravel App With One Artisan Command](https://cdn.msaied.com/504/d72224689abc7b396bce187535008272.png) Laravel Artisan Health Checks 

### Laravel Doctor: Diagnose Your Laravel App With One Artisan Command

Laravel Doctor is a first-party package announced at Laracon US 2026 that adds an `artisan doctor` command to...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 3 Aug 2026     4 min read  

  Read    

 ](https://msaied.com/articles/laravel-doctor-diagnose-your-laravel-app-with-one-artisan-command) [ ![Livewire v4.3.5 Released: Fix for SFC Detection with PHP Attribute Array Arguments](https://cdn.msaied.com/503/9678ed8dbf5d7a6f4f19ca7694cf241b.png) Livewire Laravel PHP 

### Livewire v4.3.5 Released: Fix for SFC Detection with PHP Attribute Array Arguments

Livewire v4.3.5 ships a targeted bug fix for Single File Component (SFC) detection when PHP attributes contain...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 3 Aug 2026     2 min read  

  Read    

 ](https://msaied.com/articles/livewire-v435-released-fix-for-sfc-detection-with-php-attribute-array-arguments) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
