JVM G1 and ZGC Tuning on AWS Corretto for ECS and EKS
Quick summary: A heap that is too small triggers G1 humongous allocations, and one that is too large balloons pause times on Graviton. Corretto on ECS/EKS/Lambda Java, and when ZGC generational beats G1 for API heaps.
Key Takeaways
- A heap that is too small triggers G1 humongous allocations, and one that is too large balloons pause times on Graviton
- Corretto on ECS/EKS/Lambda Java, and when ZGC generational beats G1 for API heaps
- As of June 2026, Amazon Corretto 21+ defaults to G1 on server classpaths
- ZGC with generational mode targets sub-ms pauses on large heaps (>8 GB)
- Enable GC logs to CloudWatch via sidecar or JFR snapshots on load test

Table of Contents
As of June 2026, Amazon Corretto 21+ defaults to G1 on server classpaths. ZGC with generational mode targets sub-ms pauses on large heaps (>8 GB).
Symptoms, mechanisms, and AWS controls
| Production symptom | Mechanism | AWS control |
|---|---|---|
| Periodic latency spikes | G1 evacuation pause | Switch to ZGC generational on Corretto 21+ |
| OOM despite free heap | Metaspace or direct buffer leak | ECS/EKS memory limits, CloudWatch Container Insights |
| GC logs missing in prod | No unified observability | ADOT Java agent → AMP, JFR streaming on EKS |
My recommendation: on Corretto 21+, default new latency-sensitive services to ZGC generational and keep G1 only for throughput-bound batch workloads.
Benchmark pattern (hypothetical workload): Corretto 21 on ECS Fargate 4vCPU/8GB, G1 default: 180ms GC pause p99; ZGC generational (-XX:+UseZGC -XX:+ZGenerational on JDK 21; generational is the default from JDK 23): 4ms p99 pause at same heap, 6% higher CPU overhead; throughput-sensitive batch job favors G1.
Tuning signals on AWS
| Signal | Action |
|---|---|
Pause Young high | Increase -Xmx or reduce allocation rate |
| Humongous objects | Object size > 50% G1 region; fix batch sizes |
| Container OOM | -XX:MaxRAMPercentage=75 on ECS/EKS cgroups |
Lambda Java: minimize heap. Cold start includes JVM init, so consider SnapStart (where supported) or Graal native for a latency SLO.
AWS services map
| Need | Service | Skip when |
|---|---|---|
| Low-latency JVM runtime | Corretto 21 on ECS/EKS | Sub-millisecond C++ services |
| GC telemetry | AMP + ADOT Java instrumentation | Batch jobs with multi-minute pauses acceptable |
| Heap sizing | Fargate task memory / EKS limits | Lambda with 128MB fixed heap |
What to do this week
- Enable GC logs to CloudWatch via sidecar or JFR snapshots on load test.
- Match container memory limit to heap + native + metaspace headroom.
- A/B G1 vs ZGC on same
c7gtask size with identical load.
More in this track
Part of the Engineering Guides library (June 2026).
- Next: Part 2
- Browse tracks: Engineering Guides hub
What this guide doesn’t cover
Virtual threads are covered in part 2 of the runtime track.
Frequently asked questions
When should I keep G1 instead of ZGC on Corretto 21?
Why did the container OOM with free heap?
Should I tune GC on Lambda Java the same way as ECS?
How do I see GC in production without log-flooding CloudWatch?

AWS Cloud Architect & AI Expert
AWS-certified cloud architect and AI expert with deep expertise in cloud migrations, cost optimization, and generative AI on AWS.




