Core Concepts · Key takeaways

2 min read
Senior15 min read
Rapid overview

Key takeaways

  • The gap KEDA fills: HPA scales only on CPU/memory and has a floor of 1 — it can't react to event sources and can't scale to zero. KEDA (CNCF graduated) adds event-driven scaling + scale-to-zero.
  • Components: keda-operator (owns 0↔1, watches ScaledObject/ScaledJob), keda-operator-metrics-apiserver (external-metrics adapter so a standard HPA reads event metrics), admission webhooks. Footprint ~50–100 Mi.
  • Two-phase model (the centerpiece): 0→1 (activation) is owned by the operator (the part HPA can't do; back to 0 after cooldownPeriod, default 300s); 1→N is handed to a standard HPA KEDA creates. KEDA wraps HPA; it does not replace it.
  • Two thresholds per scaler: activation (0→1, operator) is distinct from target (1→N, HPA).
  • ScaledObject ties a Deployment to triggers[] and sets minReplicaCount (0 = scale-to-zero), maxReplicaCount, cooldownPeriod, pollingInterval. 60+ scalers (RabbitMQ length, Kafka lag, Prometheus query, Redis length, cron, SQS…).
  • HTTP needs the http-add-on because no metric exists at 0 pods: an interceptor buffers the request → signals 0→1 → waits for readiness → forwards it (and counts pending requests for 1→N), plus an external scaler and the HTTPScaledObject CRD. Wire the Ingress backend to the interceptor, not the app Service. Footprint ~30–60 Mi.
  • Cold start: first request after idle pays schedule → start → readiness (~2–5s .NET, less with ReadyToRun/AOT); the interceptor buffers it into a slow 200, not a 502. Warm requests pass straight through.
  • KEDA vs HPA vs Knative: HPA = CPU/mem, min 1. KEDA = event-driven + scale-to-zero, lightweight (wraps HPA). Knative also scales to zero but its control plane (activator/autoscaler + per-pod queue-proxy sidecar) is heavy and can cost more than it saves on a tight node — so KEDA's http-add-on is preferred there.
  • Consumer nuance: a consumer scaled to zero by a non-queue trigger stops draining its queue — but with the queue scaler (rabbitmq queueLength, polled out-of-band even at 0) it sleeps at 0 and wakes on the first message, scaling 0→N on depth. So a consumer can scale to zero with the right scaler; conservative first pass is minReplicaCount: 1.
  • Never scale to zero: stateful workloads — databases, brokers, caches.
  • What it buys: idle → 0 replicas → 0 RAM + 0 scheduling reservation, the density lever (see node-rightsizing). Caveat: 0 RAM per idle container, not a $0 hardware bill — a self-hosted node costs the same idle or full; $0-at-idle is per-request serverless only (Cloud Run/Lambda/Fly).

See also