workerman/crontab
workerman/crontab is a lightweight cron scheduler for Workerman PHP applications. It adds second-level cron expressions and recurring task scheduling to Workerman workers, letting you run background jobs on timers without relying on external cron.
Architecture fit. workerman/crontab is a resident, event-loop scheduler — not a job runner. It registers PHP callbacks against cron expressions inside a long-lived Workerman process and fires them on the loop, with second-level granularity. That fits a Laravel codebase only in a few shapes: you already run a Workerman process (websocket server, resident worker), you genuinely need sub-minute ticks, or your hosting has no dependable system cron. For a conventional Laravel app, the framework's own Schedule is a functional superset for our purposes — onOneServer, withoutOverlapping, runInBackground, before/after hooks, output capture, schedule:test, schedule:list, mutex-backed single execution — and it is already part of the stack we support. Treat this package as a deliberate exception, not a default. v1.0.7 changes none of this: it is a runtime-compatibility patch with no new scheduling capability, no persistence, and no locking.
Integration feasibility. Technically easy, organisationally awkward. Installation is a single Composer dependency on workerman/workerman; driving it from an Artisan command is straightforward. The friction is process-level, not code-level: you must bootstrap Laravel once and keep it alive correctly, accept a new supervised daemon in the deployment topology, and guarantee pcntl/posix plus a POSIX host (no Windows parity outside containers).
Technical risk. Moderate to high for anything production-critical. The library provides scheduling primitives only: no persistence, no run history, no retry, no failed-task store, no distributed lock or leader election. Duplicate execution is a live footgun — if the Workerman worker count exceeds one, the same crontab is registered in each process and fires in each. Long-lived Laravel containers accumulate state (stale DB/Redis connections, warmed config, memory growth), and a blocking callback delays or skips subsequent ticks. Exception behaviour inside a callback should be verified against Workerman's restart semantics before relying on it.
Release delta (v1.0.7). One change: a fix for running errors on PHP 8.4 (PR #17, community contributor). No API change, no behavioural change, no deprecations, no new features. Two implications for us: (a) it confirms the package was broken on 8.4 — if our target runtime is PHP 8.4 (Laravel 11/12 default images), v1.0.7 is the minimum usable pin, and anything earlier is a non-starter rather than a preference; (b) it is the first external contribution in recent memory, which is a small positive on maintenance responsiveness, but the maintainer remains the sole release authority.
Vendor risk. 71 stars and 0 dependents is very low ecosystem adoption; the mitigating factor is that the author maintains Workerman itself, so it is first-party in practice. Bus factor is effectively one. A first-time contributor getting a compatibility patch merged slightly widens the review surface, but does not change the fork/vendor contingency.
Key questions.
pcntl/posix, and can Workerman coexist with Octane/FPM?Stack fit. Poor as a general-purpose scheduler; reasonable as an in-process tick inside an existing Workerman runtime. Preference order: Laravel Scheduler + queue > workerman/crontab as a dedicated standalone worker > workerman/crontab embedded in an unrelated worker process.
Migration path. Introduce a thin internal registry (name, expression, handler, lock key, timeout) and compile it to either Laravel Schedule or Crontab::add(). Port expressions explicitly — this package supports second/minute/hour/day/month/week (and year) fields, not the standard 5-field format, so expressions are not interchangeable 1:1. Bind every handler to an Artisan command or queued job rather than an inline closure, so the same unit of work runs unchanged under either scheduler.
Compatibility. Pin ^1.0.7 as the floor if we are on PHP 8.4; earlier tags regress on that runtime and should be excluded rather than merely discouraged. Verify the package's PHP constraint against our Composer resolution and run composer why-not in CI to prevent a transitive downgrade. Confirm coexistence with Laravel Octane and Swoole/RoadRunner (Composer and extension conflicts are plausible); confirm supervisor/systemd patterns and that it does not contend with Horizon or existing queue workers. Note that the 8.4 fix is a patch on the loop-side behaviour, not a functional claim — re-run the soak on 8.4 rather than assuming parity with 8.3 results.
Sequencing. (1) Inventory existing scheduled tasks and their owners. (2) Spike in staging with one non-critical task on the exact target PHP version. (3) 72-hour soak measuring RSS, tick drift, connection health, and exception behaviour. (4) Implement single-run guarantees plus a heartbeat/health probe. (5) Canary one task in production with system cron still in place as fallback. (6) Cut over task-by-task, or abandon with no residue.
Recommendation. Do not adopt for the general case. Adopt only where a Workerman process already exists and sub-minute or in-process ticks are a real requirement; otherwise keep Laravel's scheduler and revisit only if that constraint changes. The v1.0.7 patch removes a hard blocker on PHP 8.4 but does not improve the fit — it moves the package from "cannot run here" to "can run here, still not the right tool."
Maintenance. Low release cadence and a small, readable codebase; pin to an exact version and expect to read the source rather than rely on documentation. v1.0.7 is a targeted compatibility fix rather than a step-change in maintenance posture — treat patch releases as something we must track manually, because there is no changelog RSS, LTS branch, or security policy. Budget a fork/vendor contingency given single-maintainer risk.
Support. Community-only, no vendor SLA. The owning team absorbs the wrapper, upgrades, and runbook. The PHP 8.4 fix arriving as a community PR means upstream support exists in practice but is not on any committed timeline — do not plan around a fix landing on a date we need.
Scaling. Single event loop; throughput is bounded by the slowest callback. Horizontal scale requires explicit task sharding or leader election, otherwise every replica fires every job. CPU-bound work must be pushed to the queue.
Failure modes to instrument. Silent stop (process alive, no ticks); crash-loop on uncaught callback exceptions; duplicate fire across replicas or worker counts; missed runs across deploys; blocking callbacks causing drift; unbounded memory growth; stale DB/Redis connections after idle; PHP-version drift between the scheduler container and the web tier (the exact class of failure v1.0.7 addresses, and one a mixed fleet can reintroduce during a rolling upgrade). Mitigate with a heartbeat metric, per-task logging of duration and outcome, alerting on missed intervals, and a CI check that all images share one PHP minor.
Ramp-up. The API is tiny (add/remove/clear), so library fluency is roughly a day. The real cost is operational literacy: Workerman event-loop semantics, the pcntl/posix process model, supervising a long-lived Laravel container, and lock-based single execution. Estimate 1–2 days for a mid-level engineer plus a written runbook, and add the new process to the deploy and observability checklist before it reaches production.
How can I help you explore Laravel packages today?