Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Realtime Job Batching Laravel Package

yogameleniawan/realtime-job-batching

A Laravel package for dispatching and monitoring batches of queued jobs in real time. Track batch progress, status, completion, and failures without building custom batching infrastructure, making long-running job workflows easier to observe and manage.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the package actually is. yogameleniawan/realtime-job-batching is a thin convenience layer over two first-class Laravel capabilities: native job batching (Bus::batch() with then/catch/finally callbacks and the Batchable trait's progress() accessor) and the broadcasting subsystem. Its value-add is wiring batch lifecycle transitions to broadcastable events so a browser subscribed via Laravel Echo/Pusher can render a live progress bar instead of polling a status endpoint. That is an integration convenience, not infrastructure — an important framing for the buy-vs-build decision.

Architecture fit. Good fit for any conventional Laravel monolith or modular monolith running a Redis or database queue with broadcasting already configured. It sits at the boundary between the queue worker and the presentation layer, adds no new persistence, no new runtime, and no new protocol beyond the existing WebSocket channel. It does not attempt to replace Horizon, and should not be positioned as an observability tool — it emits UI-facing progress, not operational telemetry. Apps without broadcasting configured, or without a queue driver that supports batching (batching requires a database-backed batch store; sync and beanstalkd are not viable), get nothing from it.

Integration feasibility. Low engineering effort in the happy path, moderate effort to make production-grade. The install is a Composer require, a config publish for Pusher credentials, private-channel authorization in routes/channels.php, and a frontend Echo subscriber. The real work is not the install — it is the hardening: throttling broadcast volume, handling terminal-event loss, and confirming version compatibility against the Laravel major you run.

Technical risk. Concentrated in sustainability rather than correctness:

Risk Severity Notes
Bus factor / abandonment High 24 stars, 0 dependents, single maintainer, composite score 0.24. No community validation, no downstream pressure to keep it current.
Laravel major drift High Batching internals and broadcast event conventions have shifted across Laravel 8→11. An unmaintained adapter is a future upgrade blocker.
Pusher coupling Medium Whether it broadcasts through Laravel's BroadcastManager (swappable to Reverb/Soketi/Ably) or binds the Pusher SDK directly determines exit cost. Must verify.
Broadcast volume / cost Medium One event per job completion is chatty for large batches; Pusher message quotas and connection limits become the scaling ceiling.
Progress semantics Medium Retries, allowFailures, and partial failures can produce double-counted or non-monotonic progress; out-of-order delivery across workers can make a bar jump backwards.
Terminal-event loss Medium If finally broadcast fails or the worker is killed, the UI hangs at 97% indefinitely with no recovery path.
Security surface Low Small, but channel authorization and not leaking job class names/counts to unauthorized subscribers must be confirmed.

The high opportunity score (5.64) against a low composite (0.24) is the tell: the problem is real and recurring, the package is not differentiated. Realtime batch progress is a genuine gap in Laravel's DX — native batching gives you progress() but nothing push-based — but the implementation gap is roughly 100–200 lines of glue.

Key questions to resolve in a one-day spike.

  1. Which Laravel and PHP versions are actually supported, and is there a CI matrix proving it?
  2. Does it use native Bus::batch() under the hood, or does it reimplement batching state?
  3. Does it broadcast through BroadcastManager (driver-agnostic) or hard-bind Pusher?
  4. What is the event payload schema, and is it versioned/stable enough to build a frontend against?
  5. Are events fired per-job, per-percentage-tick, or debounced? What is the message volume for a 10k-job batch?
  6. How are retries and allowFailures reflected in the emitted progress?
  7. Is there a polling fallback or a way to reconcile state after a dropped connection?
  8. Are private/presence channels supported with proper authorization callbacks?
  9. Does it coexist with Horizon, queue:prune-batches, and Laravel Octane?
  10. Is there test coverage, and does it ship a fake/assertion helper for our own test suite?
  11. What is the last commit date, release cadence, and open-issue backlog?
  12. What happens to in-flight batches on deploy/restart — does the UI recover?

Integration Approach

Stack fit. Assumes Laravel with a batching-capable queue (Redis or database driver), a configured broadcasting stack, and a JS frontend with Echo. It is additive: no schema changes, no data migration, no change to how jobs are dispatched or retried. That is its strongest property from a delivery-risk standpoint — it can be adopted on a single workload and backed out by deleting one line.

Build-vs-buy position. Given the adoption signals, the recommended path is adopt-with-a-fork, not adopt-as-dependency. Concretely: run the spike against the upstream package, then either (a) pin the version and vendor it internally behind our own interface, or (b) reimplement the small surface we need directly on Bus::batch()->then()/finally() plus a single BatchProgressUpdated broadcast event. Option (b) is likely 1–2 engineer-days and eliminates the abandonment risk entirely; option (a) is faster if the package's frontend contract saves us meaningful work. Decide after the spike, not before.

Whichever we pick, do not let package types leak into application code. Define an internal seam:

  • BatchProgressBroadcaster interface with started(), progress(), finished(), failed().
  • One adapter that delegates to the package; one that delegates to native batch callbacks.
  • A stable, versioned event payload we own — batchId, name, totalJobs, processedJobs, failedJobs, percentage, status, sequence, emittedAt. Treat this as a public contract with the frontend, independent of the vendor.

Compatibility checks before committing. Laravel version matrix (pin to our major), PHP version, queue driver, broadcasting driver, Horizon coexistence, Octane safety (long-lived workers and broadcast state), and queue:prune-batches retention versus how long the UI needs to query historical batch state. If Reverb/Soketi is our target rather than hosted Pusher, confirm the package doesn't bypass the BroadcastManager.

Sequencing.

  1. Spike (0.5 day). Sandbox app, 50-job batch, confirm events, payload shape, message count, retry behavior.
  2. Seam (0.5 day). Introduce the interface and the owned event payload; wire the package as one adapter.
  3. Harden (1 day). Add debounce/throttle, monotonic sequence guard, terminal-event watchdog, and a GET /batches/{id} polling fallback so a dropped socket self-heals.
  4. Pilot (1 sprint). One non-critical, long-running workload (e.g., bulk import or export) with a real user-facing progress UI.
  5. Decide. If the pilot holds, either keep the vendored fork or swap the adapter to the in-house implementation with zero frontend change.

Operational Impact

Maintenance. The dominant operational cost is ownership, not runtime. With one maintainer, zero dependents, and a sub-0.3 composite score, assume no upstream fixes: we own every future Laravel upgrade incompatibility. Mitigation is to fork into our org, pin the version, and budget roughly 2–4 hours per Laravel major for verification. Keep the fork's diff from upstream minimal so re-syncing remains possible if the project revives.

Support. No vendor SLA, no commercial backing, thin community. Support load falls entirely on the adopting team; document the event contract internally so a future engineer can debug the UI without reading package internals. Expect the most common support ticket to be "progress bar stuck" — pre-empt it with the polling fallback and a visible "last updated" indicator.

Scaling. Two independent ceilings. First, the queue: batch progress reads scale with worker count and job completion rate, which is a solved problem with Redis and Horizon. Second, and more binding, the broadcast plane: hosted Pusher pricing scales on concurrent connections and messages delivered. A 10,000-job batch emitting one event per job will burn quota fast and may trip rate limits, causing dropped or delayed events that look like UI bugs. Enforce throttling at the adapter layer — coalesce to at most one broadcast per N jobs or per fixed time window — and treat the raw per-job event as an anti-pattern. Set a documented batch-size threshold above which the UI degrades to polling.

Failure modes.

Failure User-visible symptom Mitigation
Terminal event lost (worker killed, broadcast error) Bar freezes below 100% forever Watchdog timeout + polling reconciliation endpoint
Out-of-order delivery across workers Bar jumps backwards Monotonic sequence; client discards stale updates
Pusher quota/rate limit exceeded Stuttering or silently missing updates Server-side coalescing; alert on broadcast error rate
Retries re-increment processed count Progress exceeds 100% or double-counts Derive percentage from progress() snapshot, not client-side accumulation
WebSocket auth misconfiguration Silent zero updates for all users Integration test asserting channel authorization; smoke check in staging
Package incompatible after Laravel upgrade Fatal on boot in production Pin, fork, add a CI job against the next Laravel major
Batch records pruned before UI reads history "Batch not found" on reload Set pruning window > max UI retention; persist a summary row

Ramp-up. Low for a Laravel-fluent engineer: roughly half a day to understand batching plus broadcasting, one day to build and harden the integration, and one to two days of frontend work for the Echo subscriber and progress component. The real cost is organizational — someone must own the fork and the event contract indefinitely. If the team cannot commit a named owner, that alone argues for building the ~150-line in-house version instead, where ownership is unambiguous and the upgrade path is entirely under our control.

Bottom line. Real problem, thin package, weak durability signals. Adopt it as a reference implementation and a fast path to a working demo, but put it behind an internal interface, plan to fork or replace it, and do not let it become load-bearing infrastructure.

Primary risks: maintainer abandonment (high), Laravel major drift (high), broadcast cost/volume at scale (medium). Recommendation: conditional — spike now, wrap in an owned seam, decide fork-vs-replace at the pilot exit gate.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log