How Much Heap Memory Does Each SpringBoot HTTP Request Really Use?

This article explains how to measure the exact heap memory consumption of individual SpringBoot HTTP and RPC requests by calculating required memory from request size, configuring JVM GC parameters, creating a JMeter test plan, collecting GC logs, and analyzing results to identify optimization opportunities.

Top Architect
Top Architect
Top Architect
How Much Heap Memory Does Each SpringBoot HTTP Request Really Use?

Background

In production environments it is often necessary to perform full‑stack load testing, tune GC parameters, and optimise JVM memory allocation. Knowing the heap memory required for a single RPC or HTTP request allows you to calculate the total heap needed for a given concurrency level and to estimate GC frequency.

Experiment Idea

The goal is to determine how much heap memory a single HTTP request consumes in a SpringBoot application and to observe the impact of request size, logging, and GC configuration.

Key Steps

Create a SpringBoot application (version 2.5.4).

Add a POST endpoint ( /create ) to receive an order and a GET endpoint ( /gc ) that triggers System.gc() .

@Slf4j
@RestController
public class TestController {
    private AtomicLong count = new AtomicLong(0);

    @ResponseBody
    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String create(@RequestBody Order order) {
        //log.warn("Received order cnt{}:{}", count.getAndIncrement(), order);
        return "ok";
    }

    @ResponseBody
    @RequestMapping(value = "gc", method = RequestMethod.GET)
    public String gc() {
        System.gc();
        return "ok";
    }
}

Configure JMeter:

Create a Thread Group with 10 threads, each looping 2000 times (total 20 000 HTTP calls).

Add an HTTP Request Defaults element to set the target URL.

Add an HTTP Header Manager with Content-Type: application/json.

Add an HTTP Request sampler that posts a small JSON payload (≈50 bytes).

Start the SpringBoot application with explicit GC logging and memory settings:

java -server \
    -Xmx4g -Xms4g -XX:SurvivorRatio=8 -Xmn2g \
    -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g -XX:MaxDirectMemorySize=1g \
    -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCCause -XX:+PrintGCDetails \
    -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution \
    -XX:+UnlockDiagnosticVMOptions -XX:ParGCCardsPerStrideChunk=32768 \
    -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -XX:+UseParNewGC \
    -XX:ParallelCMSThreads=6 -XX:+CMSClassUnloadingEnabled \
    -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelInitialMarkEnabled \
    -XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+PrintHeapAtGC \
    -XX:CMSFullGCsBeforeCompaction=1 -XX:CMSInitiatingOccupancyFraction=70 \
    -XX:+UseCMSInitiatingOccupancyOnly -XX:+PrintReferenceGC \
    -XX:+ParallelRefProcEnabled -XX:ReservedCodeCacheSize=256M \
    -Xloggc:/Users/testUser/log/gc.log \
    -jar target/activiti-0.0.1-SNAPSHOT.jar

Before the load test, manually trigger a GC to clear warm‑up objects: curl http://localhost:8080/gc Run the JMeter test plan (20 000 HTTP calls). The GC log records the Eden space usage before and after the test.

Result Analysis

After the test the GC log shows that the Eden space used by the 20 000 HTTP calls equals the total heap allocated for those requests. Key observations:

Even with a tiny request body (≈50 characters), each HTTP call allocated about 34 KB of heap.

Increasing the detail field to 1 200 characters raised the per‑request allocation to 36 KB , roughly matching the payload size.

Adding a log statement inside the controller increased the average allocation to 56 KB , indicating that log object creation significantly impacts memory usage.

Removing the detail field dropped the allocation back to 35.7 KB .

These numbers suggest that SpringBoot creates several internal objects per request, and that logging overhead can dominate memory consumption.

Practical Implications

In a real‑world service the per‑request heap usage can be much higher (0.5 MB–1 MB for RPC calls) due to complex business logic, multiple downstream calls, database access, caching, and extensive logging. For a server handling 500 requests per second, this translates to roughly 15 GB of memory allocated per minute, requiring frequent young‑generation GCs.

To keep GC pauses low and improve throughput, it is advisable to:

Limit the size of individual log messages.

Reuse objects where possible.

Tune GC parameters based on measured allocation rates.

Conclusion

The experiment demonstrates that a simple SpringBoot HTTP request can consume around 34 KB of heap, but real applications often exceed this due to additional processing and logging. Accurate measurement and careful tuning are essential for high‑performance backend services.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMMemory OptimizationJMeterSpringBootgcperformance-testing
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

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.