How to Change Default Port and Context Path in Spring Boot (application.properties & YAML)
Learn how to change the default port (8080) and context path in Spring Boot using application.properties, YAML, environment variables, and programmatic configuration for production..
20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.
- ✓Java 17+ installed on your machine
- ✓Spring Boot 2.x or 3.x project (Maven or Gradle)
- ✓Basic understanding of application.properties or application.yml
- ✓IDE with Spring Boot support (IntelliJ, VS Code, or Eclipse)
• Use server.port=8081 in application.properties to change the port
• Use server.servlet.context-path=/api to change the context path (Spring Boot 2.x+)
• For older Spring Boot 1.x, use server.context-path instead
• Override via command line: --server.port=9090
• Use environment variables: SERVER_PORT=9090
Think of Spring Boot as a hotel where each app is a guest. The default port (8080) is like room 101 — every guest wants it, causing fights. Changing the port is like giving each guest a unique room number so they don't trample each other. The context path is like a hallway sign ('/api', '/admin') that directs visitors to the right wing of the hotel.
Every Spring Boot developer hits this wall on day one: you start your app, it boots on port 8080, and everything is fine — until you try to run a second microservice. Then you get a lovely Port 8080 already in use error, and your day goes downhill. In production, you rarely want to run on port 8080 anyway. Security scanners, reverse proxies, and container orchestrators all expect you to configure ports explicitly. The context path is equally critical: running multiple services behind a single load balancer requires unique paths like /api/v1/users, /api/v1/orders, etc. This article covers every way to change the default port and context path in Spring Boot, from the simple application.properties approach to advanced programmatic configuration using TomcatServletWebServerFactory. We'll also cover the subtle differences between Spring Boot 1.x, 2.x, and 3.x — because the API changed, and the official docs sometimes gloss over that. By the end, you'll know how to set these values in application.properties, application.yml, environment variables, command-line arguments, and even via @Configuration beans. We'll also discuss common pitfalls like port conflicts with embedded containers, context path not being applied to Actuator endpoints, and how to debug when things go sideways.
Setting Port and Context Path via application.properties
The simplest and most common way to change the default port and context path in Spring Boot is through application.properties. This file is automatically loaded by Spring Boot from the classpath (typically src/main/resources/). To change the port, add server.port=8081. To change the context path (the base URL prefix), use server.servlet.context-path=/myapp. In Spring Boot 2.x and 3.x, the property is server.servlet.context-path. In Spring Boot 1.x, it was server.context-path — a common pitfall for developers upgrading legacy apps. If you're using Spring Boot 3.0+, note that the property name remains the same as 2.x, but the behavior is identical. Here's a complete example:
server.port and server.servlet.context-path in application.properties for simple, static configuration.What the Official Docs Won't Tell You
The official Spring Boot docs show the basic properties, but they don't tell you about the subtle bugs. First, server.servlet.context-path does NOT apply to Actuator endpoints by default — you must set management.server.servlet.context-path separately if you want Actuator under a different path. Second, if you use server.port=0, Spring Boot assigns a random port, but that port changes on every restart — great for testing, terrible for production unless you're behind a service mesh. Third, the context path must start with '/' — if you forget, Spring Boot silently prepends it, but your logs will show a different path than expected. Fourth, when using embedded Tomcat, setting server.port to a privileged port (< 1024) on Linux will fail unless you run as root or use authbind. Fifth, the order of precedence matters: command-line arguments override application.properties, which override YAML files. The official docs list the precedence but don't emphasize how easy it is to accidentally override your port in a Dockerfile with CMD ["java", "-jar", "app.jar", "--server.port=8080"] when your application.properties already sets it. This causes confusion when your local dev environment works but production doesn't.
management.server.servlet.context-path if you want different paths.Using Command-Line Arguments and Environment Variables
Spring Boot allows overriding properties via command-line arguments and environment variables. This is essential for containerized deployments (Docker, Kubernetes) where you don't want to rebuild the JAR just to change the port. Command-line arguments take precedence over application.properties: java -jar myapp.jar --server.port=8081 --server.servlet.context-path=/api. Environment variables use uppercase with underscores: SERVER_PORT=8081 and SERVER_SERVLET_CONTEXT_PATH=/api. Note that environment variables are case-insensitive on Windows but case-sensitive on Linux — use uppercase to be safe. The mapping is: server.port becomes SERVER_PORT, server.servlet.context-path becomes SERVER_SERVLET_CONTEXT_PATH. This is a common source of bugs: developers forget the underscore between 'servlet' and 'context', writing SERVER_SERVLETCONTEXTPATH which is ignored.
Programmatic Configuration with WebServerFactoryCustomizer
For advanced scenarios, you can programmatically configure the embedded server using WebServerFactoryCustomizer<TomcatServletWebServerFactory>. This is useful when you need dynamic port assignment based on external conditions (e.g., reading from a database or a feature flag). You create a @Configuration class that implements WebServerFactoryCustomizer and override the customize method. Inside, you can set the port and context path programmatically. This approach gives you full access to the Tomcat factory, allowing you to set additional properties like connector, SSL, or compression. Note: this only works for the main web server — for Actuator, you need ManagementServerProperties customizer.
Using @Value and @ConfigurationProperties for Port Configuration
Another approach is to inject port and context path values using @Value or @ConfigurationProperties, then pass them to a customizer bean. This is cleaner than hardcoding env var names in the customizer. First, define properties in application.properties: app.port=9090 and app.context-path=/api. Then create a @ConfigurationProperties class, and inject it into the customizer. This approach keeps your configuration centralized and type-safe. However, note that server.port and server.servlet.context-path are already built-in Spring Boot properties — you don't need custom ones unless you have a specific reason (e.g., mapping from a legacy config source).
Handling Port Conflicts Gracefully
In production, port conflicts happen when two services try to bind to the same port on the same host. Spring Boot's default behavior is to throw a BindException and fail to start. You can handle this more gracefully by using server.port=0 (random port) and then discovering the port at runtime. To get the actual port, inject ServletWebServerApplicationContext and call getWebServer().getPort(). Alternatively, you can use Spring Boot's PortInUseException and implement a retry mechanism. For containerized environments, random ports are fine because the container orchestrator handles port mapping. For bare-metal deployments, use a port range and scan for available ports programmatically.
server.port=0 and let the container runtime assign the port. Never use fixed ports in containerized microservices.Context Path and Reverse Proxy Configuration
When running Spring Boot behind a reverse proxy (Nginx, Apache, AWS ALB), the context path interacts with proxy configuration. If you set server.servlet.context-path=/api, your app expects requests at /api/.... The reverse proxy must strip or forward the path correctly. Common issue: the proxy forwards /api/users but the app sees /users because the proxy already stripped the prefix. To fix, use server.forward-headers-strategy=framework in Spring Boot 2.2+ to let the app know it's behind a proxy. Alternatively, set server.use-forward-headers=true (deprecated in 2.2). The context path should match the proxy's location block. If the proxy uses a different prefix (e.g., /app), you must either change the context path or configure the proxy to rewrite paths.
curl -v http://localhost/api/actuator/health should return 200. If you get 404, check path stripping.server.forward-headers-strategy=framework to handle forwarded headers correctly.Testing Port and Context Path Configuration
Testing port and context path changes is critical before deploying to production. Use Spring Boot's @SpringBootTest with webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT to test with a random port. You can inject TestRestTemplate or WebTestClient to make requests. To verify the context path, use @LocalServerPort to get the actual port and build the URL manually. Alternatively, use @TestPropertySource to override properties for specific tests. For integration tests that check the context path, use RestTemplate with a base URL that includes the context path. Never hardcode ports in tests — always use random ports to avoid conflicts with other running tests.
@SpringBootTest(webEnvironment = RANDOM_PORT) and @LocalServerPort in tests to avoid port conflicts.The Great Port 8080 War of 2021
server.port=8080 hardcoded in their application.properties. Kubernetes does not magically assign different ports — you must configure them explicitly, especially when using hostPort or NodePort.server.port=0 (random port) for internal services, and used environment variable injection via SERVER_PORT in the Kubernetes deployment manifests.- Never hardcode port 8080 in production microservices — use environment variables or random ports
- Always validate port uniqueness when running multiple Spring Boot apps on the same host
- Use
server.port=0for random port assignment in containerized environments
lsof -i :8080 (Linux/macOS) or netstat -ano | findstr :8080 (Windows) to find the process using the port. Kill it or change your app's port. Use server.port=0 for random port in development.management.server.port is set to a different port than the main app. Ensure firewall allows traffic to the management port.curl -v http://localhost:8080/actuator/healthgrep -i 'context path' /var/log/app.logserver.servlet.context-path=/ temporarily to verify routes work at root| File | Command / Code | Purpose |
|---|---|---|
| application.properties | server.port=9090 | Setting Port and Context Path via application.properties |
| application.yml | server: | What the Official Docs Won't Tell You |
| Dockerfile | FROM openjdk:17-jdk-slim | Using Command-Line Arguments and Environment Variables |
| CustomPortConfig.java | @Configuration | Programmatic Configuration with WebServerFactoryCustomizer |
| AppProperties.java | @Component | Using @Value and @ConfigurationProperties for Port Configura |
| PortConflictHandler.java | @Component | Handling Port Conflicts Gracefully |
| nginx.conf | server { | Context Path and Reverse Proxy Configuration |
| PortContextPathTest.java | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | Testing Port and Context Path Configuration |
Key takeaways
server.port and server.servlet.context-path in application.properties for static configuration; override via environment variables for containerized deployments.management.server.servlet.context-path separately to avoid exposing management endpoints on the main app path.@SpringBootTest(webEnvironment = RANDOM_PORT) and @LocalServerPort to catch conflicts before production.Interview Questions on This Topic
How does Spring Boot resolve port configuration when multiple sources provide it (application.properties, environment variables, command-line arguments)?
Frequently Asked Questions
20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.
That's Spring Boot. Mark it forged?
4 min read · try the examples if you haven't