Scale on Queue Depth with KEDA
Use KEDA to scale a consumer deployment from queue length, set a sensible target and cooldown, and scale to zero when the queue is empty.
Task
Autoscale a worker on an external queue metric instead of CPU.
When to use this
Workers idle with no work and cannot keep up with a burst, because scaling is based on CPU which lags behind the real backlog.
Prerequisites
- KEDA installed
- A queue with a readable depth metric
Steps
1. Create a ScaledObject targeting the consumer with a queue trigger.
Expected output: KEDA creates an HPA driven by queue depth.
2. Set the target queue length per replica from measured throughput.
Expected output: Scaling responds to real backlog, not CPU.
3. Configure cooldown and polling intervals to avoid thrashing.
Expected output: Scaling is stable.
4. Enable scale-to-zero if a cold start is acceptable.
kubectl get scaledobject app-scaler -o jsonpath='{.status}'Expected output: Idle cost drops when there is no work.
Troubleshooting
Problem
Workers scaled faster than they can drain
Solution
Tune the target per replica against measured per-worker throughput and add a maxReplicaCount cap.
Problem
Messages reprocessed on scale-in
Solution
Drain gracefully before termination; scale-in must not cut processing mid-message.
Limitations
- Scaling on queue depth assumes roughly uniform per-message cost; highly variable work needs a different signal.
- Scale-to-zero introduces cold-start latency that some latency-sensitive consumers cannot tolerate.
Context
Autoscale a worker on an external queue metric instead of CPU. Workers idle with no work and cannot keep up with a burst, because scaling is based on CPU which lags behind the real backlog.
Steps
- Create a ScaledObject targeting the consumer with a queue trigger. Expected: KEDA creates an HPA driven by queue depth.
- Set the target queue length per replica from measured throughput. Expected: Scaling responds to real backlog, not CPU.
- Configure cooldown and polling intervals to avoid thrashing. Expected: Scaling is stable.
- Enable scale-to-zero if a cold start is acceptable. Expected: Idle cost drops when there is no work.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata: { name: app-scaler }
spec:
scaleTargetRef: { name: consumer }
minReplicaCount: 0
maxReplicaCount: 30
triggers:
- type: rabbitmq
metadata: { queueName: orders, queueLength: "20" }
Verify
- KEDA creates an HPA driven by queue depth.
- Scaling responds to real backlog, not CPU.
- Scaling is stable.
- Idle cost drops when there is no work.
Limits
- Scaling on queue depth assumes roughly uniform per-message cost; highly variable work needs a different signal.
- Scale-to-zero introduces cold-start latency that some latency-sensitive consumers cannot tolerate.