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

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

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

  [ home ](https://www.msaied.com)    [ articles ](https://www.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%2Fwww.msaied.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%2Fwww.msaied.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://www.msaied.com/articles) 

 [ ![Laravel Signed Routes and Temporary URLs: Secure Link Patterns Beyond the Basics](https://cdn.msaied.com/222/1bcb5bdf8f9b2490d0898cfa28479582.png) laravel security routing 

### Laravel Signed Routes and Temporary URLs: Secure Link Patterns Beyond the Basics

Signed routes are more than a password-reset trick. Learn how to build expressive, tamper-proof URL workflows...

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

 17 Jun 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-signed-routes-and-temporary-urls-secure-link-patterns-beyond-the-basics) [ ![Read Model Projections in Laravel Without Full Event Sourcing](https://cdn.msaied.com/220/967a0feff7428e3f2a68209163804743.png) laravel architecture eloquent 

### Read Model Projections in Laravel Without Full Event Sourcing

Learn how to build fast, queryable read models in Laravel using database projectors and Eloquent—without commi...

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

 17 Jun 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/read-model-projections-in-laravel-without-full-event-sourcing) [ ![Laravel Observers vs. Model Events: Choosing the Right Hook for Side Effects](https://cdn.msaied.com/219/c16eb6ef2428da6f1d4a18025bf6c15d.png) laravel eloquent observers 

### Laravel Observers vs. Model Events: Choosing the Right Hook for Side Effects

Model events and observers both react to Eloquent lifecycle changes, but picking the wrong one creates tangled...

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

 16 Jun 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-observers-vs-model-events-choosing-the-right-hook-for-side-effects) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.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://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.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)
