laravel/pulse
Laravel Pulse is a real-time application performance monitoring tool and dashboard for Laravel apps, surfacing slow requests, usage, and server health so you can spot bottlenecks fast.
Laravel Pulse is a first-party, database-backed performance dashboard, not a full APM platform. The fastest useful setup is:
Install the package:
composer require laravel/pulse
Publish the config and migrations:
php artisan vendor:publish --provider="Laravel\Pulse\PulseServiceProvider"
php artisan migrate
Immediately restrict dashboard access in AppServiceProvider::boot():
use Laravel\Pulse\Facades\Pulse;
Pulse::auth(fn ($request) =>
app()->environment('local') ||
$request->user()?->isAdmin()
);
Start the long-running workers your setup needs. For server CPU/memory metrics, run php artisan pulse:check under Supervisor on each server. If you use Redis ingest, run php artisan pulse:work under Supervisor too. A one-off cron invocation will not give you the continuous server metrics Pulse expects.
Visit /pulse and start with the Slow Requests, Slow Queries, Exceptions, and Queues cards.
The first place to look after installation is config/pulse.php. That file controls recorders, thresholds, sampling, ignore patterns, ingest/storage drivers, trimming, dashboard path/middleware, and cards. The first real use case should be post-deploy triage: identify slow endpoints, slow or repeated queries, failing jobs, and exception spikes before reaching for custom cards.
Use Pulse as an operational triage dashboard. The strongest day-to-day pattern is a short loop: deploy, watch exceptions and slow requests, drill into slow queries, then fix the endpoint or job. Pulse is good at pointing you toward a problem; it is not designed for distributed tracing or deep profiling.
Configure recorders deliberately. Enable only cards/recorders the team will act on. Tune thresholds before lowering sample rates; a threshold that is too low creates noise, while aggressive sampling makes cards statistically misleading. Use ignore patterns for health checks, /pulse, Horizon/Telescope routes, and other high-volume non-business traffic. Slow request, query, and job thresholds can be customized per environment, including regex-based matching for noisy paths.
A typical recorder config pattern looks like:
'recorders' => [
Laravel\Pulse\Recorders\SlowRequests::class => [
'enabled' => true,
'threshold' => 500,
'sample_rate' => 1,
'ignore' => ['#^/health$#', '#^/pulse#'],
],
Laravel\Pulse\Recorders\SlowQueries::class => [
'enabled' => true,
'threshold' => 100,
'sample_rate' => 1,
],
],
Monitor queues and jobs alongside requests. Pulse is especially useful when a queue-backed app slows down: slow jobs, queue sizes, and exceptions in one dashboard make it easier to distinguish app code problems from worker capacity problems. Keep Horizon or your queue supervisor for operational control; use Pulse for the performance view.
Add custom metrics sparingly. For business-specific visibility, use Pulse::record() and Pulse::set() from Laravel\Pulse\Facades\Pulse, or write a custom recorder. Keep cardinality low: use stable route patterns, job classes, or IDs rather than raw URLs, emails, or unbounded values. Never record inside tight loops without sampling. Custom cards are best for a small number of durable questions, such as failed imports, active tenants, or external API latency.
Use Redis ingest for busier applications. Pulse’s default database ingest is fine for low-traffic apps, but high write volume can add load to the primary database. Redis ingest plus pulse:work decouples capture from storage. Consider a dedicated database connection for Pulse storage so dashboard queries and ingest writes do not compete with application traffic. If you hit ingest upsert failures on certain database setups, check the use_upsert_alias option added in recent releases.
Run server checks per server. In a multi-server setup, run pulse:check on every server and ensure hostnames are stable. Ephemeral containers can produce noisy or misleading server cards; either disable the Servers recorder or give instances predictable names. Recent versions also support sorting options on the Server card.
Treat environments differently. Keep Pulse enabled and useful in staging, but disable it in test/CI (PULSE_ENABLED=false) to avoid unnecessary database writes. In production, combine a restrictive auth callback with a custom path or domain/middleware if the dashboard should not live at the default /pulse.
Pulse::auth, you risk leaking request paths, exception traces, job names, and query details.pulse:check is not running under Supervisor. Missing or stale data with Redis ingest usually means pulse:work is not running.pulse:check and pulse:work are long-running processes. Use Supervisor with autorestart, and avoid running Telescope in the same process where possible; historical memory-leak issues have been fixed, but lightweight workers are still safer.How can I help you explore Laravel packages today?