Spring Boot
Jetty Configuration
Java
Web Server
DevOps

How to configure Jetty in spring-boot easily?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Spring Boot makes Jetty configuration easier than it used to be because the embedded server is just another starter dependency. In most cases, "configure Jetty" means three separate tasks: swap out Tomcat, apply server settings, and optionally customize Jetty-specific internals. Once those are separated, the setup is straightforward.

Replace Tomcat With Jetty

If you start from spring-boot-starter-web, Tomcat is included by default. Exclude it and add Jetty instead.

xml
1<dependencies>
2  <dependency>
3    <groupId>org.springframework.boot</groupId>
4    <artifactId>spring-boot-starter-web</artifactId>
5    <exclusions>
6      <exclusion>
7        <groupId>org.springframework.boot</groupId>
8        <artifactId>spring-boot-starter-tomcat</artifactId>
9      </exclusion>
10    </exclusions>
11  </dependency>
12
13  <dependency>
14    <groupId>org.springframework.boot</groupId>
15    <artifactId>spring-boot-starter-jetty</artifactId>
16  </dependency>
17</dependencies>

After that, Boot will start Jetty automatically because it detects the server on the classpath.

Start With Standard Server Properties

Many server settings are not Jetty-specific at all. They come from Spring Boot’s standard server properties.

properties
server.port=9090
server.servlet.context-path=/api
server.shutdown=graceful

These work regardless of the embedded server implementation and should be your first stop for basic configuration.

Add Jetty-Specific Thread Settings

When you need Jetty tuning, Spring Boot exposes several Jetty-specific properties. Thread configuration is a common example.

properties
server.jetty.threads.min=10
server.jetty.threads.max=200
server.jetty.threads.idle-timeout=60000

These values affect the server thread pool. They should be chosen based on expected concurrency, blocking behavior, and the rest of the deployment stack, not copied blindly from internet snippets.

Customize Jetty Programmatically

For settings that are easier to express in code, define a JettyServletWebServerFactory bean.

java
1import org.eclipse.jetty.server.Server;
2import org.eclipse.jetty.server.handler.StatisticsHandler;
3import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
4import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
5import org.springframework.context.annotation.Bean;
6import org.springframework.context.annotation.Configuration;
7
8@Configuration
9public class JettyConfig {
10
11    @Bean
12    public JettyServletWebServerFactory jettyServletWebServerFactory() {
13        JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
14        factory.addServerCustomizers(new JettyServerCustomizer() {
15            @Override
16            public void customize(Server server) {
17                StatisticsHandler statisticsHandler = new StatisticsHandler();
18                statisticsHandler.setHandler(server.getHandler());
19                server.setHandler(statisticsHandler);
20            }
21        });
22        return factory;
23    }
24}

This pattern is useful when you need handlers, connectors, request logging, or other server-level adjustments that do not fit neatly into properties.

Keep The Change Small At First

A common mistake is trying to tune every Jetty knob before the app has even been measured. A good migration path is:

  1. replace Tomcat with Jetty,
  2. keep default settings,
  3. confirm the app starts and passes tests,
  4. tune only the settings tied to a measured bottleneck.

That keeps the change understandable and reduces the chance of mixing server migration bugs with tuning mistakes.

Know What Jetty Does Not Change

Switching to Jetty does not automatically fix application-level problems such as:

  • slow database queries,
  • blocking controllers,
  • oversized thread pools elsewhere,
  • memory leaks,
  • poor connection management to downstream systems.

Jetty can be a better fit for some workloads, but the embedded server is only one part of the runtime profile.

A Minimal Gradle Equivalent

If you use Gradle instead of Maven, the dependency change is similar.

groovy
1dependencies {
2    implementation("org.springframework.boot:spring-boot-starter-web") {
3        exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
4    }
5    implementation("org.springframework.boot:spring-boot-starter-jetty")
6}

The rest of the Spring Boot configuration patterns stay the same.

Common Pitfalls

  • Adding Jetty without excluding Tomcat and then wondering which server Boot will use.
  • Tuning Jetty thread counts without understanding whether the app is blocking or non-blocking.
  • Moving Jetty-specific code into the app before verifying that standard Boot properties are enough.
  • Assuming a server swap alone will solve throughput or latency issues.
  • Making too many migration changes at once instead of isolating the server change.

Summary

  • Replace Tomcat with spring-boot-starter-jetty and let Spring Boot auto-configure the server.
  • Use standard server.* properties first for basic setup.
  • Add Jetty-specific properties only when you actually need them.
  • Use JettyServletWebServerFactory for programmatic server customization.
  • Measure before tuning so Jetty configuration stays tied to a real performance goal.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.