How to monitor Laravel in production (without Datadog)
Your Laravel app is not slow because you lack a six-figure observability contract. It is slow because PHP-FPM ran out of workers at 2:14pm, the queue backlog hit forty thousand jobs while Horizon was down, and nobody noticed until the checkout page returned a 502. Datadog would have shown you beautiful graphs of the incident you already knew about from angry Slack messages. What you actually needed was monitoring tied to repair, not more dashboards.
Most Laravel teams running on a single VPS or a small Forge fleet do not need distributed tracing across fifty microservices. They need the Linux layer under Laravel to stay healthy: PHP-FPM pools, nginx, Redis, MySQL connections, supervisor workers, disk space, and deploy correlation. Skip the consumption-priced SaaS until you have a dedicated platform team. Start with signals that predict revenue loss.
What breaks in production (and what customers feel first)
The failure modes are predictable. PHP-FPM pool exhaustion shows up as intermittent 502/504 errors from nginx while CPU looks fine — every worker is busy or stuck. Queue worker death means emails stop sending, webhooks pile up, and Horizon shows a red status nobody is watching. Deploy regressions push broken .env keys or migration failures live because CI passed but production health was never checked. Disk pressure fills /var/log or release directories until MySQL cannot write temp tables and everything grinds to a halt.
Customers do not care about your Grafana panels. They care that login works, checkout completes, and password resets arrive. Monitor symptoms they feel, not every metric your host exposes.
Diagnosis without a SaaS bill
SSH still works. Use it deliberately before you automate.
Check PHP-FPM status. On most Ubuntu/Debian installs:
sudo systemctl status php8.3-fpm
sudo tail -f /var/log/php8.3-fpm.log
Look for server reached pm.max_children setting — that is pool saturation, not a mystery bug. Inspect the slow log if you enabled it:
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
For queues, confirm supervisor is running and Horizon is reachable:
sudo supervisorctl status
php artisan horizon:status
Correlate timestamps with deploys. If 502s started two minutes after forge deploy, you are debugging today's release, not infrastructure drift. Check disk before you blame code:
df -h
df -i
Inode exhaustion is silent until it is catastrophic.
Manual fixes that actually work
When FPM is saturated, you have three levers: reduce per-request memory, increase pm.max_children within available RAM, or fix the slow endpoint. A typical pool snippet in /etc/php/8.3/fpm/pool.d/www.conf:
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500
Never raise max_children without calculating total memory — use the PHP-FPM calculator before you swap one error for an OOM kill.
Watch Laravel logs in storage/logs/laravel.log for repeated exceptions after deploy — a misconfigured cache driver can peg workers without obvious nginx errors. Enable LOG_LEVEL=warning in production to cut noise but keep stack traces for 500s.
For stuck queues:
sudo supervisorctl restart laravel-worker:*
php artisan queue:restart
If Horizon will not start, check Redis connectivity and failed jobs table — a poison message looping crash-restarts workers.
Deploy safety means post-deploy smoke tests, not just green CI. Hit /health, confirm queue depth is stable, and watch error rates for ten minutes before you declare victory.
Schedule a weekly five-minute review: FPM slow log samples, Horizon metrics, disk trend, failed job count. Consistency beats heroic debugging.
Uptime monitors are necessary but insufficient
External ping services prove the homepage returned 200 from one vantage point. They do not prove checkout works, API auth succeeds, or background jobs run. Layer synthetic checks on business-critical routes and pair them with process-level metrics on the box itself.
If you are on Forge or DigitalOcean, enable their alerts — then supplement with FPM and queue depth. See deploy Laravel on DigitalOcean for a post-launch checklist.
What to skip early
Full OpenTelemetry instrumentation across every Eloquent query. Log aggregation at gigabyte scale. Custom Slack bots that ping #devops when CPU crosses 70%. These create noise and maintenance debt. Start with host plus process health, deploy markers, and alerts that page humans only when automation cannot fix the problem.
Where Reflex fits
Reflex installs reflexd on your server — Forge, DigitalOcean, bare EC2 — and ships metrics for PHP-FPM, queues, disk, memory, and deploy events without a per-host Datadog tax. The Brain runs playbooks for failures Laravel teams see weekly: restart exhausted FPM pools, clear disk pressure, bounce stuck workers, and correlate regressions with Pipeline deploy markers.
You get repair audit trails your clients understand, not just graphs. Start a trial, read how the Brain repair cycle works, or compare Reflex vs Datadog if you are evaluating observability spend. For Laravel-specific depth, see the Laravel monitoring guide. Agencies managing multiple client apps should also review Reflex for agencies.
Start small: one production server, reflexd installed, alert on FPM and queues only. Expand to deploy gating and auto-repair after a week of baseline metrics — crawling before sprinting beats another abandoned monitoring project.
Ready to stop firefighting your servers?
Try Reflex free for 14 days.