zenstruck/schedule-bundle
Symfony bundle for scheduling repetitive tasks and console commands with a single cron entry. Define schedules in PHP with flexible frequencies, lock protection, and output logging, powered by Symfony Messenger.
zenstruck/schedule-bundle is a thin, opinionated layer over Symfony's Scheduler component and Messenger. Adopting it is effectively a decision to not hand-roll a cron wrapper, a "run this command every N minutes" registry, or a bespoke task-dispatch console command.schedule:list / schedule:run-style introspection as in execution. It supports decisions like "do we need an admin UI showing upcoming runs?" — the answer is often "no, we can surface the CLI output."bin/console app:foo is a candidate for migration. Use this as a backlog item to inventory and migrate recurring jobs into version-controlled PHP, which improves reviewability and testability.Adopt when most of the following hold:
Look elsewhere when:
For executives (one paragraph): This is a small, low-risk dependency that lets us define all recurring background jobs — nightly cleanups, digests, syncs, reminders — in version-controlled code instead of server crontabs. That means changes go through code review and CI, jobs become testable, and we stop depending on undocumented hand-edited server config. The v1.9.0 release adds support for the next major Symfony version and clears deprecation warnings, so adopting it now does not create a blocker for our upcoming framework upgrade. Cost is minimal: one Composer dependency plus running the Messenger worker we already operate.
For engineering leadership: It's a ~thin bundle over Symfony Scheduler + Messenger, maintained in the Zenstruck ecosystem. Interfaces are small (a ScheduleProvider plus attributes), migration is incremental — one crontab line at a time — and reversible. v1.9.0 is a compatibility and hygiene release: Symfony 8 support, deprecation fixes, dev-dependency bumps. No breaking changes, no new API surface, nothing requiring code changes on our side; it's a safe composer update.
For the engineering team: Treat it as a scheduling declaration layer, not an execution-guarantee layer. We still own worker supervision, lock strategy for anything that must not double-run, and observability. Recommendation: pilot on non-critical jobs first, and standardize on a shared lock for anything money- or customer-visible.
How can I help you explore Laravel packages today?