How to monitor Laravel
Monitor a Laravel app with the built-in /up route or Spatie's Laravel Health JSON endpoint, which Vigil reads check by check. Watch queue workers and the failed_jobs count, make the scheduler ping a heartbeat with pingOnSuccess, and send exceptions to a Sentry-compatible endpoint. The server agent watches PHP-FPM, Supervisor and the logs.
What can go wrong with Laravel
- Queue workers stopped.
queue:workdied or was not restarted after a deploy (workers keep old code in memory untilqueue:restart). Jobs pile up or run stale code. - Failed jobs pile up. Jobs that exhaust their tries go to
failed_jobsand stay there silently. - Scheduler not running. The single
* * * * * php artisan schedule:runcron entry is missing on a new server, so every scheduled task stops at once. - Storage and cache. Wrong permissions on
storage/, or a staleconfig:cacheafter changing.env, give 500s that only show in the log. - PHP-FPM saturated. All
pm.max_childrenare busy; the FPM log saysserver reached pm.max_children settingand the web server returns 502/504.
The signals that matter, with alert thresholds
| Signal | Alert when | Why it matters |
|---|---|---|
| Laravel Health checks | any failed or warning | Database, cache, disk, queue, schedule, per check. |
| Uptime of /up and key pages | non-2xx twice | App does not boot or serve. |
| failed_jobs count | > 0 new per hour | Jobs giving up. |
| Scheduler heartbeat | late | No scheduled tasks run. |
| max_children warnings in the FPM log | any | Capacity. |
| New exceptions | first occurrence | Bugs. |
Thresholds are starting points. Tune them after a week of data: an alert nobody acts on should be raised or removed.
How to check Laravel by hand
php artisan about
php artisan queue:failed
php artisan schedule:list
sudo supervisorctl status php artisan horizon:status
sudo grep max_children /var/log/php*-fpm.log | tail
How to watch Laravel with Vigil
- Install
spatie/laravel-health, register its checks, expose its JSON results endpoint (or its Oh Dear endpoint) and create an App health monitor on it in New monitor. Vigil reads that format natively and sends a configured secret asoh-dear-health-check-secret. Each check alerts on its own. - Add an Uptime monitor on
/up(Laravel 11's built-in route) and on the pages that matter. - Give the scheduler a heartbeat: create a Heartbeat and chain
->pingOnSuccess('https://puzaricloud.in/ping/<token>')on an important scheduled task (or on a trivial every-minute task to proveschedule:runitself runs). - Install the server agent, add
php8.3-fpm(your version) andsupervisorto the services to watch, and the failed-jobs command below with the limitlaravel_failed_jobs = 1. - Create a project under Errors and set its DSN as
SENTRY_LARAVEL_DSNforsentry/sentry-laravel. For traces, the OpenTelemetry PHP SDK sends to the OTLP endpoint (quick start).
{
"commands": {
"laravel_failed_jobs": "cd /var/www/app && php artisan tinker --execute=\"echo DB::table('failed_jobs')->count();\""
},
"log_watch": [
{"name": "fpm_max_children", "path": "/var/log/php8.3-fpm.log", "pattern": "max_children"}
]
}
Every alert goes to the channels you pick: email, Slack, Telegram, Discord, Microsoft Teams, Pushover, webhooks or on-call paging. Failures are confirmed by a second check before anyone is woken up.
Laravel monitoring FAQ
Is /up enough?
It proves the framework boots, nothing more: it does not touch the database, cache or queue. Use it for uptime and Laravel Health for the dependencies.
How do I know the scheduler runs on every server?
Run it on one server only (or use onOneServer()), and give that a heartbeat. If you run it on several, one heartbeat per server tells you which one stopped.
Does Horizon change anything?
Horizon manages the workers and shows metrics. Watch the horizon process or Supervisor program, keep the failed-jobs limit, and add Horizon's status as a Laravel Health check.