RadhaPublication
HomeInterviewLearning PathsRole TracksMockBooksPricing
Login / Sign UpLog in

© 2026 Radha Publication. All rights reserved.

Shop on AmazonDonateContactPrivacyTerms
Spring Boot questions
MediumSpring Boot#77 min readJul 11, 2026

Explain embedded Tomcat.

practice
learning
Practice modeTest yourself instead of reading straight through

Tomcat is like a kitchen built into your house: Spring Boot brings the server with the app, so you do not have to install one separately.

Question: Explain embedded Tomcat.

Answer: In Spring Boot, embedded Tomcat means the Tomcat web server runs inside your application process instead of being installed and managed as a separate server. When you add spring-boot-starter-web, Boot usually auto-configures Tomcat, starts it on startup, and listens on port 8080 by default. That is why a Boot app can be packaged as a simple runnable JAR.

Interview-Ready Answer: 'Embedded Tomcat means my Spring Boot app starts its own Tomcat server inside the same JVM, so I can run the app as a self-contained JAR. Spring Boot auto-configures it when I use spring-boot-starter-web, typically on port 8080 unless I change it. The big benefit is simpler deployment and fewer server setup steps.'

🧠 Memory Map
Memory map — visual summary of this topic

What embedded Tomcat really means

Tomcat is a servlet container (a server that runs Java web requests through the Servlet API). In Spring Boot, embedded means that container is started by your app, inside the same JVM process, instead of being installed separately and managed as a separate server. Your application becomes both the business logic and the web server.

How Spring Boot starts it under the hood

  1. You add spring-boot-starter-web. That pulls in Spring MVC, the Servlet API, and Tomcat libraries by default.
  2. Boot detects that this is a servlet-based web app and creates a web application context, which is the Spring container plus web support.
  3. Auto-configuration creates a TomcatServletWebServerFactory bean. This factory knows how to build and configure Tomcat for the app.
  4. Boot creates a TomcatWebServer from that factory and binds it to a port, usually 8080 unless you set server.port or customize it in code.
  5. Spring registers the DispatcherServlet (the main Spring MVC front controller) with Tomcat. A front controller is one entry point that receives all requests and routes them to controllers.
  6. When an HTTP request arrives, Tomcat accepts the socket, picks a worker thread from its pool, and passes the request into Spring MVC, which maps it to your controller method.

Why people use embedded Tomcat

It makes local development and deployment much simpler. You can ship one executable JAR, run it with java -jar, and the same artifact works in a laptop, a VM, or a container. It also reduces environment mismatch: the app carries the server version it was tested against.

Embedded vs external Tomcat

Embedded TomcatExternal Tomcat
Server ships with appServer installed separately
Run as JARDeploy WAR
Boot controls startupOps controls server
Good for containersGood for shared app servers
Fewer moving partsMore server admin work

Version and config details interviewers like

Spring Boot 3 uses Tomcat 10.1 and the Jakarta Servlet API, so package names moved from javax.servlet to jakarta.servlet. Spring Boot 2 used Tomcat 9 and the older javax namespace. The default port is 8080, but you can change it with server.port or programmatically via the embedded server factory.

Performance and practical limits

The container itself adds only a small startup and memory cost compared with your application code, but Tomcat still uses a thread pool. Common Tomcat defaults are around 200 max request threads and an accept backlog near 100. That means a busy app can queue briefly and then start rejecting or timing out if traffic exceeds the pool and backlog. Request routing is effectively O(1) at the server level; the expensive part is your application logic, database calls, and serialization.

Important edge cases

  • If port 8080 is already in use, startup fails fast with a bind error.
  • If you exclude Tomcat and add Jetty or Undertow instead, Boot still gives you embedded server behavior, just with a different container.
  • If you package a WAR for an external server, Boot can still work, but the deployment model changes.
  • Embedded Tomcat does not mean no tuning: you may still configure max threads, connection timeout, SSL, compression, and access logs.

Memory hook: think of embedded Tomcat as a suitcase hotel: the app checks in with its own front desk, instead of renting a separate building across town.

Real-world story: A checkout service in a Kubernetes cluster runs as a Spring Boot JAR with embedded Tomcat. Each pod owns its own HTTP server, so the team can scale pods horizontally without asking ops for a shared Tomcat installation. One Friday, a release changed the app to use a fixed port that was already taken by a sidecar container. The pod kept crashing, and logs showed java.net.BindException: Address already in use. Users saw 502 errors at the load balancer, health checks failed, and the deployment never became ready. The lesson: with embedded Tomcat, the web server is part of the app’s startup path, so server configuration mistakes become application outages, not just server chores.

Spring Boot
package com.example.embeddedtomcat;

import java.util.Map;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

@SpringBootApplication
public class EmbeddedTomcatDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(EmbeddedTomcatDemoApplication.class, args);
    }

    // Port 0 asks the OS for a free port, so the sample starts reliably
    // even if 8080 is already busy on the machine.
    @org.springframework.context.annotation.Bean
    WebServerFactoryCustomizer<TomcatServletWebServerFactory> embeddedTomcatCustomizer() {
        return factory -> {
            factory.setPort(0);
            factory.setContextPath("/demo");
        };
    }

    @EventListener
    public void logActualPort(WebServerInitializedEvent event) {
        // Embedded Tomcat lives inside the same JVM, so we can inspect the live port after startup.
        System.out.println("Embedded Tomcat started on port: " + event.getWebServer().getPort());
    }

    @RestController
    @RequestMapping("/api")
    static class GreetingController {

        @GetMapping("/ping")
        public Map<String, Object> ping() {
            return Map.of(
                    "status", "ok",
                    "container", "embedded Tomcat"
            );
        }

        @GetMapping("/greet")
        public ResponseEntity<Map<String, Object>> greet(@RequestParam(required = false) String name) {
            // This edge case shows that application errors are still handled normally
            // even though the HTTP server is embedded.
            if (name == null || name.isBlank()) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "name is required");
            }

            return ResponseEntity.ok(Map.of(
                    "message", "Hello, " + name,
                    "server", "embedded Tomcat",
                    "path", "/demo/api/greet"
            ));
        }
    }
}

Follow-up & Tricky Questions:

  • How does Spring Boot decide to use Tomcat? If spring-boot-starter-web is on the classpath, Boot auto-configures a servlet web server, and Tomcat is the default embedded choice unless you replace it.
  • How do you change the port or context path? Use properties like server.port and server.servlet.context-path, or customize the embedded server factory in code.
  • Can I use Jetty or Undertow instead? Yes. Exclude Tomcat and add the starter for another server; Boot still runs it embedded.
  • What is the difference between JAR and WAR deployment? A JAR usually runs with embedded Tomcat from java -jar, while a WAR is packaged for deployment into an external servlet container.
  • What happens if Tomcat cannot bind to the port? The app fails during startup with a bind exception, because the web server is part of application bootstrapping.
  • Is embedded Tomcat the same thing as Spring Boot? No. Tomcat is the server; Spring Boot is the framework that auto-configures and launches it.
  • Is Tomcat thread-per-connection? Not exactly. Tomcat uses a worker thread pool, so requests are handled by reusable threads rather than one permanent thread per client.
  • Can I still use an external Tomcat with Spring Boot? Yes. You can package as a WAR and deploy to a managed server when that model fits the organization.
  • Does embedded Tomcat remove the need for tuning? No. You still may tune threads, timeouts, compression, SSL, and logging for production traffic.
  • Does Boot 3 use the same servlet packages as Boot 2? No. Boot 3 uses jakarta.servlet; Boot 2 used javax.servlet.
  • Does embedded Tomcat mean there is no server process? No. There is still a server process; it just runs inside the same application JVM.
  • Does embedded Tomcat mean no Tomcat files on disk? Usually yes for the app server install itself, because the server libraries are bundled inside the app artifact.

Common Mistakes:

  • Mistake: Saying embedded Tomcat is a Spring feature. Correction: Tomcat is a separate servlet container; Spring Boot just auto-configures and launches it.
  • Mistake: Assuming embedded Tomcat only works with JARs. Correction: JAR is the common case, but Boot can also support WAR deployment when needed.
  • Mistake: Ignoring server tuning. Correction: Embedded still needs thread, timeout, SSL, and port configuration in real systems.
  • Mistake: Forgetting the version shift from javax to jakarta. Correction: Boot 3 and Tomcat 10 use Jakarta namespaces, which breaks older imports.

Memory Hook: Your app brings its own front desk. Embedded Tomcat means the server travels with the application instead of living in a separate building.

Cheat Sheet:

  • Embedded Tomcat = Tomcat runs inside the Spring Boot JVM.
  • Default starter: spring-boot-starter-web.
  • Default port: 8080 unless changed.
  • Boot creates and configures TomcatServletWebServerFactory.
  • Boot 3 uses Tomcat 10.1 and jakarta.servlet.
  • Big win: one runnable artifact, simpler deployment, fewer environment mismatches.

Practice Tasks:

  • Run a tiny Spring Boot app with spring-boot-starter-web and confirm Tomcat starts in the logs.
  • Change server.port and server.servlet.context-path, then hit the endpoint again.
  • Replace Tomcat with Jetty or Undertow and observe that the app still behaves like an embedded server application.
Previous
Back to Questions←→to navigate
Next

Recommended Resources

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

package com.example.embeddedtomcat; import java.util.Map; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.context.WebServerInitializedEvent; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.event.EventListener; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; @SpringBootApplication public class EmbeddedTomcatDemoApplication { public static void main(String[] args) { SpringApplication.run(EmbeddedTomcatDemoApplication.class, args); } // Port 0 asks the OS for a free port, so the sample starts reliably // even if 8080 is already busy on the machine. @org.springframework.context.annotation.Bean WebServerFactoryCustomizer<TomcatServletWebServerFactory> embeddedTomcatCustomizer() { return factory -> { factory.setPort(0); factory.setContextPath("/demo"); }; } @EventListener public void logActualPort(WebServerInitializedEvent event) { // Embedded Tomcat lives inside the same JVM, so we can inspect the live port after startup. System.out.println("Embedded Tomcat started on port: " + event.getWebServer().getPort()); } @RestController @RequestMapping("/api") static class GreetingController { @GetMapping("/ping") public Map<String, Object> ping() { return Map.of( "status", "ok", "container", "embedded Tomcat" ); } @GetMapping("/greet") public ResponseEntity<Map<String, Object>> greet(@RequestParam(required = false) String name) { // This edge case shows that application errors are still handled normally // even though the HTTP server is embedded. if (name == null || name.isBlank()) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "name is required"); } return ResponseEntity.ok(Map.of( "message", "Hello, " + name, "server", "embedded Tomcat", "path", "/demo/api/greet" )); } } }