No description
  • PHP 99.6%
  • JavaScript 0.4%
Find a file
2026-03-22 12:39:29 +10:00
src chore: rename to laravel-metronome 2026-03-22 11:40:19 +10:00
tests chore: rename to laravel-metronome 2026-03-22 11:40:19 +10:00
workbench test: add some test logging to enture the event loop works 2025-12-28 15:11:44 +10:00
workflows ci: add Github Actions 2026-03-22 12:35:45 +10:00
.editorconfig build: install pest 2025-12-28 14:08:20 +10:00
.envrc build: set up tooling 2025-12-27 15:56:00 +10:00
.gitignore build: set up testbench 2025-12-27 16:19:55 +10:00
.nvmrc build: set up tooling 2025-12-27 15:56:00 +10:00
.php-cs-fixer.php build: set up tooling 2025-12-27 15:56:00 +10:00
commitlint.config.js build: set up tooling 2025-12-27 15:56:00 +10:00
composer.json chore: bump to v0.1.0 2026-03-22 12:39:29 +10:00
CONTRIBUTING.md docs: add CONTRIBUTING.md 2026-03-22 12:38:42 +10:00
herd.yml build: install pest 2025-12-28 14:08:20 +10:00
lefthook.yml build: install pest 2025-12-28 14:08:20 +10:00
LICENSE docs: add a proper readme 2026-03-22 12:31:11 +10:00
package.json build: set up tooling 2025-12-27 15:56:00 +10:00
phpstan.neon build: set up tooling 2025-12-27 15:56:00 +10:00
phpunit.xml build: install pest 2025-12-28 14:08:20 +10:00
pnpm-lock.yaml build: set up tooling 2025-12-27 15:56:00 +10:00
README.md docs: add a proper readme 2026-03-22 12:31:11 +10:00
rector.php build: set up tooling 2025-12-27 15:56:00 +10:00
testbench.yaml feat: set cache store 2025-12-28 15:20:29 +10:00

Laravel Metronome

A drop-in replacement for Laravel's built-in scheduler using an event loop instead of Cron.

Requirements

  • PHP 8.2+
  • Laravel 12+
  • ext-pcntl

Installation

composer require rvxlab/laravel-metronome

Usage

Replace your schedule:work invocation with:

php artisan schedule:metronome

Tick rate

The tick rate controls how often the scheduler checks for due tasks in seconds. By default, the tick rate is 1 second. You can change the tick rate by passing the --tick-rate or -t option:

# Default, suitable for most workloads
php artisan schedule:metronome --tick-rate=1

# Check twice per second, useful for high-frequency sub-minute tasks
php artisan schedule:metronome --tick-rate=0.5

# Minimum allowed value (100 times per second), rarely needed in practice
php artisan schedule:metronome --tick-rate=0.01

Lower tick rates increase the number of times the scheduler checks for due tasks, which can be helpful if your workload relies on sub-minute scheduling or if you have a large number of small tasks scheduled. It's worth keeping in mind that lowering the tick rate will increase the CPU usage slightly. In most cases the difference is negligible (< 0.1%).

Overlap Protection

Metronome makes use of Laravel's overlap protection, exactly how the built-in scheduler works.

Calls to ->withoutOverlapping() will continue to work as expected.

Long-running tasks

As with Laravel's built-in scheduler, synchronous tasks that run long will delay later ticks. For tasks expected to take more than a second or two, use ->runInBackground() to shell out a child process instead.

$schedule->command('orders:process')->everyMinute()->runInBackground();

Running with Supervisor

Add the following to your Supervisor configuration, adjusting command, user, and stdout_logfile to match your setup.

[program:laravel-metronome]
process_name = %(program_name)s_%(process_num)02d
command = php /var/www/html/artisan schedule:metronome
autostart = true
autorestart = true
stopasgroup = true
killasgroup = true
user = www-data
numprocs = 1
redirect_stderr = true
stdout_logfile = /var/www/html/storage/logs/metronome.log
stopwaitsecs = 60

numprocs must be 1 — running multiple instances will cause tasks to fire multiple times. stopwaitsecs should be set high enough to allow any currently running tasks to finish before Supervisor force-kills the process.

Running with Docker

Because Metronome doesn't rely on Cron, it's really easy to have it run in a Docker container, either directly or through Supervisor.

Without Supervisor, you can run the scheduler directly as the container's entrypoint:

FROM php:8.2-cli

RUN docker-php-ext-install pcntl

WORKDIR /var/www/html

COPY . .

CMD ["php", "artisan", "schedule:metronome"]

Or with Supervisor, if you need it running alongside other processes:

FROM php:8.2-cli

RUN apt-get update && apt-get install -y \
        supervisor \
    && rm -rf /var/lib/apt/lists/* \
    && docker-php-ext-install pcntl

WORKDIR /var/www/html

COPY . .

COPY supervisord.conf /etc/supervisor/conf.d/laravel-metronome.conf

CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/supervisord.conf"]

Stopping the Scheduler

Send SIGINT (Ctrl+C) or SIGTERM to stop the process cleanly. Laravel's shutdown logic runs before the process exits, so process managers like Supervisor and systemd work out of the box.

Differences from schedule:work

schedule:work schedule:metronome
Tick mechanism sleep(60) Event loop
Default tick rate 60 seconds 1 second
Configurable tick rate No Yes
Sub-minute precision Best effort High precision
Overlap protection Yes Yes
Laravel events Yes Yes
Filters (->when(), etc.) Yes Yes

Known limitations

  • Last-run state is held in memory and not persisted across process restarts. A task that ran shortly before a crash may re-run immediately on startup.

License

This package is licensed under MIT.