romanzipp/laravel-queue-monitor
Laravel Queue Monitor tracks queue jobs in your database, recording status, duration, attempts, exceptions, and payloads. It adds a dashboard for searching, filtering, and inspecting failed or completed jobs, helping you debug and monitor queue performance without extra infrastructure.
Architecture fit
romanzipp/laravel-queue-monitor is a database-backed, in-process observability layer for Laravel queues. It fits the shape of a standard Laravel app well: it is a service provider plus a migration, a QueueMonitor Eloquent model, an optional trait applied to individual job classes, and a bundled Blade dashboard mounted on a configurable route. There is no sidecar, no agent, no external time-series store, and no vendor account — the entire monitoring plane lives in the same database as the application.
Release 5.0.0 changes the shape of that fit in one important way: it adds monitoring of queued jobs (a new queued_at column and a monitor_queued_jobs config flag, defaulting to on). Instrumentation is no longer confined to the worker/consumer tier — a monitoring row is now written at dispatch time, inside the web request cycle. That expands the architecture surface from "observability inside the queue worker" to "observability that also touches the producer path." For a TPM this matters less as a feature question and more as a blast-radius question: the package now sits between the application and the queue on the hot path of every dispatch.
Otherwise the fit assessment holds: strong where the TPM is optimizing for lowest integration cost and no new infrastructure (internal tools, admin back-offices, single-tenant SaaS, teams treating the primary database as the source of operational truth); weaker where platform strategy depends on centralized observability — still no Prometheus metrics, OpenTelemetry spans, structured logs, alerting, or paging. Position it as job-level record-keeping and debugging UX, not a replacement for Horizon, Sentry, or a metrics pipeline.
The 5.0 release sharpens the Horizon distinction rather than blurring it. Horizon owns supervisor/queue health and recent job metadata in Redis; Queue-Monitor now also answers "was this job ever queued, and did it ever start?" — a question Horizon is not designed to answer and one that support teams ask constantly when a dispatch silently goes nowhere. That is a genuine differentiator and should be stated as the primary business case for the upgrade.
Integration feasibility
Delivery risk remains low, but 5.0 is a major version with a schema change, so it is not a drop-in composer update. The upgrade path is explicit: republish migrations (--tag=migrations), run php artisan migrate to add queued_at, and review the new monitor_queued_jobs config value. A single engineer can complete a proof of concept in under a day; a production upgrade should be scoped as a small, deliberate piece of work rather than routine dependency hygiene. MIT-licensed, no commercial entanglement, no procurement or legal friction.
Technical risk
The risks are concentrated in six areas, all of which a TPM should force to a decision before build:
illuminate/* or PHP constraints. Verify against the actual composer.json before committing. The existence of an active 5.0 release is a positive signal on maintenance, but it is not evidence of Laravel 11/12 support. Budget for a fork or patch release if the constraint is short; this remains the highest-probability blocker.queued write at dispatch on the web tier and (b) the existing start/finish/fail writes in the worker. That is roughly 3–4 writes per job rather than 2–3, split across two connection pools. Do the arithmetic against peak dispatch rate, not just peak job completion rate — fan-out endpoints can dispatch far faster than workers drain.monitor_queued_jobs enabled, dispatched jobs are monitored automatically without touching job classes, so volume is driven by your dispatch call sites, not by your trait decisions. Selective instrumentation is no longer a single control; the config flag, the trait, and the call sites must all be reasoned about together.queued_at column is added to a large existing queue_monitor table without a lock-driven write stall. On MySQL 8 a nullable column add is typically instant; verify, and rehearse on a production-shaped copy including rollback.Key questions
composer.json, and is a maintained fork required?monitor_queued_jobs be on or off, and if on, which dispatch paths are excluded? Who owns that config decision?Stack fit
The package expects a conventional Laravel stack: Eloquent, the default queue abstraction, relational storage, and Blade for the bundled UI. 5.0 materially improves this dimension by officially adding PostgreSQL and SQLite support alongside MySQL. PostgreSQL shops previously flagged as "unproven" can now treat fit as confirmed; SQLite is supported for local development and test suites, which is a real quality-of-life gain (developers can exercise the dashboard locally against real data). Production SQLite at meaningful volume remains inappropriate. Multi-tenant databases, sharded queues, and non-relational primary stores are still unproven — spike first.
Migration path
Because the package is additive and the upgrade is versioned, adoption and upgrade should both be incremental rather than big-bang:
queued_at column add. Do not let this ride along with an unrelated deploy.monitor_queued_jobs before the upgrade ships, not after. Default-on is the release's default, not necessarily yours; high-dispatch-volume paths may need it off or a code-level exclusion.queue_monitor table before attaching traffic. Retrofitting this later means a data migration under load — and 5.0's higher write rate makes the case stronger than it was in 4.x.Compatibility
Pin to ^5.0 explicitly and record the supported Laravel/PHP matrix in the service catalog entry. Teams still on 4.x should note that 5.0 is a breaking release (new column, new config, behavior change): 4.x is now the legacy line, and remaining on it should be a dated decision with an owner, not a default. If the app is on a newer framework major than the package advertises, the decision is: fork and maintain, or select an alternative (Horizon plus a custom job_history table, or hosted APM). Do not adopt on the assumption that "it probably works" — the failure mode is silent, partial instrumentation.
Sequencing
The correct order is compatibility verification → storage and connection decision → monitor_queued_jobs decision → retention policy → auth boundary → narrow instrumentation → broaden. Inverting this (upgrade, instrument everything, then discover the table is bloating the primary DB and the dispatch path is degraded) is the most common and most expensive mistake with database-backed monitoring packages. A realistic plan is one to two sprints for a production-grade rollout, with the majority of effort in the upgrade rehearsal, retention automation, and dashboard access control — not in the Composer install.
Maintenance
This is the dominant long-term concern, and 5.0 improves the picture without retiring it. Evidence of active development — a new major, community contribution (#131), and expanded database support — is a meaningful positive signal against the prior "last release September 2023" read. But the structural facts are unchanged: single-maintainer, MIT-licensed project, no listed dependents. The practical read for a TPM remains assume you may own this code. Budget for fork-and-patch capability (Laravel major upgrades, dashboard security patches), assign a named owner, and classify it as a low-activity dependency with a review checkpoint at each Laravel upgrade cycle. Add one new maintenance obligation to that budget: the 5.0 upgrade itself, including its migration.
Support
Support load is low and predictable, and 5.0 measurably increases the positive support value by distinguishing "never queued" from "queued but never ran" from "ran and failed." Those are three different conversations for a support engineer, and 4.x could only speak to the last one. That is the upgrade's clearest business case and should be measured rather than assumed: track ticket resolution time on instrumented job classes before and after, and specifically watch for dispatches that were previously invisible. The small, well-understood surface still means failures present visibly (dashboard empty, rows not populating) rather than subtly.
Scaling
Scaling characteristics remain linear and unglamorous: rows and writes grow proportionally to monitored job volume — now with an additional write per dispatch and additional retained rows per job. The levers are (a) selective instrumentation across both the trait and the monitor_queued_jobs flag, (b) a dedicated database connection so monitor writes never contend with application traffic, (c) scheduled retention pruning including stale queued rows, and (d) indexes covering queue, job class, status, queued_at, and started-at, which the dashboard's filtering depends on. Note that 5.0's schema change may invalidate existing index assumptions; review them as part of the upgrade. Beyond roughly low-millions of retained rows, expect partitioning or shorter retention. Cap the dashboard's default time window — this matters more now that tables grow faster.
Failure modes
queued write is not isolated, a saturated or unavailable monitor table turns telemetry into failed or delayed dispatches for end users. Verify fail-open behavior explicitly, separately from the worker-side case, and test both by revoking write access in staging.monitor_queued_jobs on, a well-intentioned fan-out loop can multiply monitoring writes without any engineer touching a job class. Watch dispatch rate as a first-class capacity metric.queued_at to a large table can lock; rehearse, time it, and have a rollback.Ramp-up
Engineer ramp-up remains minimal — roughly half a day to a day for a Laravel-fluent developer, now with a small addition for the 5.0 migration and the monitor_queued_jobs semantics. Operational ramp-up for on-call is the larger cost: the team must learn that this dashboard answers job-level history questions (queued, started, failed, retried) while Horizon answers queue health questions, and that neither is an alerting system. Write that distinction into the runbook before launch, along with the retention job's owner, the escalation path if the monitor table becomes unavailable, and — new in 5.0 — the explicit statement that a monitoring failure must never block a dispatch.
How can I help you explore Laravel packages today?