Skip to content
← All packages

Queue Autoscale for Laravel

SLA-driven autoscaling for Laravel queue workers. Declare how long a job may wait before pickup, and the manager solves for the worker count each cycle using queueing theory, bounded by the CPU and memory the host actually has.

SLA-driven, not threshold-driven

Most autoscalers react to queue depth thresholds. When the queue grows past 100 jobs, add workers. When it drops below 10, remove them. This is backwards. You do not care about queue depth. You care about how long jobs wait before a worker picks them up.

Queue Autoscale for Laravel lets you define SLA targets: "jobs on the default queue should start processing within 30 seconds." Each evaluation cycle the manager solves for the worker count that holds that target, then constrains it by the CPU and memory measured on the host. Worker counts are derived, not configured.

How It Scales

Little's Law

The steady-state baseline is workers = arrival rate × average job time. The arrival rate is only used when the estimator is confident enough; otherwise the observed processing rate stands in, and retry volume is subtracted so retries are not counted as new arrivals.

Backlog Drain

A second candidate kicks in once half the SLA budget is consumed, with a quadratic urgency curve: 1.0x at half the budget, 3.0x at the target, capped at 5.0x. The larger of the two candidates wins.

p95 Pickup Time

The SLA signal is the p95 of real observed pickup times over a sliding window, falling back to oldest-job age when there are too few samples. Measured spawn latency is subtracted from the budget, so the manager reacts to when a worker will actually be running.

Failure Fuse

A downstream outage looks exactly like load to any autoscaler. The fuse detects a high failure rate, holds the queue at workers.min instead of pouring workers into a wall, then probes with a single worker before releasing.

Resource Awareness

CPU and memory ceilings measured on the host constrain every decision, reduced by what other queues on the same host already use. It will not scale beyond what the machine can carry.

Cluster & Worker Groups

Managers auto-join via Redis, elect a leader and distribute worker targets across hosts. A worker group is one worker set polling several queues in strict priority order.

How the algorithm works

The default hybrid strategy computes two candidate worker counts and takes the larger. Little's Law gives the steady-state baseline; backlog drain protects the SLA once half the budget is gone. A saturation guard adds a worker when the existing ones are above 90% utilisation but neither calculation asked for more. The target is then clamped to the queue's min and max, smoothed by hysteresis that limits scale-down to one worker per cycle, and blocked by an anti-flapping cooldown that stops only reversals, never further scaling in the same direction.

See what it is thinking

php artisan queue:autoscale:debug --queue=payments prints one queue's raw state, metrics and fuse status. queue:autoscale:cluster shows the leader, hosts, capacity and workload targets. Use them to tune SLA targets against real numbers.

Grafana dashboard showing worker scaling decisions, queue depths, and SLA compliance over time.