Member-only story
Forget Heap Tuning — One JVM Upgrade Cut Our Pod Memory 33%
For 3 weeks I tuned G1 flags to shrink our Java pods. They stayed at 3 GiB.
Then we moved from JDK 21 to JDK 25, switched on a setting that JDK 21 does not have, and the same pods now run in 2 GiB.
That is 33% less memory per pod, across 40 pods, without touching application code.
The Flags That Did Almost Nothing
Our service is an ordinary Java API. Lots of maps, lots of small DTOs, a lookup cache that never gets very big. Every time a pod got OOMKilled at peak, the limit went up, and 3 GiB became the number nobody wanted to touch.
So I did what everyone does. I opened the GC logs and started turning knobs:
JAVA_OPTS="-XX:MaxRAMPercentage=70 \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=150 \
-XX:G1HeapRegionSize=4m \
-XX:InitiatingHeapOccupancyPercent=35 \
-XX:G1ReservePercent=15"Each flag moved something. Pause times shifted. Concurrent cycles started earlier or later. But the number that mattered, how much memory a pod needed to survive peak traffic, barely changed.
It took me too long to see why. Heap tuning decides how much room your objects get and when the garbage is collected. It cannot make the live objects smaller. Our live set was…







