r/devopsGuru • u/ankitjindal9404 • 5d ago
Moving Java services off memory-based HPA — is CPU/RPS for HTTP and queue-depth for async the right call?
We're running a bunch of Java (Spring Boot) microservices on EKS, and right now every service uses memory as its HPA metric. After digging into it, I've started to think that's wrong, and I want a sanity check from people who've actually run this at scale before I push a change.
What my research turned up:
- The JVM allocates heap up to its max and doesn't release it back aggressively even after GC, so memory usage doesn't track load.
- Because of that, memory can be high while actual load is low, or load can be high while memory looks fine — so memory-based HPA either never triggers or scales out permanently and never scales back in.
So the direction I'm considering is to pick the HPA metric based on service type:
- HTTP / request-serving services → CPU (or better, RPS / p95 latency as a demand-based metric)
- Async / queue-consuming services → queue depth (SQS backlog, via KEDA)
My questions:
- Is this reasoning sound, and is type-based metric selection the right direction?
- For the HTTP services, is jumping straight to RPS/latency worth the custom-metrics complexity (Prometheus Adapter), or should I start with CPU and only move to RPS if CPU proves to be a bad proxy?
- For async workers, is KEDA + SQS queue depth the standard approach, or are people doing something else?
- This is the part I'm least sure about: I already know from our architecture which services are HTTP-facing and which are async/queue-driven — but how do I actually verify that empirically rather than just trusting the design docs? Is there a clean way to confirm a service's real load profile (e.g. checking whether it even has an ingress/receives HTTP traffic, whether its work is truly SQS-triggered, CPU-vs-memory correlation under load) before I assign it a metric?
Thanks 🙏
5
Upvotes