Skip to main content
All posts
· 5 min read

Why Generic Uptime Monitors Miss Laravel Queue Failures

Your uptime monitor shows green while your queue depth climbs to 5,000 and customers wait. Here's why HTTP pings can't see Laravel queue failures, and what actually works.

Your Laravel app responds to HTTP requests in milliseconds. Your queue workers process jobs asynchronously. These are two different systems running in parallel, and most monitoring only watches the first one.

A standard uptime monitor - Pingdom, Better Stack, UptimeRobot, Cronitor - sends an HTTP request to your domain and declares everything healthy if it gets a 200. That tells you your web server is running. It tells you nothing about what happens inside your queue.

What the monitor sees vs. what your users experience

When a queue worker crashes and 3,000 jobs back up in Redis, the HTTP layer doesn’t change. example.com still responds to requests. Your PHP-FPM pool still handles traffic. The Laravel scheduler still fires. The queue is just quietly not processing anything.

This is the failure mode that generic uptime monitors completely miss.

The sequence

  1. 08:00 - Supervisor default crashes. Horizon reports it as “running” because the Horizon process is alive. The queue workers for the default queue are gone.
  2. 08:01 - Your generic uptime monitor checks example.com, gets 200, logs “all clear.”
  3. 08:15 - Crontinel sees that the default supervisor has reported no processed jobs in 15 minutes. Alert fires.
  4. 09:30 - A customer asks why they haven’t received their order confirmation. You find out about the crash from a support ticket, not an alert.
  5. 09:35 - You manually restart the queue workers, 5,000 jobs process, customers get delayed emails.

The generic monitor never flagged anything. The queue backed up for 90 minutes. Your users waited.

The difference between HTTP monitoring and queue monitoring

HTTP monitoring checks if the outside of your system is working. Queue monitoring reads the inside - the actual state of your job processing, from the perspective of your Laravel app itself.

ScenarioHTTP monitorCrontinel
Web server downDetects itDoesn’t detect it
Queue workers crashedShows greenAlerts immediately
Horizon supervisor pausedShows greenAlerts immediately
Database queue backing upShows greenAlerts with depth + oldest age
Scheduler running but jobs silently skippedShows greenDetects late runs

The two approaches are complementary. You need HTTP monitoring for your web layer. But if you run Laravel queues and you only have HTTP monitoring, you’re flying blind on the most critical part of your app.

What queue monitoring actually requires

Monitoring Laravel queues properly isn’t about polling an HTTP endpoint. It’s about reading the same internal state your app uses.

Laravel Horizon stores state in Redis - supervisor status, job counts, failed job flags, process IDs. That’s the data source. A monitor that only checks your web server’s HTTP response can’t see it.

Crontinel reads those Redis keys directly:

// Crontinel monitors these signals:
Redis::get("horizon:supervisor_status:{$name}")
Redis::llen("horizon:{$connection}:{$queue}")
Redis::get("horizon:failed_jobs")

No HTTP polling. No external agent. Just direct Redis reads from inside your infrastructure.

The real-world cost

Queue failures aren’t theoretical. A billing queue that stops processing means:

  • Subscriptions don’t renew
  • Invoices don’t send
  • Customers don’t get order confirmations
  • Background jobs that should have run today are sitting in Redis, waiting

When the queue finally recovers, you may not even know jobs were missed unless you’re explicitly tracking queue depth and oldest-job age.

The generic uptime monitor doesn’t know any of this happened. When you rebuild your queue workers and the backlog clears, the HTTP monitor never even noticed there was a problem.

What works

Queue monitoring that actually catches failures needs to:

  1. Read Horizon’s Redis keys directly - not just poll an HTTP endpoint
  2. Alert on supervisor pause state - not just check if the process is alive
  3. Track queue depth and oldest-job age - not just count completed jobs
  4. Record failed jobs per minute - not just log errors somewhere
  5. Alert on late cron runs - the scheduler fired but no jobs executed

That’s the difference between “the web server responded” and “the queue is actually working.” Your users feel the queue. Your generic monitor doesn’t.


Crontinel monitors Laravel queues from the inside - supervisor state, queue depth, oldest-job age, and failed job rates. Try it free.

See also

blog
Laravel Cron vs Queue Monitoring — What's the Difference?

Generic uptime monitors miss scheduler failures. Queue depth monitors miss Horizon supervisor death. Here's why you need both, and what each one actually covers.

blog
Why Generic Cron Monitors Miss Laravel Horizon Failures

Cronitor tells you a job ran. It can't tell you your Horizon supervisor is paused. Here's what's actually going on under the hood.

blog
Laravel Horizon Workers Idle While Jobs Pile Up? 6 Causes (And Fixes)

Horizon shows workers as running while 2,000 jobs pile up untouched. Here are the 6 real causes — and how to fix each one fast.

use cases
horizon:purge Not Cleaning Jobs? Detect Silent Failures

horizon:purge can exit with code 0 while Redis memory keeps climbing. Here is exactly how to tell if it is actually working — and how to get alerted when it isn't.