Why Big Companies Are Dropping Tomcat for Undertow in Spring Boot

Large enterprises are increasingly replacing Spring Boot’s default embedded Tomcat with Undertow because Undertow delivers superior memory efficiency, higher concurrency, lower latency, and more flexible configuration, as demonstrated by detailed performance benchmarks, architectural analysis, and real‑world migration case studies presented in this article.

IT Services Circle
IT Services Circle
IT Services Circle
Why Big Companies Are Dropping Tomcat for Undertow in Spring Boot

Preface

We discuss why more large companies prohibit the use of Spring Boot's default Tomcat and mandate Undertow.

1. Spring Boot's Default Choice and Current Situation

Spring Boot, the most popular Java framework, embeds Tomcat by default, leading many developers to adopt a "out‑of‑the‑box" approach. However, many enterprises are switching to Undertow in production.

2. Performance Comparison

2.1 Memory Usage Comparison

Test results under identical conditions:

Container   Startup Memory   Heap   Non‑Heap   Thread Memory
Tomcat      120MB            80MB   25MB       15MB
Undertow     85MB             60MB   15MB       10MB
Optimization -29%            -25%   -40%       -33%

Undertow shows clear memory advantages, which translate into significant cost savings at scale.

2.2 Concurrency Handling

Concurrent performance test code:

// Performance test example
@SpringBootTest
class WebContainerPerformanceTest {
    @Test
    void testConcurrentPerformance() {
        // Simulate 1000 concurrent users for 30 seconds
        LoadTest loadTest = LoadTest.configure()
            .threads(1000)
            .duration(30, TimeUnit.SECONDS)
            .build();
        TomcatResult tomcatResult = loadTest.runWithTomcat();
        UndertowResult undertowResult = loadTest.runWithUndertow();
        System.out.println("QPS - Tomcat: " + tomcatResult.getQps());
        System.out.println("QPS - Undertow: " + undertowResult.getQps());
        System.out.println("Avg latency - Tomcat: " + tomcatResult.getAvgResponseTime());
        System.out.println("Avg latency - Undertow: " + undertowResult.getAvgResponseTime());
    }
}

Typical results:

Tomcat : QPS 8500, average latency 15 ms

Undertow : QPS 12000, average latency 8 ms

3. Underlying Architecture Differences

3.1 Tomcat Architecture Design

Tomcat uses a traditional BIO/NIO connector architecture, which is relatively heavyweight.

Tomcat architecture diagram
Tomcat architecture diagram

3.2 Undertow Architecture Design

Undertow is built on the modern XNIO foundation and features:

IO thread and worker thread separation : IO threads handle network I/O, worker threads handle business logic.

Event‑driven model : Callback‑based event handling.

Zero‑copy capability : Direct buffers reduce memory copying.

Undertow architecture diagram
Undertow architecture diagram

4. Memory Management

4.1 Direct Memory Usage

// Undertow memory management example
public class UndertowMemoryManagement {
    // Use direct buffer to handle requests
    public void handleRequest(HttpServerExchange exchange) {
        ByteBuffer buffer = exchange.getConnection().getBufferPool().allocate();
        try {
            readRequestData(exchange, buffer);
            processRequest(buffer);
            writeResponse(exchange, buffer);
        } finally {
            exchange.getConnection().getBufferPool().free(buffer);
        }
    }
    // Tomcat typically performs multiple memory copies
    public void tomcatHandleRequest(Request request, Response response) {
        byte[] inputData = readInputStream(request.getInputStream());
        byte[] outputData = processData(inputData);
        response.getOutputStream().write(outputData);
    }
}

4.2 Connection Pool Optimization

# Undertow configuration example
server:
  undertow:
    threads:
      worker: 16
      io: 4
    buffer-size: 1024
    direct-buffers: true
    max-connections: 10000
    max-http-post-size: 10485760

Tomcat equivalent configuration (for comparison):

# Tomcat configuration example
server:
  tomcat:
    max-connections: 10000
    max-threads: 200
    min-spare-threads: 10
    max-http-post-size: 10485760
    connection-timeout: 20000

5. Concurrency Model

5.1 Undertow XNIO Architecture

// XNIO worker model example
public class XNIOWorkerModel {
    public void demonstrateWorkerModel() {
        XnioWorker worker = Xnio.getInstance().createWorker(
            OptionMap.create(Options.THREAD_DAEMON, true)
        );
        // IO thread handles network events
        worker.getIoThread().execute(() -> handleIOReadyEvents());
        // Worker thread handles business logic
        worker.getWorkerThreadPool().execute(() -> executeBusinessLogic());
    }
}

5.2 Tomcat Thread Model Comparison

Tomcat thread model diagram
Tomcat thread model diagram

Issues under extreme concurrency:

High thread‑context‑switch overhead

Threads block waiting for resources

Memory usage grows linearly with thread count

6. Configuration Flexibility

6.1 Fine‑Grained Configuration Capability

@Configuration
public class UndertowConfig {
    @Bean
    UndertowServletWebServerFactory undertowServletWebServerFactory() {
        UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
        factory.addBuilderCustomizers(builder -> {
            // Enable HTTP/2
            builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);
            // Buffer settings
            builder.setSocketOption(Options.RECEIVE_BUFFER, 1024 * 16);
            builder.setSocketOption(Options.SEND_BUFFER, 1024 * 64);
            // Thread pool
            builder.setIoThreads(Runtime.getRuntime().availableProcessors());
            builder.setWorkerThreads(200);
            // Connection limits
            builder.setServerOption(UndertowOptions.MAX_CONNECTIONS, 10000);
        });
        return factory;
    }
}

6.2 Handler Chain Mechanism

public class CustomHandler implements HttpHandler {
    private final HttpHandler next;
    public CustomHandler(HttpHandler next) { this.next = next; }
    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        long startTime = System.currentTimeMillis();
        try {
            preHandle(exchange);
            next.handleRequest(exchange);
        } finally {
            postHandle(exchange, startTime);
        }
    }
    private void preHandle(HttpServerExchange exchange) {
        if (!checkAuthentication(exchange)) {
            exchange.setStatusCode(401);
            exchange.endExchange();
            return;
        }
        logRequest(exchange);
    }
}

This flexible chain allows deep customization of request processing.

7. Practical Case Study

7.1 Container Migration in an E‑commerce Platform

Before migration (Tomcat):

QPS 8000

Average latency 25 ms

Memory usage 2 GB

CPU usage 85 %

After migration (Undertow):

QPS 15000 (+87 %)

Average latency 12 ms (‑52 %)

Memory usage 1.2 GB (‑40 %)

CPU usage 65 % (‑23 %)

7.2 Configuration Optimization Example

# Production Undertow optimization
server:
  undertow:
    io-threads: 8
    worker-threads: 200
    direct-buffers: true
    buffer-size: 16384
    max-connections: 10000
    max-http-post-size: 10485760
    no-request-timeout: 60000
    drain-wait-time: 20000
    port: 8080
    compression:
      enabled: true
      mime-types: text/html,text/xml,text/plain,application/json

8. How to Migrate?

8.1 Maven Configuration Adjustment

<!-- Exclude Tomcat -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- Include Undertow -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

8.2 Migration Considerations

Servlet API compatibility : Ensure code uses standard Servlet APIs.

WebSocket configuration : Undertow’s WebSocket setup differs from Tomcat’s.

SSL configuration : Certificates and SSL settings may need adjustment.

Session management : Verify compatibility for distributed sessions.

Summary

Performance Advantages

Higher concurrency handling : XNIO suits high‑load scenarios.

Lower memory footprint : Direct buffers reduce usage.

Better response times : Event‑driven model cuts latency.

Resource Efficiency

Fine‑grained resource control : Thread pools and buffers are configurable.

Scalability : Fits cloud‑native and container deployments.

Reduced operational cost : Fewer servers and lower resource consumption.

Modern Architecture

Advanced concurrency model : Aligns with modern hardware.

Extensible handler chain : Deep customization possible.

Future‑ready : Prepared for HTTP/2, QUIC, etc.

Business‑Driven Needs

Large‑scale deployment : Microservice architectures demand efficient containers.

Cost control : Performance gains translate to cost savings.

Technical competitiveness : Staying on the cutting edge of the tech stack.

My recommendation: for new projects—especially those expecting high concurrency—prefer Undertow. For existing projects encountering performance bottlenecks, consider migrating to Undertow.
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.

Spring BootTomcatundertow
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

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.