Backend Development 26 min read

JVM Parameter Tuning for a Platform Handling 1 Million Daily Login Requests on an 8 GB Node

This article presents a comprehensive, step‑by‑step guide on estimating capacity, selecting and configuring garbage collectors, sizing heap, young and survivor spaces, tuning thread stacks, and adding diagnostic options for a Java service that must handle one million login requests per day on a server with 8 GB of memory.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
JVM Parameter Tuning for a Platform Handling 1 Million Daily Login Requests on an 8 GB Node

JVM Parameter Tuning for a Platform Handling 1 Million Daily Login Requests on an 8 GB Node

When a new system is about to go live, it is essential to estimate the required server configuration and JVM memory parameters based on the expected workload. The following eight steps outline a systematic approach to capacity planning, GC selection, memory partitioning, and diagnostic configuration.

Step 1: Capacity Planning for a New System

Calculate the per‑second object allocation, estimate the memory consumption of the young generation, and decide how many machines are needed to keep GC pauses acceptable. For a login service with a peak of 100 requests per second, a 3‑node cluster of 4 CPU / 8 GB machines with a 4 GB heap (2 GB young generation) can comfortably handle the load.

Step 2: Choosing the Garbage Collector

Two main trade‑offs exist: throughput vs. latency. Larger heaps increase throughput but also lengthen pause times, while smaller heaps reduce pause duration at the cost of throughput. The choice of collector should match the service’s performance goals.

GC Design Considerations

The JVM must stop all application threads (Stop‑The‑World) during certain phases of GC.

Young‑generation collections are frequent and benefit from parallel copy algorithms.

Old‑generation collections aim to minimize fragmentation.

CMS vs. G1

Current mainstream configurations use ParNew for the young generation combined with CMS for the old generation, or the newer G1 collector for larger heaps. G1 is the officially recommended collector for future Java versions.

Step 3: Planning Heap Partition Ratios

The most critical JVM parameters are -Xms (initial heap size) and -Xmx (maximum heap size). A common rule of thumb is to allocate half of the physical memory to the heap. The young‑generation size ( -Xmn ) is flexible: for stateless web services it can be up to 75 % of the heap, while stateful services often use a 1/3 ratio.

JVM Parameter

Description

Default

Recommended

-Xms

Initial heap size

OS memory / 64

OS memory / 2

-Xmx

Maximum heap size

OS memory / 4

OS memory / 2

-Xmn

Young generation size

≈ 1/3 of heap

Sun recommendation 3/8 (adjust per workload)

-Xss

Thread stack size

Depends on JDK & OS

512 KB–1 MB (usually 1 MB)

For an 8 GB node, allocating 4 GB to the JVM (e.g., -Xms3072M -Xmx3072M ) leaves enough memory for the OS and other processes.

Step 4: Tuning Survivor Space and Object Age

To avoid premature promotion of short‑lived objects, increase the survivor space (e.g., -Xmn2048M -XX:SurvivorRatio=8 ) so that the Eden‑to‑Survivor ratio is 8:1:1, giving roughly 1.6 GB Eden and 0.2 GB each survivor. Adjust -XX:MaxTenuringThreshold (e.g., 5) to control when objects move to the old generation.

Step 5: Thread Stack Size

Set -Xss1M (or 512 KB) depending on the expected number of concurrent threads; hundreds of threads can consume hundreds of megabytes of stack memory.

Step 6: Direct Allocation of Large Objects

Use -XX:PretenureSizeThreshold=1M to allocate objects larger than 1 MB directly in the old generation, reducing survivor‑space pressure.

Step 7: CMS Old‑Generation Optimisation

Typical JVM flags for a ParNew+CMS configuration:

-Xms3072M -Xmx3072M -Xmn2048M -Xss1M \
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M \
-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 \
-XX:PretenureSizeThreshold=1M \
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC \
-XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly \
-XX:+AlwaysPreTouch

Key points:

-Xms and -Xmx are set equal to avoid heap resizing.

-XX:+UseParNewGC and -XX:+UseConcMarkSweepGC provide low‑latency collection for young and old generations.

-XX:CMSInitiatingOccupancyFraction=70 triggers CMS when old‑gen usage reaches 70 %.

-XX:+AlwaysPreTouch forces the OS to allocate physical memory up front.

Step 8: Diagnostic Options for OOM and GC Logging

Enable heap dumps and detailed GC logs to aid post‑mortem analysis:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=${LOGDIR}/
-Xloggc:/var/log/jvm/gc.log
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps

What Is ZGC?

ZGC (Z Garbage Collector) is a low‑latency collector introduced in JDK 11, using region‑based memory, read barriers, and colored pointers to achieve pause times under 10 ms even for multi‑terabyte heaps.

How to Choose a Garbage Collector

For small heaps (< 100 MB) or single‑core machines, use the Serial collector ( -XX:+UseSerialGC ).

For throughput‑oriented workloads, use the Parallel collector ( -XX:+UseParallelGC ).

For latency‑sensitive services, consider G1, CMS, or ZGC ( -XX:+UseG1GC , -XX:+UseConcMarkSweepGC , -XX:+UseZGC ).

Metaspace vs. Permanent Generation

Java 8 replaced the Permanent Generation with Metaspace, moving class metadata out of the heap into native memory. This eliminates the fixed -XX:PermSize / -XX:MaxPermSize limits and reduces the risk of OutOfMemoryError: PermGen space . Metaspace size can be tuned with -XX:MetaspaceSize and -XX:MaxMetaspaceSize .

Summary of Tuning Process

Estimate business load and required machine count.

Allocate heap (≈ 50 % of physical memory) and size the young generation according to workload characteristics.

Select a collector: ParNew+CMS for low‑latency, G1 for large‑heap throughput‑oriented services.

Fine‑tune survivor ratios, tenuring thresholds, and large‑object thresholds to keep short‑lived objects in the young generation and avoid frequent Full GCs.

Enable diagnostic flags for OOM dumps and GC logs.

Remember that code‑level and architectural optimisations are usually more effective than JVM tuning alone.

By following these steps before launch, you can configure the JVM to achieve stable performance for a high‑traffic login service.

JavaJVMMemory ManagementGarbage CollectionPerformance TuningCMSG1
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.