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

Laravel Horizon Cron Supervisor Laravel Package

ralphjsmit/laravel-horizon-cron-supervisor

Run Laravel's scheduled tasks through Horizon instead of system cron. Your schedule is dispatched as Horizon jobs, so it's supervised, monitored, and retried automatically and visible on the Horizon dashboard.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Laravel's deployment guidance assumes an external process manager — Supervisor or systemd — keeps Horizon alive. Where that assumption doesn't hold (cPanel/Plesk, a single small VPS, cron-only PaaS, containers with no init process, staging or on-prem environments where the customer owns the box and won't install a process manager), Horizon has no supported liveness story at all. This package fills exactly that gap using primitives the host already provides: one artisan command and one cron entry. It adds no new daemon, no schema change, no queue-driver change, and it reuses the existing config/horizon.php supervisors and queues. That is close to the minimum possible footprint for the capability, and it is the strongest argument for adopting it.

The one thing a TPM must resolve before scoping: the source materials describe two different mechanisms, and they are not equivalent. The package description implies a liveness poll — cron checks whether Horizon is running and starts it if not. The prior assessment describes a bounded run — cron invokes a command that boots Horizon, drains jobs for a max runtime or job count, exits gracefully, and is re-invoked next tick. These imply different failure modes (stale-PID false positives vs. overlapping masters and throughput gaps), different tuning parameters (none vs. max runtime under cron interval), and different deploy interactions. Confirming which one the code implements is the first task in the spike, not an implementation detail. Any estimate built before that is confirmed is provisional.

Integration feasibility. High, inside a deliberately narrow envelope. Adoption is composer require, optional config publish, and a cron line under the deploy user. Rollback is deleting the cron line and re-enabling the prior supervisor. No application-code change, no data migration, no dashboard reconfiguration, and no new dependency in the runtime stack — Laravel + Horizon + Redis are already present if Horizon is a candidate at all. The real integration cost isn't engineering hours; it's decision and documentation work: confirming you're genuinely in the target environment, and rewriting the on-call runbook to describe the new restart semantics.

Technical risk. Risks are operational rather than code-quality, and most are verifiable inside one day of staging work:

  • Overlap / duplicate workers. Under the bounded-run model, a max runtime exceeding the cron interval means two Horizon masters against the same queues. Possibly benign (a poor man's autoscaler), possibly harmful (contention, doubled Redis connections, incoherent dashboard state). Confirm a lock or atomic guard exists.
  • Throughput gaps. If the pool is torn down and rebuilt each cycle, there is a workerless window between exit and the next tick. Invisible at low volume; visible as sawtooth queue depth and inflated job age at steady volume.
  • Cron granularity and host throttling. Recovery time and blast radius depend entirely on whether the host floors cron at 1, 5, or 15 minutes. Measure it on each target host; do not read it off a doc page.
  • Deploy interaction. Zero-downtime deploys typically call horizon:terminate and rely on the supervisor restarting immediately on new code. Under cron, restart waits for the next tick — up to a minute of queue stall per deploy. Fixable in the pipeline, but it must be sequenced, not discovered in production.
  • Maintainer concentration. 63 stars, zero dependents, single maintainer, MIT. That is effectively an internal dependency sitting on the critical job-processing path. The March 2025 release adding Laravel 12 support is a good responsiveness signal; it is not a guarantee about the next Horizon major.

Key questions.

  1. Liveness-poll or bounded-run? What exactly does the command do, and what determines its exit?
  2. Is there a lock or atomic guard against overlapping cron invocations?
  3. What is the measured cron granularity on each target host?
  4. What happens to in-flight jobs at shutdown — released back to the queue, or dropped?
  5. How do the Horizon dashboard, metrics, and auto-balancing behave when the master exits every cycle?
  6. How does this interact with horizon:terminate during deploys, and what pipeline change avoids the stall?
  7. Which Laravel and Horizon majors are supported, and what is our exposure when the next Horizon major ships?
  8. Is the host genuinely supervisor-incapable, or are we routing around a solvable ops problem?

Integration Approach

Stack fit. Best fit: single-server deployments, cPanel/Plesk/semi-managed hosting, small teams without config management, containers lacking a process supervisor, staging and QA environments that want production-like Horizon behavior without a second class of infrastructure, and single-tenant on-prem installs where the customer controls the server. Decline outright for Kubernetes (liveness probe plus a proper controller), ECS with a service definition, Vapor, Forge with native daemons, or any host already running Supervisor or systemd — there the package is strictly redundant complexity and introducing it degrades a working setup.

Migration path. Low ceremony and reversible, but don't skip the measurement steps:

  1. Pin the version in composer.json; install and publish config on staging.
  2. Read the source — it's small. Look specifically at shutdown handling, locking, and how supervisors and queues are resolved.
  3. Install the cron entry under the deploy user — not root, and not the web user if Horizon runs as a dedicated worker.
  4. Deliberately kill the Horizon master on staging and measure actual recovery time. This single test converts the latency-SLA conversation from debate into data.
  5. Load-test at expected peak: does queue depth stay flat or sawtooth between cycles? Tune max runtime and cron interval against that curve, not against intuition.

Compatibility. Verify the package's Laravel/PHP/Horizon constraints against the app's pinned versions before anything else. Laravel 12 support landed in 1.4.3 (March 2025); older Laravel lines should be confirmed against the composer constraints rather than assumed. Horizon major version is the sharper edge — the package wraps Horizon's supervisor lifecycle, so a Horizon internals change is more likely to break it than a Laravel bump. Pin Horizon and this package together, and treat a Horizon upgrade as requiring a re-read of the source and a staging kill-test.

Sequencing. Treat this as two decoupled releases rather than one:

  1. Release A — adopt Horizon behind cron. Ship queue visibility, retries, and tagging on today's hosting with no new infrastructure. Write down the explicit boundary: this tier has a recovery window measured in cron ticks, not milliseconds.
  2. Release B (conditional, later) — move to real supervision when job latency acquires an SLA, volume grows past what a single master drains, or the deployment goes multi-node. That migration is not blocked by this package; deleting the cron line and enabling a Supervisor unit is a clean cutover.

Rollback at any point in Release A is deleting the cron line and re-enabling the prior mechanism — which is exactly why a tested fallback should be prepared before cutover rather than after.

Operational Impact

Maintenance. Small and bounded: a pinned Composer dependency, one config file, one cron entry, and a paragraph in the runbook. The continuing obligation is not patching — it's the version-watch duty on Horizon upgrades, since this package tracks Horizon's lifecycle internals. Assign a named owner in the dependency inventory and record the tested fallback (a hand-written scheduled liveness command, or a Supervisor unit that can be re-enabled) alongside it. Absent an owner, a low-adoption single-maintainer package on the job-processing path becomes an unowned availability risk.

Support. Community-only: MIT, GitHub issues, no vendor backing, no SLA. Acceptable for glue you could replace in an afternoon; not acceptable where compliance or audit requires vendor-backed support — that bar should be checked explicitly rather than assumed irrelevant. Budget roughly a day of engineering for the source read and staging kill-test, which is also the cost of being able to say you vetted it.

Scaling. This is a single-node, modest-volume solution by construction. It does not autoscale, and under the bounded-run model it does not continuously hold worker capacity — capacity exists in windows. Two thresholds mark the ceiling: (a) queue depth does not drain within a cycle at expected peak, and (b) job age becomes a product-visible number. Multi-node Horizon fleets need real process supervision and health checks; the package should not be stretched to cover them. Write the ceiling down now, so the eventual migration is a planned step rather than an incident response.

Failure modes. Enumerate them and monitor each independently — do not rely on the supervisor to report its own failure:

  • Silent non-start. Cron fires, command errors, nothing runs. Detected only by alerting on Horizon process age and queue depth.
  • Stale or recycled PID false positive (liveness-poll model). Horizon appears alive; it isn't.
  • Overlapping masters (bounded-run model with max runtime > interval). Contention, doubled connections, confusing dashboard.
  • Workerless gaps between cycles. Latency, not data loss — jobs sit in Redis until reserved — but latency that compounds under backlog.
  • Deploy stall. horizon:terminate with no immediate restart; queue halts until the next tick.
  • Host-level cron failure or throttling. Managed hosts may suppress or delay the entry; verify, don't assume.

Ramp-up. Very low for an engineer already comfortable with Horizon. The genuinely new knowledge is narrow and testable: how this command determines liveness and shutdown, and what the host's actual cron granularity is. On-call needs one rewritten runbook page — "queue is stalled, check whether Horizon is running and re-invoke the command" — plus the two new alerts (process age, queue depth) and a documented manual restart procedure that does not depend on cron firing. The trap is assuming cron behaves like Supervisor: it polls, it doesn't react, and the difference shows up as a minute of queue stall at the worst possible moment — during a deploy.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource