KEDA: How Event-Driven Autoscaling Cuts Kubernetes Cost KEDA, an open-source Kubernetes event-driven autoscaler graduated by the CNCF, reduces cloud costs by scaling workloads to zero replicas when no events are pending, a capability standard HPA lacks. Created by Microsoft and Red Hat, KEDA supports 70+ event sources and manages HPA resources automatically, with scale-to-zero as its most impactful cost feature. Cold starts are a trade-off, mitigated by lean containers and tuned probes, while Cast AI optimizes the node layer for cost efficiency. Key takeaways - KEDA is a CNCF Graduated open-source project graduated August 22, 2023 , created by Microsoft and Red Hat. - It scales Kubernetes workloads using external event signals: queue depth, Kafka consumer lag, Prometheus metrics, and 70+ additional sources. - KEDA wraps Kubernetes HPA rather than replacing it. When you create a ScaledObject, KEDA creates and manages an HPA resource automatically. - Scale to zero is KEDA’s most impactful cost feature. HPA cannot go below 1 replica; KEDA patches replicas directly to 0 when no events are pending. - Cold starts are the trade-off of scale-to-zero. Mitigate with lean container images, tuned readiness probes, and per-workload minReplicaCount decisions. - Cast AI handles the node layer: provisioning instances, placing pods on spot, and right-sizing resource requests so KEDA-scaled pods land on minimum-cost nodes. What is KEDA? Most queue-based workloads sit idle between processing bursts, holding node reservations and consuming compute budget without doing useful work. KEDA Kubernetes Event-Driven Autoscaling addresses this directly. It scales workloads based on external event signals such as queue depth or Kafka lag, rather than CPU or memory alone. When no events are pending, KEDA takes the Deployment all the way to zero replicas, eliminating idle cost. Microsoft and Red Hat created the project; it reached CNCF Graduation on August 22, 2023, with over 10,000 GitHub stars and 400+ contributors confirming production maturity. The most important capability separating KEDA from standard HPA: KEDA can scale to zero. HPA enforces a minimum of 1 replica with no mechanism to reach zero. KEDA bypasses that constraint at the controller level, patching the replica count directly when all event sources report empty. Key CRDs KEDA introduces four primary CRDs: ScaledObject : Links a Deployment or StatefulSet to one or more event source triggers. It defines min/max replicas, polling interval, and cooldown period. ScaledJob : Targets Kubernetes Jobs instead of long-running Deployments. Use ScaledJob when each event should spawn an isolated Job instance rather than routing to a shared worker pool. This is the right choice for one-shot batch tasks where job isolation matters more than pooled efficiency, for example image processing or report generation where shared state is a liability. TriggerAuthentication : Manages credentials for scalers that need to authenticate to external systems, for example storing an AMQP connection string for RabbitMQ. ClusterTriggerAuthentication : A cluster-scoped variant of TriggerAuthentication, reusable across multiple namespaces. KEDA supports Deployments, ReplicaSets, StatefulSets, and Jobs. It runs across AWS EKS, GCP GKE, Azure AKS, and on-premises clusters without cloud-vendor lock-in. How event-driven scaling works KEDA deploys three pods into your cluster: the KEDA Operator keda-operator , the Metrics API Server keda-metrics-apiserver , and the Admission Webhooks server keda-admission-webhooks . The KEDA Operator The KEDA Operator watches for ScaledObject and ScaledJob CRDs. When you create a ScaledObject, the operator creates and manages an HPA resource targeting your specified Deployment. It polls external event sources continuously to determine whether scaling should activate or deactivate. The Metrics API Server The keda-metrics-apiserver implements the external.metrics.k8s.io API. This bridges Kubernetes and external event sources so the HPA controller can query queue depths, Kafka consumer lag, or Prometheus values as if they were native cluster metrics. Therefore, HPA’s existing scaling logic applies without modification. The Admission Webhooks The keda-admission-webhooks pod validates ScaledObject and ScaledJob CRDs at creation time. Before Kubernetes commits a ScaledObject to etcd, the webhook checks that the target resource exists and the trigger configuration is valid. It also verifies the referenced TriggerAuthentication is present. This means misconfigured ScaledObjects fail fast at apply time rather than silently misbehaving at runtime. All three pods must be healthy for KEDA to function correctly. Scaling flow - You create a ScaledObject referencing a Deployment and a trigger, for example a RabbitMQ queue. - The Admission Webhook validates the ScaledObject before Kubernetes commits it. - The KEDA Operator detects the validated ScaledObject and creates an HPA targeting the Deployment. - The Metrics API Server queries the external event source for current queue depth. - HPA reads the metric via external.metrics.k8s.io and scales the Deployment accordingly. - When the queue empties, KEDA directly patches the Deployment replica count to 0, bypassing HPA’s minimum-1 constraint. KEDA scalers A scaler is KEDA’s abstraction for connecting to an external event source. Each entry in a ScaledObject’s triggers list corresponds to one scaler. KEDA ships with 70+ built-in scalers. Common examples include: rabbitmq : Scales on queue length or queue message rate. kafka : Scales on consumer group lag per topic. aws-sqs-queue : Scales on ApproximateNumberOfMessagesVisible . prometheus : Scales on any PromQL query result. azure-servicebus : Scales on Azure Service Bus topic or queue depth. KEDA also supports custom scalers through the External Scaler gRPC interface, so you can connect KEDA to any internal or proprietary metric source. Scale to zero and cold starts Scale-to-zero is what makes KEDA materially different from HPA in cost terms. Here is exactly how it works. How scale-to-zero works When all triggers in a ScaledObject report zero events empty queue, zero lag, no metrics above threshold , KEDA patches the Deployment replica count directly to 0. This deliberately bypasses HPA. Standard HPA enforces a minimum of 1 replica and cannot eliminate idle pods. KEDA bypasses that constraint at the controller level. When a new event arrives, KEDA detects it on the next polling interval. It then sets replicas to 1, and HPA takes over for further scale-out based on the metric value. Note that when a Deployment is at 0 replicas, only KEDA polls at pollingInterval . The managed HPA does not activate until the first replica exists. This means the maximum wait time on the first event after scale-to-zero is one pollingInterval default: 30 seconds, or 10 seconds in the example YAML below . Cold-start implications Scaling from 0 to 1 requires Kubernetes to schedule a pod, pull the container image if not cached on the node , and complete initialization before processing begins. For queue-based workloads, the first messages in a burst typically experience a delay of a few seconds to over a minute, depending on image size and startup behavior. This trade-off is acceptable for batch workers and background consumers. However, it is not acceptable for latency-sensitive request processors. Know your workload before enabling scale-to-zero. Mitigations Set for latency-sensitive workloads. Reserve scale-to-zero for batch jobs and background consumers. minReplicaCount: 1 Optimize container images : Use multi-stage builds and minimize layer count. Pre-pull images using a DaemonSet or node image caching policy. Tune : A longer cooldown 60-300 seconds prevents rapid oscillation during intermittent bursts. cooldownPeriod Use the KEDA-HTTP add-on for HTTP workloads: it proxies and buffers incoming requests during the cold-start window, preventing dropped connections. KEDA vs HPA KEDA does not replace HPA. It wraps and extends HPA. When you deploy a ScaledObject, KEDA creates and manages an HPA resource in the background. You get HPA scaling mechanics plus KEDA event triggers and scale-to-zero capability. For a deeper look at HPA mechanics, see What Is Kubernetes HPA and How Can It Help You Save on the Cloud? https://cast.ai/blog/what-is-kubernetes-hpa-and-how-can-it-help-you-save-on-the-cloud/ Comparison table | Feature | HPA | KEDA | |---|---|---| | Scale to zero | No minimum 1 replica | Yes | | Scaling signals | CPU, memory, custom metrics | 70+ external sources queues, Kafka, Prometheus, etc. | | Event-driven triggers | No | Yes | | Requires installation | No built-in to Kubernetes | Yes Helm chart or operator YAML | | Manages HPA under the hood | N/A | Yes | | Works with Kubernetes Jobs | No | Yes ScaledJob | | Best for | HTTP services, CPU-correlated workloads | Queue consumers, batch jobs, bursty event workloads | When to use HPA Use HPA when your workload is an HTTP service that scales predictably with traffic. If CPU or memory correlates well with load and you never need scale-to-zero, HPA’s zero-installation setup wins on simplicity. Stateless API services are the canonical example. When to use KEDA Use KEDA when your workload consumes from a queue, Kafka topic, or SQS stream. Choose KEDA when your workload sits idle for hours or has unpredictable burst patterns: queue consumers, batch jobs, and webhook processors all fit this profile. For these patterns, scale-to-zero alone often justifies the additional setup cost. In contrast, forcing a queue-based consumer through HPA’s CPU-based scaling produces poor results. CPU does not rise until workers are already processing messages, introducing unnecessary lag in scaling response. ScaledObject YAML The following example configures KEDA to scale a RabbitMQ consumer Deployment based on queue length. It includes all required resources: the Kubernetes Secret for credentials, the TriggerAuthentication CRD, and the ScaledObject itself. Installing KEDA Before applying ScaledObject resources, install KEDA into your cluster with Helm: helm repo add kedacore https://kedacore.github.io/charts Pin chart version to avoid breaking changes. Check https://github.com/kedacore/charts/releases for the latest stable release. helm install keda kedacore/keda --namespace keda --create-namespace --version 2.14.0 This deploys all three KEDA pods into a dedicated keda namespace. Run kubectl get pods -n keda to confirm the operator, metrics server, and admission webhook are all running before proceeding. Step 1: Create the Secret apiVersion: v1 kind: Secret metadata: name: keda-rabbitmq-secret namespace: default type: Opaque data: Base64-encoded AMQP URI: amqp://user:password@rabbitmq:5672/vhost host: