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.
Architecture fit
Laravel Pulse is a first-party, application-embedded APM: it runs inside the Laravel process rather than as a sidecar or external SaaS agent. That makes it a strong fit for Laravel-only estates and a poor fit as a general observability backbone.
| Dimension | Assessment |
|---|---|
| Install model | Composer package + auto-discovered service provider; no daemon, no sidecar, no external account |
| Extension surface | Config-published cards, custom recorders, Pulse::record() / Pulse::set() public API, viewPulse gate |
| Runtime shape | Livewire dashboard at /pulse; ingest drivers (database / Redis / null); two CLI workers (pulse:work for ingest+trim, pulse:check for server stats) |
| Data plane | Metrics land in your own database (default) or Redis buffer — no data leaves your infrastructure |
| Boundary | Laravel HTTP, queue, cache, DB, and outgoing-request instrumentation only; no distributed tracing, no cross-language, no host/infra monitoring |
The Dependents: 0 and 49.95 opportunity signals are metric artifacts, not adoption signals: Pulse is installed at the application layer, not consumed as a library, so it will never accumulate Packagist dependents the way a utility package does. Judge it on the download badge and first-party status instead.
Integration feasibility — high, with two real work items
Greenfield: composer require laravel/pulse, publish config, run the pulse_* migrations, register the gate, schedule the two commands. Realistically half a day for a competent Laravel engineer, excluding review and dashboard tuning.
The two non-trivial items are not installation but operation:
/pulse exposes exception traces, slow-query SQL, request paths, and user identifiers. The viewPulse gate defaults to local-only; leaving it permissive in staging/production is the single largest risk in this package.pulse_* tables unless pulse:work is running under a supervisor. A misconfigured or crashed worker silently produces unbounded table growth on your primary database.Technical risk
| Risk | Severity | Mitigation |
|---|---|---|
| Write amplification on the primary DB under high RPS | High | Set sampling rates per recorder; switch to Redis ingest; use a dedicated DB connection |
Dashboard data exposure via weak viewPulse gate or public route |
High | Gate bound to an explicit admin role; restrict route by middleware/VPN; verify in a non-prod environment first |
Untrimmed pulse_* tables |
Medium | Supervised pulse:work + retention config; add a row-count monitor |
| Server metrics silently blank | Medium | Supervised pulse:check; alert on stale pulse_servers rows |
| Livewire version constraints conflicting with the host app | Medium | The 1.x line already had to pin against an unpatched Livewire; treat Livewire as a shared dependency to be version-managed |
| Sensitive data captured in slow-query/outgoing-request cards (bindings, URLs) | Medium | Use ignore lists and threshold regexes; note that credential stripping in outgoing requests was itself a patched bug (v1.8.0) |
| Redis ingest deserialization trust boundary | Medium | Stay current — unserialize was restricted in v1.7.0 |
| No native alerting | Medium | Pulse is a dashboard, not an alerting product; plan for scheduled threshold checks or a separate alerting path |
Key questions to resolve before committing
Stack fit
Best fit: a Laravel 10–13 monolith or a small number of Laravel services, on PHP 8.1–8.5, with MySQL/Postgres/SQLite and phpredis, Relay, or Predis available. Weak fit: polyglot estates, heavy service-mesh topologies, or teams expecting trace-level correlation across services. Pulse aggregates; it does not trace.
Positioning recommendation: adopt Pulse as the application-tier instrument, and explicitly decide what, if anything, retains the infrastructure-tier and cross-service view. If a commercial APM is already licensed, Pulse is a faster, cheaper, first-party companion for day-to-day Laravel debugging rather than a rip-and-replace.
Migration path
Compatibility considerations
Pin to a known-good 1.x release and track the changelog; the project ships frequently and several releases are compatibility fixes (Laravel 12/13, PHP 8.4/8.5, Livewire 4, Redis prefix/serialization changes in Laravel 13). Treat Pulse like a framework component — upgrade alongside Laravel, not on an independent cadence.
Sequencing
| Phase | Scope | Exit criteria |
|---|---|---|
| 0 — Design | Decide ingest driver, DB connection, sampling, retention, audience, gate | Written decision record; owner named |
| 1 — Staging | Install, migrate, viewPulse gate, run both workers under supervisor, load-test at production-like RPS |
Ingest overhead measured; dashboard usable; no table growth anomaly |
| 2 — Production (read-only audience) | Migrations, gate, workers, route restriction | Dashboard reachable by named group only; stale-data alerts firing correctly |
| 3 — Tune | Sampling rates, slow thresholds by regex, ignore lists, retention | Ingest cost within budget; signal-to-noise acceptable to on-call |
| 4 — Extend | Custom cards/recorders for domain metrics; scheduled threshold checks | Team uses Pulse as first stop in triage |
Maintenance
Low code maintenance, moderate operational maintenance. The package is first-party with an active release train (Dependabot-managed, CI hardened, PHPStan 2, GitHub Actions pinned to SHAs) — a good signal for supply-chain hygiene. Your recurring work is: version bumps alongside Laravel, supervising two long-running commands, watching table growth, and periodically re-validating sampling and thresholds as traffic grows. Budget roughly 1–2 engineer-days per quarter post-launch, plus the initial setup.
Support
MIT license, no commercial SLA. Support is the Laravel docs site plus the community and maintainers via GitHub. That is acceptable for a visibility tool and unacceptable as the sole dependency of an on-call paging path — reinforcing that alerting must live elsewhere. Escalation for a genuine defect is "wait for upstream patch," which for a first-party package has historically been days, not weeks.
Scaling
Scaling pressure is entirely on ingest writes and dashboard reads, both against your own storage. Levers, in order of preference:
The dashboard itself is a Livewire app hitting aggregate queries; on large pulse_* tables card loads can become slow, which is a symptom of retention being too long rather than a reason to scale up hardware.
Failure modes
| Failure | User-visible symptom | Blast radius |
|---|---|---|
pulse:work not running |
Dashboard shows data but tables grow without bound | Slow queries, disk pressure, eventual DB incident |
pulse:check not running |
Server/CPU/memory cards blank or stale | Silent loss of host visibility |
| Ingest write failure (DB down/locked) | Gaps in charts | Should degrade quietly rather than fail requests — verify under fault injection before trusting it |
| Sampling set too aggressively | Dashboards look "quiet"; real incidents missed | False confidence — worst failure mode because it is invisible |
| Permissive gate / exposed route | Full exception traces and SQL readable by unauthorized users | Security and data-protection incident |
| Livewire version conflict after upgrade | Dashboard 500s while app is healthy | Monitoring blind spot exactly when you need it |
| Redis ingest eviction/restart | Missing time slices | Misleading trend lines |
Ramp-up
/pulse, which storage the data lands in, and what replaces it for alerting.How can I help you explore Laravel packages today?