Sail: queues & workers
How to run Laravel queues when the app lives in Sail. Pair this with Databases & services for Redis/RabbitMQ containers and Environments & deployment for .env across machines.
Navigation: All tools · Sail overview · Databases · Env & deploy · Troubleshooting
Table of contents
- Connections at a glance
- Running
queue:workin Sail - Horizon (Redis)
- RabbitMQ and AMQP packages
- Failed jobs and retries
- Code changes and
queue:restart - Scheduler (
schedule:run) - Contrast with production
Connections at a glance
| Driver | Use case in Sail |
|--------|-------------------|
| sync | Debug job logic without a worker; no concurrency. |
| database | Simple async; needs jobs table and one or more workers. |
| redis | Typical choice; pairs with Horizon; needs Redis service. |
| sqs | Cloud queue; configure AWS keys; less common purely local. |
| rabbitmq (via package) | AMQP exchanges/queues; needs container + package. |
Set QUEUE_CONNECTION in .env. Run sail artisan config:clear after changes.
Running queue:work in Sail
sail artisan queue:work
Useful flags:
sail artisan queue:work redis --queue=high,default --tries=3 --timeout=90
Run multiple terminals if you want separate workers for different queues. For one-off jobs:
sail artisan queue:work --once
Horizon (Redis)
Requires QUEUE_CONNECTION=redis and Horizon installed/configured.
sail artisan horizon
Open Horizon’s dashboard on the path you configured (often /horizon behind auth). On production, Supervisor or systemd keeps Horizon alive; in Sail you stop it with Ctrl+C when you close the terminal.
RabbitMQ and AMQP packages
Laravel does not ship a first-party RabbitMQ driver. Steps:
- Add a RabbitMQ service to Compose (example).
- Install a maintained AMQP queue package; publish config.
- Set
QUEUE_CONNECTION(or connection name) per package docs. - Run:
sail artisan queue:work rabbitmq
Test delayed jobs, failed routing, and TTL—AMQP semantics differ from Redis lists.
Failed jobs and retries
- Ensure
failed_jobsmigration ran when using thedatabasefailed driver. - Inspect:
sail artisan queue:failed - Retry one:
sail artisan queue:retry {id} - Flush:
sail artisan queue:flush
Tune $tries, $timeout, and backoff on jobs to avoid infinite poison messages.
Code changes and queue:restart
Long-running workers cache the application bootstrap. After deploying code (or switching branches):
sail artisan queue:restart
Horizon honors this as well. During aggressive local iteration, --max-jobs=1 or --once reduces stale-code surprises.
Scheduler (schedule:run)
Sail does not add a cron daemon. Options:
- Run manually:
sail artisan schedule:run - Use
sail run --rm laravel.test php artisan schedule:work(Laravel 8+) for a long-lived scheduler process in dev. - On production, a single server cron entry calls
schedule:runevery minute.
Contrast with production
| Topic | Sail (local) | Production | |-------|--------------|------------| | Worker lifecycle | Manual terminal / Horizon foreground | Supervisor, Kubernetes Job, or managed worker | | Scaling | One container | Multiple workers, autoscale | | Redis | Single container | Cluster / managed ElastiCache, etc. | | RabbitMQ | Dev container | Cluster, policies, monitoring |
Treat Sail as correct enough to write jobs and run integration tests—not as a load or HA model.