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 Short Schedule Laravel Package

spatie/laravel-short-schedule

Schedule Artisan commands at sub-minute frequencies—every second or half-second—using a long-running ReactPHP event loop kept separate from Laravel's native scheduler, so short tasks never delay your regular schedule.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package fills a genuine gap: Laravel's native scheduler is minute-granular, and this provides sub-minute cadence down to 0.5s. Architecturally it is one long-lived ReactPHP event-loop process (short-schedule:run), with one periodic timer per task, each firing spawning a detached Symfony\Component\Process via the non-blocking start(). Slow tasks therefore do not delay sibling tasks — notably better isolation than the native scheduler's sequential foreground execution, and fully independent of schedule:run.

The critical implication is that this is not an in-process worker. Every tick cold-boots a fresh Laravel process. At everySecond(), a single task is ~86,400 boots/day. That cost shapes the correct use: it belongs where you need a cheap, frequent trigger, not sustained in-process throughput. The recommended pattern is tick → thin artisan command → dispatch a queued job. Good fit: cache warmers, external API polling, heartbeat/watchdog checks, queue-backlog nudges, metric scrapers. Poor fit: heavy in-process work, state held across ticks, exactly-once semantics.

Integration feasibility. Very low effort. composer require, register via the ShortSchedule facade in routes/console.php (facade added in 1.6.0) or the legacy shortSchedule() Console Kernel method, add a Supervisor program. No migrations, no published config, no new infrastructure. onOneServer() requires an atomic-lock-capable cache store (redis, memcached, database, dynamodb) — verify the driver per environment. exec() covers non-PHP shell tasks. The two events (ShortScheduledTaskStarting/Started) provide hooks, but listeners execute inside the loop and must be non-blocking.

Technical risk (ranked):

  1. Support-window cliff. v1.7.0 requires PHP 8.3+ and Laravel 13, and explicitly drops Laravel 10/11. On L10/L11 we are pinned to 1.6.x with no forward fixes. Decide whether the framework upgrade lands before or after adoption.
  2. Silent failure. Tasks are fire-and-forget; the loop records no exit codes, stdout, or durations. There is no schedule:monitor analogue and no short-schedule:list. A task can fail every second indefinitely with nothing surfacing it.
  3. Loop-blocking hazards. when(), between(), environments() and event listeners are evaluated in-loop on every tick. A slow DB call inside when() at 1s cadence stalls every other task. Easy to violate, hard to notice.
  4. Ungraceful restarts. --lifetime=N terminates the worker and its child processes; deploy and Supervisor bounces do the same. In-flight tasks die mid-execution. Task bodies must be idempotent, short, and restart-tolerant.
  5. Orphaned locks. withoutOverlapping()/onOneServer() depend on cache locks; a killed child can leave a lock until TTL, stalling that task silently.
  6. Adoption signal. 659 stars and 0 dependents in the sampled graph — modest ecosystem validation. Spatie's track record and test suite mitigate, but do not treat this as load-bearing infrastructure without a fork contingency.

Key questions.

  • What is the actual business cadence requirement, and could event-driven design or delayed queue jobs satisfy it instead? Sub-minute cron is usually a fallback for missing eventing.
  • Is the estate on the 1.7.0 support window, or does adoption start pinned to 1.6.x?
  • What is the acceptable worst-case task duration, and therefore the --lifetime value?
  • Which cache store backs onOneServer(), and is it shared across all app servers?
  • Who owns the Supervisor config, and is it in the deploy pipeline?
  • Do we accept building our own observability layer, or is the missing failure recording a blocker?

Integration Approach

Stack fit. Standard Laravel app under Supervisor or systemd, PHP 8.3+, Composer-managed dependencies. No conflict with the native scheduler — the two loops are deliberately independent, so short tasks cannot delay the regular schedule and vice versa. It does not touch queue workers, Horizon, or Octane (Octane's long-lived app process is unaffected because spawned commands remain separate processes). exec() makes a small number of non-Laravel shell tasks possible, though plain cron/systemd timers are usually the better home for those.

Migration path. Nothing to migrate from, since sub-minute scheduling is not natively possible. The realistic migration is from the approximations teams use today: while(true) scripts under Supervisor, hand-rolled daemons, over-frequent queue polling, or sleep loops embedded in commands. Replace those one at a time, each as its own PR with an independent rollback (disable the entry, restart the worker). Do not migrate existing minute-level native scheduler tasks into this package — that strictly adds cold-start cost for no cadence gain.

Compatibility. PHP 8.3+ and Laravel 13 on 1.7.x; Laravel 9–11 on 1.5–1.6.x. Verify: cache driver supports atomic locks if using onOneServer(); the PHP binary resolved by the scheduler matches the application's binary (1.6.4 fixed paths containing spaces; check multi-PHP and version-manager setups); process spawning is not blocked by disable_functions or a read-only filesystem — Symfony Process needs a writable temp directory, hence the spatie/temporary-directory dependency. Multi-node deployments must run the worker on every node, with onOneServer() wherever duplicates are unacceptable.

Sequencing.

  1. Spike (1–2 days). Install in staging, one everySeconds(5) command that just logs, confirm the loop starts under Supervisor and survives a restart.
  2. Observability before any real task. Wire both events to a queue-backed logger plus per-task duration metrics. Add an alert on "no task-start events in N minutes" — this is the only reliable liveness signal available.
  3. Adopt 2–3 low-risk trigger tasks. Keep bodies thin (validate, dispatch job); apply withoutOverlapping() by default to anything non-trivial.
  4. Codify the schedule. Entries in routes/console.php with owner comments, one task per PR, a documented --lifetime per environment, and a deploy-pipeline step that restarts short-schedule:run whenever the schedule definition changes (the README is explicit that schedule changes require a restart).
  5. Only then adopt tasks with business consequence.

Operational Impact

Maintenance. Small code surface — a thin wrapper around ReactPHP and Symfony Process — but two recurring chores. The package tracks only the newest Laravel, making it a forced annual upgrade dependency; fold it into the framework upgrade initiative rather than treating it as standalone. And restart-on-schedule-change means schedule definitions are runtime state, not deploy state — the most common route to silent environment divergence. Low bus-factor risk: MIT, stable maintainer, no commercial dependency.

Support. Community only: GitHub issues, no SLA, no paid support for this package, plus a [email protected] channel for vulnerabilities. With 0 dependents and modest stars, expect to be first to hit edge cases; budget for engineers reading the source (it is small) rather than waiting upstream. Keep a fork-and-patch contingency — the license and code size make single-engineer ownership viable.

Scaling. Scales per node, not horizontally by default: N app servers run N loops, so each task executes N times unless onOneServer() is applied. That flag adds a shared-cache round-trip per tick per task — at 1s cadence across several tasks and nodes this is real lock churn on Redis, and it does not pin a task to a specific node. Cost scales with (tasks × frequency × nodes × Laravel boot cost), independent of business volume — predictable, but easy to underestimate on small instances. Cold-booting Laravel every second will show clearly in CPU baselines. Prefer the lowest frequency that satisfies the requirement: 5s instead of 1s is an 80% reduction in overhead.

Failure modes. (1) Worker dies and is not restarted — total silent stop, detectable only via heartbeat alerting. (2) Worker alive but loop blocked — all tasks stall at once, presenting as "no executions" rather than an error; the same alert covers both. (3) --lifetime or a deploy restart kills an in-flight task mid-write — partial state, so require idempotent, resumable bodies. (4) Orphaned overlap/server locks stall an individual task until TTL. (5) Task failures produce no signal — they must be caught and logged inside the artisan command itself. (6) Memory growth in the loop from constraint closures or listeners, mitigated by --lifetime at the cost of (3). (7) Duplicate execution during a rolling deploy where two workers briefly coexist without onOneServer().

Ramp-up. Roughly half a day for an engineer fluent in Laravel's scheduler, most of it spent on operational framing rather than the API. The surface is small: everySecond, everySeconds, between, when, environments, plus withoutOverlapping, onOneServer, runInMaintenanceMode. The genuinely new knowledge is ReactPHP-loop reasoning: constraints and listeners run in-loop and must never block, and spawned processes are detached so nothing returns to the caller. Formalize with a short internal runbook covering Supervisor configuration, --lifetime selection, restart-on-schedule-change, heartbeat alerting, and the "thin command → queued job" pattern. Spatie's three-part video series is a reasonable onboarding artifact for the under-the-hood portion.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle