System Health
Live diagnostic cards for database, Redis, S3, queue, scheduler, and PHP.
Overview
System Health runs connectivity and runtime checks and shows an overall verdict (healthy / degraded / critical).
Where it lives
Route: /admin/settings/system-health (admin.settings.system-health)
Open Admin → System → System Health. Requires admin access. Retrying failed jobs requires settings.manage.
Key workflows
- Checks run on mount; auto-refresh every 30s (pause/resume) plus manual Refresh
- Cards cover PostgreSQL, Redis, S3, queue (with failed-job expand + retry), scheduler heartbeat, and PHP limits
- Remediation text can be copied from cards
From the command line
php artisan doctor runs the same checks without a browser — useful during install, in CI, and when the app will not boot far enough to serve the admin page.
php artisan doctor # full report
php artisan doctor --only=signals-queue # one group
php artisan doctor --fix # apply the offered repairs
php artisan doctor --format=json # machine-readable, for CI
The report combines two sets of diagnostics:
| Source | Covers |
|---|---|
| Laravel Doctor built-ins | App key, .env, PHP version and extensions, Composer autoload and lockfile, config caching, migrations pending, storage writability and permissions, plain connection reachability for database/cache/queue/session, debug mode, security audit |
| Signals diagnostics | The subsystems this application depends on, probed the way the System Health page probes them |
The Signals diagnostics, by group:
| Group | Checks |
|---|---|
signals-database |
PostgreSQL answers, and reports its version, size, and connection count |
signals-settings |
The settings table exists, is readable, and holds entries |
signals-redis |
Redis answers when it backs the cache, queue, or sessions — skipped otherwise |
signals-storage |
S3 accepts a write, read-back, and delete — skipped on local disk |
signals-queue |
Named queues are draining and no jobs have failed |
signals-scheduler |
The schedule:run heartbeat is recent, so cron is still firing |
Exit code is non-zero when a diagnostic fails, so it can gate a deployment. Use --fail-on=warn to treat warnings as failures too, or --fail-on=never to report without failing.
Adding your own checks
Plugins register diagnostics through the registrar, and they appear in the same report:
$registrar->doctorCheck(AcmeIntegrationIsConfigured::class);
The class must extend Laravel\Doctor\Diagnostic. Scaffold one with php artisan make:diagnostic. See Plugins.