Laravel Queue Backpressure &amp; Dead-Letter Queues | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. Laravel Queues at Scale: Backpressure, Dead-Letter Queues, and Graceful Degradation

 Laravel Queues at Scale: Backpressure, Dead-Letter Queues, and Graceful Degradation
====================================================================================

 Beyond basic queue workers: learn how to implement backpressure signals, dead-letter queues, and graceful degradation strategies so your Laravel queue system survives traffic spikes without data loss.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 28 Aug 2026 · Updated 28 Aug 2026 · 3 min read

ShareCopy linkCopied

 ![Laravel Queues at Scale: Backpressure, Dead-Letter Queues, and Graceful Degradation](https://cdn.msaied.com/602/fcffaaa5442f84486d6059eaa4106d26.png) 

  On this page +1. [The Problem Nobody Talks About](#the-problem-nobody-talks-about)
2. [Backpressure: Slowing the Producer](#backpressure-slowing-the-producer)
3. [Measuring Queue Depth Before Dispatching](#measuring-queue-depth-before-dispatching)
4. [Dead-Letter Queues: Isolating Poison Pills](#dead-letter-queues-isolating-poison-pills)
5. [Routing Exhausted Jobs to a DLQ](#routing-exhausted-jobs-to-a-dlq)
6. [Graceful Degradation: Shedding Load Intentionally](#graceful-degradation-shedding-load-intentionally)
7. [Observability Glue](#observability-glue)
8. [Key Takeaways](#key-takeaways)

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

Most Laravel queue tutorials stop at `php artisan queue:work`. That is fine for low-traffic apps, but once you have burst traffic — a flash sale, a viral email campaign, a cron that fans out 50,000 jobs — you need three things your default setup does not give you: **backpressure**, **dead-letter isolation**, and **graceful degradation**.

---

Backpressure: Slowing the Producer
----------------------------------

Backpressure means the producer (the HTTP request or command that dispatches jobs) slows down when the queue is already overwhelmed. Without it, a spike fills Redis memory and workers fall further behind.

### Measuring Queue Depth Before Dispatching

```php
use Illuminate\Support\Facades\Redis;

final class ThrottledDispatcher
{
    private const MAX_DEPTH = 5_000;

    public function dispatch(ShouldQueue $job, string $queue = 'default'): void
    {
        $depth = (int) Redis::llen('queues:' . $queue);

        if ($depth >= self::MAX_DEPTH) {
            throw new QueueSaturatedException(
                "Queue '{$queue}' depth {$depth} exceeds limit."
            );
        }

        dispatch($job)->onQueue($queue);
    }
}

```

In an HTTP context you can catch `QueueSaturatedException` and return HTTP 503 with a `Retry-After` header. For internal fan-out commands, log the saturation and skip non-critical jobs.

---

Dead-Letter Queues: Isolating Poison Pills
------------------------------------------

Laravel's `failed_jobs` table is a dead-letter store, but it is a single flat table. When a job fails repeatedly it keeps consuming worker time on retries. A better pattern is a dedicated **dead-letter queue** that workers never touch automatically.

### Routing Exhausted Jobs to a DLQ

```php
use Throwable;
use Illuminate\Queue\InteractsWithQueue;

class ProcessOrderExport implements ShouldQueue
{
    use InteractsWithQueue;

    public int $tries = 3;
    public int $backoff = 60;

    public function failed(Throwable $e): void
    {
        // Re-queue onto a monitored DLQ instead of only logging
        dispatch(new DeadLetterJob(
            originalClass: static::class,
            payload: $this->order->id,
            reason: $e->getMessage(),
        ))->onQueue('dead-letter');
    }
}

```

`DeadLetterJob` itself never retries (`$tries = 1`) and simply persists a record to a `dead_letter_events` table with full context. A Filament resource or a nightly alert then surfaces these for human review.

---

Graceful Degradation: Shedding Load Intentionally
-------------------------------------------------

Not every job is equal. Sending a transactional email is critical; regenerating a report thumbnail is not. Tag jobs with a priority tier and shed low-priority work under load.

```php
enum QueueTier: string
{
    case Critical = 'critical';
    case Standard = 'default';
    case Background = 'background';
}

class RegenerateThumbnail implements ShouldQueue
{
    public string $queue = QueueTier::Background->value;
    public int $tries = 1; // shed silently on failure
}

```

In `config/horizon.php` (or your supervisor config) assign more workers to `critical`, fewer to `background`, and set `--stop-when-empty` on background workers during incidents:

```php
'environments' => [
    'production' => [
        'supervisor-critical' => [
            'queue' => 'critical',
            'processes' => 10,
            'balance' => 'auto',
        ],
        'supervisor-background' => [
            'queue' => 'background',
            'processes' => 2,
            'balance' => 'simple',
        ],
    ],
],

```

During a degraded incident you can temporarily scale `supervisor-background` processes to zero via the Horizon API or a feature flag without touching critical workers.

---

Observability Glue
------------------

None of this works without metrics. Emit a gauge from a scheduled command:

```php
Schedule::call(function () {
    foreach (['critical', 'default', 'background', 'dead-letter'] as $q) {
        $depth = (int) Redis::llen('queues:' . $q);
        Metric::gauge('queue.depth', $depth, ['queue' => $q]);
    }
})->everyMinute();

```

Alert when `dead-letter` depth grows or `critical` depth exceeds your SLA threshold.

---

Key Takeaways
-------------

- **Backpressure** protects Redis and gives callers a clear signal to back off; return 503 from HTTP, skip from CLI.
- **Dead-letter queues** isolate poison-pill jobs so they do not starve healthy workers on retries.
- **Tier your queues** and assign worker counts per tier so you can shed background load without touching critical paths.
- **Metrics on queue depth** per named queue are non-negotiable in production; alert before the backlog becomes a crisis.
- Keep `DeadLetterJob` simple and non-retrying — its only job is durable persistence for human triage.

- [laravel](https://www.msaied.com/public/articles?search=laravel)
- [queues](https://www.msaied.com/public/articles?search=queues)
- [reliability](https://www.msaied.com/public/articles?search=reliability)
- [backend](https://www.msaied.com/public/articles?search=backend)
- [scalability](https://www.msaied.com/public/articles?search=scalability)

 Frequently asked questions 
---------------------------

  Does Laravel's built-in failed\_jobs table replace a dead-letter queue?It covers the storage part, but failed\_jobs does not prevent exhausted jobs from consuming retry attempts before landing there. A dedicated DLQ pattern routes jobs there immediately after the final failure, keeping your main queues clean and giving you a single place to monitor and replay problematic jobs.

   How do I replay jobs from a dead-letter queue safely?Store enough context in your dead\_letter\_events table (original class, serialized payload, failure reason, timestamp) to reconstruct and re-dispatch the original job. Add a Filament action or artisan command that deserializes the payload, instantiates the job, and dispatches it back to the original queue — optionally with a flag to skip the DLQ on the next failure so you can investigate interactively.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

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

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articlePessimistic Locking in Laravel Eloquent with refreshForUpdate()](https://www.msaied.com/public/articles/pessimistic-locking-in-laravel-eloquent-with-refreshforupdate) [Next articleLaravel Starter Kits Now Ship with Vite+](https://www.msaied.com/public/articles/laravel-starter-kits-now-ship-with-vite)  

   On this page
-------------

1. [The Problem Nobody Talks About](#the-problem-nobody-talks-about)
2. [Backpressure: Slowing the Producer](#backpressure-slowing-the-producer)
3. [Measuring Queue Depth Before Dispatching](#measuring-queue-depth-before-dispatching)
4. [Dead-Letter Queues: Isolating Poison Pills](#dead-letter-queues-isolating-poison-pills)
5. [Routing Exhausted Jobs to a DLQ](#routing-exhausted-jobs-to-a-dlq)
6. [Graceful Degradation: Shedding Load Intentionally](#graceful-degradation-shedding-load-intentionally)
7. [Observability Glue](#observability-glue)
8. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
