leventcz/laravel-top
Lightweight real-time monitoring for Laravel apps directly from the command line. Run php artisan top to track essential metrics and busiest routes in production, with aggregated Redis data across all servers.
Architecture fit
laravel-top is an instrument panel, not an observability platform. It subscribes to Laravel's request, query, and cache events, writes pre-aggregated counters into Redis behind a short TTL, and renders a rolling ~5-second average to the terminal via php artisan top. There is no retention, no query layer, no dashboards, no alerting, no trace correlation, and no historical comparison. The accurate stakeholder framing is "top for Laravel HTTP traffic" — an incident-triage and post-deploy smoke-check utility — and explicitly not a replacement for APM, error tracking, or log aggregation. Positioning it otherwise loses on capability and burns credibility with the platform team.
The strategic appeal is that it is framework-native and additive. No agent, no sidecar, no middleware to register, no migration, no vendor contract, no new secret beyond an existing Redis connection. For a Laravel 10–13 estate already on PHP 8.2+ with Redis, the cost of a pilot is measured in hours. That makes it a low-ceremony way to close a visibility gap while a larger observability decision is still pending — which is precisely the situation most Laravel teams are in.
Multi-server coverage is the genuine differentiator. Because aggregates live in shared Redis rather than on the local host, one terminal session reflects traffic across the fleet. An on-call engineer can answer "what is slow right now, and which route is responsible?" without SSH-ing into every app server and without a dashboard having been provisioned in advance. That is the strongest argument for a pilot: material incident-response improvement at near-zero platform investment.
The scope boundary is a product constraint, not a footnote. Only incoming HTTP request events are recorded; queues, scheduled jobs, Artisan commands, and broadcast/websocket work are invisible. In most mature Laravel applications a meaningful share of latency regressions originate in workers. Left unstated, the tool manufactures false confidence during exactly the incidents where it is reached for first. This must be written into the runbook, not discovered during a page.
recording_mode is a policy lever the TPM should own explicitly. runtime (default) records only while someone is actively running the command — effectively zero steady-state cost and zero request-path dependency. always records continuously and unlocks the facade, enabling CI gates and internal dashboards, but converts the package into a permanent production dependency on every request. Defaulting to runtime and promoting to always only against a named, signed-off use case is the defensible position.
Integration feasibility
Prerequisites are shallow and documented: composer require leventcz/laravel-top, optional vendor:publish --tag="top", Laravel 10+, PHP 8.2+, Redis 5.0+, Octane-compatible. No migrations, no data model changes, no new service to operate. This is a spike, not a roadmap item — realistically one engineer for a few days including verification.
The real integration cost is Redis governance, not code. The package writes to Redis on the request path, so the work item is deciding which instance (the shared default versus a dedicated logical database), confirming the eviction policy will not silently discard aggregates before they are read, and establishing who owns capacity headroom. That is a conversation with the owner of caching, sessions, and queues — and it is where the integration budget belongs.
The facade widens both the use cases and the blast radius. Top::http(), Top::database(), Top::cache(), Top::routes(), and startRecording()/stopRecording() let a team embed metrics in CI gates or internal tooling without building collection. Attractive for a "fail the deploy if average duration regresses" check. It also means request handling now depends on this package and on Redis, and it should be managed as a production dependency with version pinning and a documented rollback, not as a developer convenience.
Edges to probe before commitment: behavior of recording_mode=always outside HTTP contexts; whether Redis unavailability or added latency degrades the very application the tool exists to observe; measured overhead at target peak RPS; correctness under Octane's long-lived workers; and whether 5-second averaging produces stable or noisy readings under bursty traffic.
Technical risk
| Risk | Severity | TPM mitigation |
|---|---|---|
| Single maintainer, zero dependents, limited adoption evidence despite ~581 stars | Medium | Pin the version; assign an owner for upgrade testing; document the exit path (one Composer package plus one config file) |
| Redis contention or eviction interfering with caching, queues, or sessions | Medium–High | Isolate to a dedicated logical database; measure Redis op rate and latency in staging at production-like RPS before rollout |
| Redis unavailability turning a read-only tool into an application risk | Medium | Verify failure behavior in staging; gate always mode behind explicit sign-off |
| False confidence from HTTP-only coverage | Medium | State non-goals in the on-call runbook; pair with queue/worker monitoring |
| Framework drift — Laravel 12 and 13 each required a separate compatibility release | Low–Medium | Add to the Laravel upgrade checklist alongside other pinned packages |
| Metric noise from 5-second averaging under bursty traffic | Low | Validate in staging load tests; treat readings as directional, not SLI-grade |
Key questions to answer before adoption
runtime (diagnostic only) or always (feeds CI/tooling)? Who signs off on the production request-path dependency?Stack fit
Clean fit for a standard Laravel 10–13 service already running Redis and PHP 8.2+, with CLI access to production or a production-like environment. That describes a large share of typical Laravel estates, so the addressable surface is broad and the pilot cohort can be chosen on convenience rather than on architectural work.
Poor fit where Redis is absent, where production shell access is restricted by platform policy, where Redis already carries critical load, or where the platform is managed in a way that precludes this pattern.
It is complementary to existing tooling, not competitive. Frame it for the platform owner as "a live HTTP triage view alongside APM and error tracking," never as "reduces APM spend."
Migration path
There is nothing to migrate. Adoption is purely additive: install, optionally publish config, select a Redis connection, choose recording mode, run the command. No traffic cutover, no dual-write period, no backfill, no schema change.
The only meaningful migration is retiring a bespoke internal Artisan monitoring script. That is the strongest build-versus-buy argument: replace homegrown code with a maintained MIT package, then decommission the internal script once the pilot demonstrates parity on the metrics the team actually uses. Exit is equally clean — remove the package and the config file. Because runtime mode does not touch the request path unless someone is recording, reversibility is unusually good for a production-adjacent tool.
Compatibility
Verified against Laravel 10 through 13.x, PHP 8.2+, Redis 5.0+, and Laravel Octane. The compatibility record is the thing to watch: releases 1.2.0 (Laravel 12) and 1.3.0 (Laravel 13) each existed solely to track a framework major. That is a healthy maintenance response, but it also means the package is a per-major-release dependency that must be on the upgrade checklist. Octane is claimed as supported, which matters because long-lived workers change how per-request state accumulates; validate that counters do not leak across requests and that the 5-second window behaves correctly under worker reuse.
Redis 5.0+ is a low floor and unlikely to be a blocker. The dependency that actually needs confirmation is the eviction policy on the chosen database — an allkeys-lru cache instance can silently discard aggregates, producing empty or misleading readings rather than an error.
Sequencing
php artisan top under synthetic load, confirm routes and metrics render correctly. No production exposure.runtime mode (2–4 weeks). Enable for on-call engineers only. Zero request-path cost when idle. Collect feedback on whether it actually shortens triage.always. Only if a named use case (CI regression gate, internal dashboard) is funded and a named owner accepts the permanent dependency. Requires explicit sign-off.The sequencing deliberately defers the irreversible-ish decision (always mode) until after the reversible one (runtime mode) has proven value.
Maintenance
The maintenance surface is small: one Composer package, one optional config file, no infrastructure. The burden is not ongoing toil but periodic attention at Laravel major upgrades, where a compatibility release must land before the framework bump can ship. Pin the version, add it to the upgrade runbook, and name an owner. The absence of a large contributor base and the single-maintainer profile means the team should assume it may need to fork or vendor the package if upstream activity stalls — a realistic possibility given zero dependents and limited adoption evidence.
Support
Community-only, MIT, no SLA, no commercial backing. There is no vendor to escalate to. The mitigation is internal ownership: one engineer who understands the event hooks, the Redis key layout, and the config surface well enough to debug or patch. That is a few hours of ramp-up and is the single most important operational control for a single-maintainer dependency.
Scaling
Redis write volume scales with request rate — every HTTP request produces event writes for HTTP, database, and cache metrics. That is not sampling. At high RPS the package adds a measurable, continuous Redis op load. The mitigating design choice is the short TTL, which bounds memory regardless of traffic; it does not bound op rate. Sizing should be based on measured Redis ops per request at peak, not on the "lightweight" claim in the README. Cross-fleet aggregation scales well by design (one shared Redis, one terminal), but it also means a single congested Redis affects the tool's accuracy for the entire estate simultaneously.
The 5-second averaging window is a scaling consideration too: under bursty traffic it produces readings that swing, and under low traffic it may not have enough samples to be meaningful. Treat output as directional and useful for ranking routes, not as an SLI.
Failure modes
runtime mode with no active recording, exposure is minimal; in always mode it is a request-path dependency.Ramp-up
Engineer ramp-up is negligible — one command, self-explanatory output. The ramp-up that matters is organisational: on-call needs to know what the tool does not show (queues, jobs, commands, historical trends) and what to reach for instead when the answer isn't HTTP-shaped. Budget a short runbook entry plus a line in the incident playbook. The pilot cohort should be the on-call rotation, since they are both the primary beneficiaries and the best judges of whether the tool earns a permanent slot.
How can I help you explore Laravel packages today?