Comparing KEDA, HPA, VPA & Custom Adapters for Real-World Scaling with Cost, Complexity & Best Practices
| Category | KEDA (Event-driven) | Prometheus-based (Adapter/HPA) | Datadog-based (Cluster Agent) | CloudWatch-based (Adapter/HPA) |
|---|---|---|---|---|
| Primary Function | Event-driven autoscaler (creates HPAs dynamically from external metrics like ALB, SQS, Kafka, etc.) | Uses HPA with Prometheus metrics via adapter (e.g., kube-metrics-adapter or prometheus-adapter) | Uses Datadog metrics (via Cluster Agent) as external metrics for HPA | Uses CloudWatch metrics (via AWS CloudWatch Metrics Adapter) for HPA |
| Metric Source | Multiple external sources: CloudWatch, Prometheus, SQS, Kafka, HTTP, etc. (50+ scalers) | Prometheus time-series metrics (scraped from exporters or apps) | Datadog platform metrics (ingested from AWS, custom apps, APM) | AWS CloudWatch (e.g., ALB metrics, RDS, SQS, Lambda, etc.) |
| Data Flow Model | Pull metrics or events โ internal HPA โ scale | Prometheus scrapes โ adapter โ Kubernetes Metrics API โ HPA | Datadog agent โ Cluster Agent โ External Metrics API โ HPA | CloudWatch Adapter โ External Metrics API โ HPA |
| Setup Complexity | ๐ข Medium (Helm + few YAMLs; no exporter needed) | ๐ต Medium-High (need Prometheus + adapter configuration) | ๐ฃ Medium (if Datadog is already deployed) | ๐ Medium (adapter installation + IAM + mappings) |
| Integration with ALB Traffic | โ
Native (via CloudWatch scaler โ uses RequestCountPerTarget, TargetResponseTime) | โ ๏ธ Requires Prometheus CloudWatch exporter (YACE or similar) | โ Native (Datadog already pulls ALB metrics) | โ Native (direct access to ALB metrics) |
| Supports Scale-to-Zero | โ Yes | โ No (HPA cannot scale to zero) | โ No | โ No |
| Responsiveness / Latency | ~30โ60 seconds (depends on CloudWatch polling) | ~15โ30 seconds (depends on scrape interval) | ~30โ60 seconds (depends on Datadog ingestion) | ~60 seconds (CloudWatch metric delay) |
| Operational Cost | ๐ฒ Low (CloudWatch API calls only) | ๐ฒ๐ฒ Medium (Prometheus infra + storage + exporter costs) | ๐ฒ๐ฒ๐ฒ High (Datadog licensing per host/container) | ๐ฒ Low (CloudWatch API calls) |
| Infrastructure Overhead | Lightweight (1 KEDA controller) | Heavy (Prometheus, exporters, adapter) | Moderate (Datadog Cluster Agent) | Moderate (Adapter deployment) |
| Ease of Maintenance | ๐ข Easy โ one Helm upgrade for all namespaces | ๐ต Moderate โ maintain adapter & Prometheus | ๐ฃ Easy if Datadog already managed | ๐ Moderate โ periodic IAM & adapter updates |
| EKS Auto Mode Compatibility | โ Fully compatible โ scales pods; NodePools handle nodes | โ Compatible | โ Compatible | โ Compatible |
| Multi-Namespace Scaling | โ Native support (Scoped per namespace) | โ Supported | โ Supported | โ Supported |
| Security / IAM | Uses IRSA or static keys for AWS APIs | No AWS permissions required (depends on Prometheus) | Uses Datadog API key & IAM integration | Uses IRSA for AWS CloudWatch read access |
| Supported Triggers / Metrics | 50+ sources (CloudWatch, Kafka, RabbitMQ, HTTP, Redis, MySQL, etc.) | Limited to Prometheus metrics | Limited to Datadog metrics | Limited to AWS metrics |
| Scales on Events (not metrics) | โ Yes | โ No | โ No | โ No |
| Can Combine Multiple Triggers | โ Yes (multi-trigger scaling rules) | โ ๏ธ Only via complex PromQL expressions | โ ๏ธ Limited (Datadog composite metrics) | โ ๏ธ Limited (one metric per HPA) |
| Recommended For | Event-driven / traffic-based workloads (ALB, queues, web APIs) | Resource or app-metric-based workloads | Organizations using Datadog for monitoring & APM | AWS-centric workloads without Prometheus |
| Learning Curve | ๐ข Low | ๐ต Medium | ๐ฃ Low | ๐ Medium |
| Vendor Lock-in | Low (Open Source) | Low (OSS ecosystem) | High (Datadog SaaS) | Medium (AWS-only) |
| Community & Ecosystem | Very active (CNCF Sandbox Project) | Large (K8s ecosystem standard) | Proprietary (Datadog documentation) | AWS-maintained (moderate community) |
| Use with WAF + ALB | โ Seamless (uses ALB TG metrics directly) | โ ๏ธ Need exporter for ALB metrics | โ Seamless (Datadog ALB integration) | โ Seamless (ALB metrics native in CloudWatch) |
| Example Metric | CloudWatch โ RequestCountPerTarget, TargetResponseTime | Prometheus โ nginx_ingress_controller_requests_total | Datadog โ aws.applicationelb.request_count | CloudWatch โ RequestCountPerTarget |
| Scale Behavior Visualization | KEDA Metrics API + Grafana dashboards | Prometheus / Grafana | Datadog Dashboards | CloudWatch Dashboards |
| Maturity (as of 2026) | โญโญโญโญโญ (CNCF Incubating) | โญโญโญโญ | โญโญโญโญ | โญโญโญโญ |
| Overall Recommendation (for EKS + ALB) | โ โ โ Best Option | โ Good (if Prometheus is already in place) | โ๏ธ Suitable for Datadog-native orgs | โ Good fallback if KEDA not allowed |
๐ 1 | Architecture Overview
Flow:Client โ DNS โ WAF โ ALB โ TargetGroup โ EKS Service/Pods
| Layer | Purpose | Key AWS / K8s Component |
|---|---|---|
| Edge Security | Filter malicious traffic | AWS WAF (Web ACL) |
| Load Balancing | Distribute inbound requests | ALB (AWS Load Balancer Controller) |
| Routing | Path/host-based dispatch to namespaces | Kubernetes Ingress |
| Compute | Run workloads | EKS Pods/Deployments |
| Node Capacity | Provision nodes automatically | EKS Auto Mode NodePools (Karpenter) |
| Autoscaling Brain | Adjust replicas dynamically | KEDA / HPA / VPA / Custom Adapter |
With EKS Auto Mode, AWS manages node scaling.
Your responsibility is pod-level scaling โ deciding how many replicas each service needs based on traffic or resource metrics.
๐งฉ 2 | Namespace-Scoped Design Pattern
- Each microservice (e.g.,
booking,auth,medical,telematics) lives in its own namespace. - Each namespace has its Ingress, Service, Deployment, ConfigMap, and autoscaler objects.
- Optionally, multiple namespaces can share one ALB via
alb.ingress.kubernetes.io/group.nameto save cost while keeping per-namespace isolation.
โ๏ธ 3 | Ingress & WAF Setup (Shared ALB Example)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: booking-ing
namespace: booking
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/group.name: shared-edge
alb.ingress.kubernetes.io/group.order: "20"
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:ap-northeast-1:111111111111:regional/webacl/mywebacl/abcd1234
spec:
rules:
- host: api.example.com
http:
paths:
- path: /booking
pathType: Prefix
backend:
service:
name: booking-svc
port:
number: 80
Each namespace can repeat this pattern using different paths (/auth, /legal, etc.) but share the same group.name โ one ALB under one WAF.
๐ 4 | Autoscaling Options for Pod Level Control
Below are five viable mechanisms for pod autoscaling inside EKS.
| # | Method | Scaling Source | Scales To Zero | Works with ALB Metrics | Typical Latency | Setup Time | Maint. Effort | Approx. Cost* | Skill Level |
|---|---|---|---|---|---|---|---|---|---|
| 1 | KEDA | External events (CloudWatch ALB, SQS, Prometheus, etc.) | โ | โ (native scaler) | 30-60 s | โ๏ธ Medium | ๐งฉ Low (once installed) | ๐ฒ๐ฒ CloudWatch API calls | Intermediate |
| 2 | HPA | CPU / memory / custom metrics | โ | โ ๏ธ via adapter | 15-30 s | โ๏ธ Low | ๐งฉ Low | ๐ฒ free | Beginner |
| 3 | VPA | Internal resource usage | โ | โ | N/A | โ๏ธ Medium | ๐งฉ Low | ๐ฒ free | Intermediate |
| 4 | Custom Metric Adapter | Prometheus / CloudWatch | โ | โ with manual mapping | 45-60 s | โ๏ธ High | ๐งฉ High | ๐ฒ๐ฒ metrics infra | Advanced |
| 5 | Manual Scaling | Human input | โ | โ | N/A | โ๏ธ Instant | ๐งฉ High Opex | ๐ฒ none | Basic |
* Cost = relative AWS service charges + operational overhead
๐งฎ 5 | Detailed Analysis of Each Approach
๐น A | KEDA (Event-Driven Autoscaler)
How it works:
KEDA reads external metrics (CloudWatch ALB RequestCountPerTarget, TargetResponseTime, SQS depth, PromQL queries, etc.) and creates an internal HPA.
Pros
- Supports 50 + scalers (AWS, Azure, Kafka, Prometheus, etc.).
- Scales to zero during idle.
- Simple YAML (
ScaledObject) per Deployment. - Works seamlessly with EKS Auto Mode and NodePools.
- Natively integrates with CloudWatch ALB metrics.
Cons
- Extra component to operate.
- CloudWatch polling โ small metric costs and โ 1 min delay.
- Needs IRSA permissions for CloudWatch API.
Setup time: โ 1 hr (Helm install + ScaledObject YAMLs)
Maintenance: Low (central Helm upgrade + namespace YAMLs)
Recommended for: Multi-namespace EKS clusters with real-traffic scaling.
๐น B | HPA (Native Horizontal Pod Autoscaler)
How it works:
Built into Kubernetes; scales based on CPU and memory by default.
Can also use custom metrics with an adapter.
Pros
- Native, stable, zero extra components.
- Predictable behavior and fine-grained control.
Cons
- Default metrics = CPU / memory only.
- Cannot scale to zero.
- Needs a metric adapter to use ALB metrics.
- Not event-driven; reactive after load hits CPU.
Setup time: โ 30 min
Maintenance: Minimal
Recommended for: Steady workloads or CPU-bound apps.
๐น C | VPA (Vertical Pod Autoscaler)
How it works:
Adjusts CPU and memory requests/limits per pod automatically.
Pros
- Prevents over/under-provisioning.
- Complements KEDA/HPA.
Cons
- No replica count scaling.
- Not suited for traffic bursts.
Setup time: โ 45 min
Maintenance: Low
Recommended for: Batch or steady apps to optimize resources.
๐น D | Custom Metric Adapters (Prometheus / CloudWatch)
How it works:
Deploy an external-metrics adapter exposing selected metrics to HPA.
HPA then scales on those metrics.
Pros
- Fine control; use any metric you own.
- Integrates into existing monitoring plane.
Cons
- Complex to deploy and maintain.
- Harder to debug.
- No scale-to-zero.
- Usually delayed by scrape interval + adapter polling.
Setup time: 1 โ 2 hrs
Maintenance: High
Recommended for: Large orgs with centralized Prometheus or Datadog.
๐น E | Manual Scaling
kubectl scale deployment <name> --replicas=N
Pros: 100 % control, simple to understand.
Cons: No automation; wastes capacity; high operational risk.
Use only for: testing or stable low-traffic sites.
๐ก 6 | KEDA Setup Walkthrough (for EKS + ALB)
- Install KEDA
helm repo add kedacore https://kedacore.github.io/charts helm install keda kedacore/keda -n keda --create-namespace - Enable IRSA (for CloudWatch)
eksctl utils associate-iam-oidc-provider --cluster my-eks --approve - IAM Policy
{ "Version":"2012-10-17", "Statement":[{"Effect":"Allow","Action":[ "cloudwatch:GetMetricData","cloudwatch:GetMetricStatistics", "cloudwatch:ListMetrics","cloudwatch:DescribeAlarms" ],"Resource":"*"}] } - ServiceAccount + TriggerAuthentication
apiVersion: v1 kind: ServiceAccount metadata: name: svc-traffic-autoscale namespace: booking annotations: eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/eks-traffic-autoscale --- apiVersion: keda.sh/v1alpha1 kind: TriggerAuthentication metadata: name: alb-cw-auth namespace: booking spec: podIdentity: provider: aws - ScaledObject
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: booking-traffic namespace: booking spec: scaleTargetRef: name: booking-deployment minReplicaCount: 2 maxReplicaCount: 30 triggers: - type: aws-cloudwatch authenticationRef: name: alb-cw-auth metadata: namespace: AWS/ApplicationELB metricName: RequestCountPerTarget dimensionName: TargetGroup dimensionValue: targetgroup/k8s-xyz/abc123456 statistic: Sum period: "60" metricUnit: Count targetValue: "100" - Observe Scaling
kubectl get hpa -n booking kubectl get pods -n booking -w
๐ 7 | Performance & Cost Considerations
| Factor | KEDA | HPA | VPA | Custom Adapter |
|---|---|---|---|---|
| Responsiveness | 30-60 s | 15-30 s | N/A | 45-60 s |
| Infra Cost | Low (CloudWatch polling) | None | None | Medium (Prometheus infra) |
| Setup Overhead | Medium | Low | Medium | High |
| Maintenance | Low | Low | Low | High |
| Complexity | Medium | Low | Low | High |
| Best for | Traffic / Event driven | CPU/Mem | Resource tuning | Centralized metrics |
| Scale-to-Zero | โ | โ | โ | โ |
๐ง 8 | Decision Matrix
| Requirement | Best Choice | Reason |
|---|---|---|
| Real ALB traffic scaling | KEDA | Direct CloudWatch integration |
| CPU/memory bound apps | HPA | Native simple autoscaler |
| Optimize pod resources over time | VPA | Adjusts requests/limits |
| Central metrics team wants Prometheus-based control | Custom Adapter + HPA | Full metric plane |
| Low-traffic or manual control | Manual | No automation needed |
๐งฐ 9 | Combining Approaches
A production-grade EKS stack often mixes them:
| Layer | Tool | Role |
|---|---|---|
| Replica Scaling | KEDA + HPA | Respond to traffic & CPU |
| Resource Tuning | VPA | Adjust limits automatically |
| Node Scaling | EKS Auto Mode (NodePools) | Provide capacity |
| Monitoring | CloudWatch + AMP + Grafana | Visibility into metrics |
๐ 10 | Security and Auth Notes
- Keep Firebase OIDC at pod level (not ALB listener), which avoids auth redirect limits.
- Enable IRSA for KEDA & pods requiring AWS API access.
- WAF rules protect ALB from volumetric attacks before KEDA reacts.
- Monitor 5xx errors + TargetResponseTime to guard against scaling loops.
๐งญ 11 | Final Recommendation
For your multi-namespace, WAF-protected, ALB-routed EKS cluster running in Full Auto Mode,
KEDA is the best fit for traffic-driven autoscaling:
- Event-driven and responsive to real user load.
- Scales independently per namespace/service.
- Integrates cleanly with EKS NodePools for capacity.
- Minimizes cost via scale-to-zero and fine-grained rules.
Use HPA as a fallback for CPU-based logic, VPA for optimization, and custom adapters only when you already maintain Prometheus or Datadog metric infrastructure.
๐ Summary Matrix
| Dimension | Best Fit |
|---|---|
| Speed to implement | HPA |
| Responsiveness to traffic | KEDA |
| Ease of maintenance | KEDA / HPA |
| Cost efficiency | KEDA (scale-to-zero) |
| Complex metric logic | Custom Adapter |
| Resource tuning | VPA |
๐ References & Further Reading
AWS Blog โ Autoscaling EKS with KEDA & CloudWatch
AWS Docs โ EKS Auto Mode & NodePools
KEDA Docs โ CloudWatch Scaler
SpectroCloud โ Kubernetes Autoscaling Patterns: HPA, VPA & KEDA
โ
Final Takeaway:
If you need hands-off, event-driven, traffic-aware, namespace-isolated scaling for an ALB-fronted EKS cluster,
KEDA + EKS Auto Mode (NodePools) is the modern production-grade combinationโ
balancing performance, cost, and operational simplicity for any multi-service cloud platform.
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services โ all in one place.
Explore Hospitals
This is a very well-written and practical guide to traffic-driven autoscaling on Kubernetes โ comparing tools like KEDA, HPA, VPA, and custom adapters in a clear, understandable way. Explaining when to use each scaling method based on load patterns, resource usage, or event triggers helps teams make informed decisions rather than blindly copying generic autoscaling configurations. I especially appreciate how the article balances theoretical advantages with real-world trade-offs so that readers can pick what best fits their workloads. A great resource for anyone running microservices in production and looking to optimize performance and cost with dynamic scaling.
Really liked how you broke down autoscaling โ you made KEDA vs HPA vs VPA way easier to understand than most guides out there. The traffic-based examples were super helpful too. Awesome write-up.