← Back to blog

Why Generic Cron Monitors Miss Laravel Horizon Failures

Most Laravel developers set up a cron monitor by pinging a URL every time a job runs. Cronitor, Better Stack heartbeats, or Forge Heartbeats — they all work the same way. The job fires, it hits a URL, the monitor marks it green.

The problem: that’s not how Horizon failures actually happen.

The real failure modes

When your Horizon setup breaks in production, it usually looks like one of these:

1. A supervisor process dies, but Horizon “stays running”

Horizon is a supervisor of supervisors. If you have two supervisor groups — say, one for default queue and one for emails — and one of them crashes, Horizon’s status still shows “running” because the other supervisor is alive. Your email queue is now dead. Generic monitors have no way to know this.

2. Horizon gets paused accidentally

php artisan horizon:pause is a valid command, sometimes run during deployments. If it never gets horizon:continue called after, your queues silently stop processing. No cron missed a heartbeat because the scheduled commands are separate from Horizon workers. Everything looks fine.

3. The failed job rate spikes gradually

Jobs fail. That’s normal. But when the failure rate climbs from 0.2/min to 8/min over two hours, you want to know before it becomes 40/min and your users start screaming. Generic monitors can’t see job failure rates — they only know if a URL was pinged.

What actually needs to be monitored

For a Laravel app with Horizon, you need to watch:

None of these are available to an HTTP ping monitor. They require reading Horizon’s internal Redis keys.

How Crontinel approaches this

Crontinel’s Laravel package reads Horizon’s Redis keys directly — the same data that the Horizon dashboard shows you, but piped into configurable alerts. It also hooks into Laravel’s ScheduledTaskFinished and ScheduledTaskFailed events to track every cron run with its exit code and duration.

The result: you get alerted when a supervisor goes down, not after a customer notices their invoice wasn’t sent.

The OSS package is free forever. If you want multi-app dashboards and a hosted view, that’s what the SaaS is for.

composer require harunrrayhan/crontinel
php artisan crontinel:install