twigger/laravel-job-status
Track Laravel queue jobs with persistent status records, progress updates, and error details. twigger/laravel-job-status helps you monitor what’s queued, running, completed, or failed, making background job visibility and debugging easier.
Architecture fit. The package is a thin, event-driven observer layered onto Laravel's queue lifecycle (JobQueued, JobProcessing, JobProcessed, JobFailed). It persists one row per tracked job into a dedicated table, exposes an Eloquent model plus a trait that jobs opt into, and emits broadcast events on status transitions so a UI can subscribe. Architecturally it is complementary to — not competitive with — Horizon: Horizon is an operator dashboard, this is application-level, queryable, model-associated status. That makes it a fit for product-facing visibility ("your export is queued / running / ready / failed, retry #2") and a poor fit as a replacement for Horizon or for cross-service job orchestration.
Integration feasibility. Composer install, publish and run one migration, add a trait to the jobs you want tracked, optionally configure broadcasting. Small surface area: one trait, one model, a modest config file. A credible spike is roughly one engineer-day. The feasibility question is not the code — it is the version matrix and the write path.
Technical risk. The dominant risk is stewardship, not design. Twenty stars, zero dependents, single maintainer, last release July 2023 — realistically untested against Laravel 11/12 and current PHP minors. Treat it as a vendored dependency with a known upgrade tax, not a supported platform component. MIT and a small footprint bound the fork cost; that is the mitigation. Secondary risk is write amplification: every status transition is a DB write on the worker path, which is fine at hundreds of jobs/hour and needs sizing at hundreds of jobs/second. Tertiary risk is lifecycle fidelity — retries, batches, chains, and worker-kill cases are where naive status packages usually leak.
Key questions.
Stack fit. Strong for a Laravel monolith or modular Laravel app on MySQL/Postgres with Redis or database queues and an existing broadcast stack (Reverb, Pusher, Soketi). Weak where jobs execute outside Laravel's dispatcher, or where the queue is shared with non-Laravel producers.
Migration path. If replacing a homegrown status table or Horizon polling: (1) freeze the current schema; (2) run the package migration into a new table; (3) dual-write via a listener while both schemas coexist; (4) cut reads to the package's models; (5) drop the legacy table. If greenfield, skip dual-write — but define the read model (status endpoint shape, authorization, pagination) before enabling the trait, or the schema will drive the UI instead of the reverse.
Compatibility. Pin the version explicitly in composer.json. Run composer why-not against the target Laravel version before planning any framework upgrade, and make "review this package" a gate in the Laravel upgrade checklist. If Horizon is present, confirm the package observes the same dispatcher events rather than Horizon's own tables — it should, but verify with a smoke test rather than assume.
Sequencing.
Maintenance. Effectively a self-maintained fork with a familiar API. Budget one to two engineer-days per Laravel major upgrade to patch, vendor, or upgrade. Keep an internal fork in a private namespace as standing insurance — MIT makes that cheap and reversible. Track upstream commits but do not depend on them for planning.
Support. No SLA, single maintainer, community-only. The escalation path is "we fork it." Acceptable for internal and product-assistive visibility; not acceptable as a hard dependency for a contractual SLA unless the fork is already in place before launch.
Scaling. Cost scales with jobs-per-second × transitions-per-job, not with job duration. At high throughput the extra INSERT/UPDATE per transition plus index maintenance can load the primary; consider a dedicated connection or separate schema, and index (job_id), (model_type, model_id), and (status, created_at). Decide retention up front — 30–90 days is a reasonable default — and plan table partitioning or archival rather than bolting it on after the table crosses a few hundred million rows.
Failure modes to design for.
started rows when a worker dies without a terminal event — needs a periodic reaper.Ramp-up. Low. A Laravel-fluent engineer is productive in under a day: apply the trait, read the model, wire one endpoint. The real onboarding artifact is the runbook — retention job, reaper, upgrade gate, fork procedure — and it should be written alongside the first integration, not after the first incident.
How can I help you explore Laravel packages today?