Understanding Spring Boot's Request Handling Limits Through Tomcat Configuration

This article explains how Spring Boot's request capacity is determined by Tomcat's configuration parameters, demonstrates the impact of min‑spare, max threads, max‑connections, and accept‑count through a small example, and discusses concurrency pitfalls caused by singleton beans.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Understanding Spring Boot's Request Handling Limits Through Tomcat Configuration

Spring Boot runs on an embedded Tomcat container, so the number of requests it can handle is essentially limited by Tomcat's configuration.

The default Tomcat settings are defined in spring-configuration-metadata.json and mapped to the class org.springframework.boot.autoconfigure.web.ServerProperties.

Four key parameters affect request handling:

server.tomcat.threads.min-spare : minimum number of worker threads (default 10).

server.tomcat.threads.max : maximum number of worker threads (default 200).

server.tomcat.max-connections : maximum number of simultaneous connections (default 8192).

server.tomcat.accept-count : length of the waiting queue (default 100).

Using a restaurant analogy, a request is a customer, min‑spare threads are permanent chefs, max threads are total chefs (permanent + temporary), max‑connections are seats, and accept‑count is the number of stools at the entrance.

The effective maximum number of requests Spring Boot can process equals max-connections + accept-count; any excess requests are dropped.

Example configuration (application.yml):

server:
  tomcat:
    threads:
      # minimum threads
      min-spare: 10
      # maximum threads
      max: 15
    # maximum connections
    max-connections: 30
    # maximum waiting count
    accept-count: 10

Simple controller:

@GetMapping("/test")
public Response test1(HttpServletRequest request) throws Exception {
    log.info("ip:{}, thread:{}", request.getRemoteAddr(), Thread.currentThread().getName());
    Thread.sleep(500);
    return Response.buildSuccess();
}

Running a test with 100 concurrent requests (using Apifox) shows that 60 requests are discarded because max-connections + accept-count = 40. With a maximum of 15 threads, 25 requests wait, then are processed in three batches of 15, 15, and 10.

Summary: If concurrent requests are below server.tomcat.threads.max, they are handled immediately; excess requests wait up to accept-count; requests beyond max-connections + accept-count are dropped.

Extended discussion: concurrency issues

In Spring, beans are singleton by default, so shared mutable state (e.g., a global cookSum variable) can lead to race conditions where multiple threads read the same value, increment, and write back, resulting in lost updates. The following code illustrates the problem:

private int cookSum = 0;

@GetMapping("/test")
public Response test1(HttpServletRequest request) throws Exception {
    // simulate cooking
    cookSum += 1;
    log.info("cooked {} dishes", cookSum);
    Thread.sleep(500);
    return Response.buildSuccess();
}

Resolving such issues requires proper synchronization (e.g., locking), which is beyond the scope of this article.

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.

performanceTomcatspring-boot
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

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.