Quick Start
Quick Start
Zero to a working autoscaled queue in about 5 minutes. Every command and file path on this page is real — nothing is a placeholder.
Prerequisites
- PHP 8.4+ and Laravel 12+, with
ext-pcntlandext-posixavailable - Redis configured in
config/database.phponly if you plan to use the Redis or cluster presets cboxdk/laravel-queue-metricsalready set up — see Installation
Step 1 — Install and publish config
composer require cboxdk/laravel-queue-autoscale
php artisan queue:autoscale:install
You now have config/queue-autoscale.php, config/queue-metrics.php, and a matching env setup for the preset you chose. The defaults work out of the box: one queue (default) on your default connection, using the BalancedProfile (30s SLA, 1–10 workers).
Step 2 — Start the daemon
In one terminal:
php artisan queue:autoscale -v
You should see something like:
Starting Queue Autoscale Manager
Manager ID: your-host-3f9c1a2b4d5e
Mode: single-host
Evaluation interval: 5s
The manager ID is your hostname plus a short hash derived from container/machine identity, so two
managers on the same host never collide. The interval comes from manager.evaluation_interval_seconds (default 5), which --interval
overrides when given. Leave the manager running.
Use
-vvfor debug-level output (per-queue metrics and decisions) and-vvvto also see the capacity breakdown used for each scaling decision.
Step 3 — Dispatch test jobs
In a second terminal, push some work onto the queue. One quick way via tinker:
php artisan tinker
>>> for ($i = 0; $i < 50; $i++) { dispatch(function () { sleep(1); }); }
(If your app already has job classes, dispatch those instead.) Switch back to the manager terminal and watch.
Within a few evaluation cycles you'll see output like:
Evaluating queue: redis:default
Metrics: pending=42, oldest_age=14s, active_workers=1, throughput=6/min
📊 Decision: 1 → 6 workers
Reason: backlog=42 requires 5.8 workers to prevent SLA breach (oldest_age=14.0s, effective_sla=29.1s)
⬆️ Scaling UP: spawning 5 worker(s)
When the backlog drains, the manager scales back down. Because scaling down is a reversal of the
previous direction, it waits out scaling.cooldown_seconds (default 60s) first. The cooldown gates
only that case: scaling further the same way is never delayed, and neither is a scale-up.
Step 4 — Tune for your workload
The defaults cover ~80% of cases. When they don't, pick a shipped profile or override specific keys.
Pick a profile
Seven profiles ship with the package. Each is a pre-tuned bundle of SLA, worker limits, forecast and fuse settings.
// config/queue-autoscale.php
use Cbox\LaravelQueueAutoscale\Configuration\Profiles\BackgroundProfile;
use Cbox\LaravelQueueAutoscale\Configuration\Profiles\BalancedProfile;
use Cbox\LaravelQueueAutoscale\Configuration\Profiles\CriticalProfile;
'sla_defaults' => BalancedProfile::class, // 30s SLA (p95), 1-10 workers
'queues' => [
'payments' => CriticalProfile::class, // 10s SLA (p99), 5-50 workers
'analytics' => BackgroundProfile::class, // 300s SLA (p95), 0-5 workers
],
The other three are HighVolumeProfile (20s, 3–40 workers), BurstyProfile (60s at p90, 0–100
workers) and ExclusiveProfile (pinned to exactly 1 worker, never scaled).
See Workload Profiles for the full comparison.
Override specific keys
Need almost a profile but with tighter limits? Pass an array that deep-merges on top of sla_defaults:
'queues' => [
'exports' => [
'sla' => ['target_seconds' => 45],
'workers' => ['min' => 0, 'max' => 3],
],
],
Lock a queue to sequential processing
Some queues must not run in parallel (customer integrations that need strict ordering, APIs with single-connection rate limits). Use ExclusiveProfile:
use Cbox\LaravelQueueAutoscale\Configuration\Profiles\ExclusiveProfile;
'queues' => [
'legacy-sync' => ExclusiveProfile::class,
],
The manager pins the queue to exactly one worker and respawns it if it dies. It never scales. See Queue Topology.
Step 5 — Hook up alerts
The manager emits events (SlaBreached, SlaRecovered, WorkersScaled, etc.) that any Laravel listener can consume.
Three paste-and-go recipes cover the common cases:
- Alert via Log — dedicated log channel, zero external deps
- Alert via Slack — one webhook URL
- Alert via Email — via Laravel Notifications
All three use the built-in AlertRateLimiter so a sustained breach doesn't become a pager storm.
Step 6 — Deploy
Run the manager as a long-running daemon. Pick your platform:
Important: if your platform has a separate "queue workers" UI (Forge, Ploi), don't configure workers there for queues the autoscaler manages. They would fight. See each platform page for details.
Verify it worked
# Inspect what the manager and metrics package see for a queue.
php artisan queue:autoscale:debug --queue=default --connection=redis
If workers are not spawning even though jobs are piling up, head to Troubleshooting — it's organized by symptom.
What to read next
- Queue Topology — when to use per-queue, groups, exclusive, or excluded. Start here before adding more queues.
- Configuration — the full config reference, including advanced keys.
- How It Works — Little's Law, backlog drain, and forecasting, explained.
- Cookbook — more recipes beyond alerting.