Skip to main content
← All use cases

Laravel Horizon Monitoring for Paused Supervisors, Queue Depth, and Failed Jobs

Laravel Horizon gives you a real-time dashboard for your queue workers. It’s good for debugging. It is not a pager.

If you’re searching for Laravel Horizon monitoring, this page covers the signals that matter most: paused supervisors, queue depth, oldest job age, and failed-job spikes.

A Horizon supervisor can pause at 2am. Jobs can pile up to thousands. Customers can start seeing delayed responses. And the dashboard will only help if somebody is already looking at it.

What Horizon writes to Redis

Horizon stores its operational state in Redis using well-defined key patterns. The supervisor states, process counts, queue metrics, and job history are all there. Crontinel reads them directly, which means:

Signals Crontinel monitors

Supervisor status

Every Horizon supervisor has a status in Redis: running, paused, or stopped. Crontinel polls this for each supervisor and alerts when any supervisor moves out of the running state.

A paused supervisor is a common failure mode during deployments. A php artisan horizon:terminate that doesn’t restart cleanly leaves the supervisor paused. Crontinel catches this within seconds.

Queue depth

Crontinel reads the pending job count per queue and alerts when depth exceeds a configured threshold. You set separate thresholds per queue:

CRONTINEL_QUEUE_DEPTH_THRESHOLD=100          # default for all queues
CRONTINEL_QUEUE_DEPTH_INVOICES=25            # tighter threshold for billing queue

This lets you be aggressive about billing queue alerts without getting paged for a temporarily backed-up notification queue.

Oldest job age

A queue with 50 jobs and an oldest job age of 2 minutes is fine. A queue with 50 jobs and an oldest job age of 40 minutes is not. Crontinel tracks both and alerts when the oldest job age exceeds your threshold, separate from depth.

Failed job rate

Horizon tracks failed jobs in a sorted set. Crontinel computes a rolling failure rate (failures per minute over the last 5 minutes) and alerts when it exceeds a configured threshold. A spike in failures often indicates a broken external dependency before the queue depth metric catches it.

Setup

Crontinel’s Horizon monitoring activates automatically when Horizon is detected. The package checks for Horizon’s presence in vendor/ and starts reading Redis state on the same polling cycle as cron recording.

composer require crontinel/laravel
php artisan crontinel:install

Configure your thresholds in .env:

CRONTINEL_HORIZON_ENABLED=true
CRONTINEL_HORIZON_SUPERVISOR_ALERT=true
CRONTINEL_QUEUE_DEPTH_THRESHOLD=100
CRONTINEL_FAILED_JOBS_PER_MINUTE=5

Alert example

When a supervisor pauses, Crontinel fires an alert to your configured channel. A Slack message looks like:

[Crontinel] Horizon supervisor "default" is paused
App: production-api
Paused at: 2:14am UTC
Queue depth (emails): 847 jobs
Oldest job: 12 minutes

You get the supervisor name, the queue state at the time of the alert, and a direct link to your Crontinel dashboard.

Horizon monitoring vs Horizon dashboard

The Horizon dashboard shows you current state. It’s useful when you’re already debugging a problem. Crontinel tells you when a problem starts, so you’re not waiting for a user report before you check the dashboard.

These two tools serve different moments in the incident lifecycle. Use both.

Team access

Organization members can view connected apps in the shared dashboard when their access allows it. Engineers on call can check Horizon health without direct Redis access.

Common Horizon failure scenarios Crontinel catches

All of these produce Redis state changes that Crontinel detects without any application-level ping or custom command.

See also

Start monitoring in minutes

Free for one app. No account needed to install and test locally.

composer require crontinel/laravel
php artisan crontinel:install
Get early access