Extensions

Scheduler

Embedded cron-style command trigger for single-binary FrankenPHP deployments.

Overview

Pogo Scheduler is a small Caddy app that runs one configured command on every wall-clock minute.

The common Laravel command is:

Terminal
php artisan schedule:run

The scheduler runs in the FrankenPHP process. It is intentionally small and does not try to be a distributed scheduler.

Status and fit

Pogo Scheduler is experimental. Its best fit is constrained, single-binary, and single-node deployments.

Use it when:

  • You run a single VPS or single server.
  • You use Docker Compose or a small container setup and want to avoid host cron.
  • You run a dedicated singleton scheduler service from the same application image.
  • Your framework handles locking, overlap, and task-level safety.

Avoid it when:

  • You run production Kubernetes. Use native CronJob resources.
  • You scale web replicas without shared application locks.
  • You need exactly-once execution without idempotency or locking.

Build

Compile the module into FrankenPHP:

Terminal
xcaddy build \
  --with github.com/dunglas/frankenphp@v1.12.3 \
  --with github.com/dunglas/frankenphp/caddy@v1.12.3 \
  --with github.com/y-l-g/scheduler/module@main

Caddy configuration

Caddyfile
{
  frankenphp

  pogo_scheduler {
    command php artisan schedule:run
    dir /var/www/html
    timeout 5m
    overlap allow
    shutdown_grace 30s
  }
}

Defaults:

DirectiveDefaultDescription
commandphp artisan schedule:runCommand and arguments to run each minute.
diremptyOptional working directory.
timeout5mMaximum duration for one command run.
overlapallowUse allow or skip.
shutdown_grace30sTime to wait for an active command before cancellation.

Application integration

Laravel

Use the default command and keep Laravel's scheduler definitions in routes/console.php or your normal scheduler setup:

Caddyfile
pogo_scheduler {
  command php artisan schedule:run
  dir /var/www/html
}

When running more than one replica, use Laravel locks such as onOneServer() and withoutOverlapping() with a shared cache backend.

Symfony or custom PHP

Point command at any CLI command that can run once per minute:

Caddyfile
pogo_scheduler {
  command php bin/console app:run-scheduled-tasks
  dir /var/www/html
  timeout 10m
  overlap skip
}

PHP API

Pogo Scheduler does not expose PHP functions. It is configured entirely through the Caddy global option.

Operations

  • Run the scheduler-enabled service as a singleton unless your application uses shared locks.
  • Keep scheduled tasks idempotent.
  • Use overlap allow for Laravel's schedule:run, especially when sub-minute tasks can keep the command alive for most of the minute.
  • Use overlap skip only when the command itself must never overlap locally.
  • Set timeout high enough for normal command duration but low enough to prevent stuck processes.

Troubleshooting

  • Command never runs: confirm the binary includes pogo_scheduler and the global Caddyfile block is loaded.
  • Wrong working directory: set dir to your application root.
  • Duplicate scheduled work: run only one scheduler process or add framework-level shared locks.
  • Command cancelled during deploy: increase shutdown_grace or make the command shorter and resumable.