Home Java How to Change Default Port and Context Path in Spring Boot (application.properties & YAML)
Beginner 4 min · July 14, 2026

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..

N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.

Follow
Production
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
Before you start⏱ 15-20 min read
  • 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)
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer

• 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

✦ Definition~90s read
What is How to Change the Default Port and Context Path in Spring Boot?

You change the default port and context path in Spring Boot to override the embedded server's default settings (port 8080, context path '/') so your application runs on a specific port and URL prefix.

Think of Spring Boot as a hotel where each app is a guest.
Plain-English First

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:

application.propertiesPROPERTIES
1
2
3
4
5
6
7
8
# Change port to 9090
server.port=9090

# Set context path to /api/v1
server.servlet.context-path=/api/v1

# Optional: set a custom server header
server.server-header=MyApp-Server
Output
Application starts on http://localhost:9090/api/v1/
⚠ Spring Boot 1.x vs 2.x Context Path
📊 Production Insight
In production, avoid hardcoding ports in application.properties. Use environment-specific profiles (application-dev.properties, application-prod.properties) or externalized configuration via Spring Cloud Config.
🎯 Key Takeaway
Use 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.

application.ymlYAML
1
2
3
4
5
6
7
8
9
10
server:
  port: 9090
  servlet:
    context-path: /api/v1

management:
  server:
    port: 9091
    servlet:
      context-path: /actuator
Output
Main app on :9090/api/v1, Actuator on :9091/actuator
🔥YAML vs Properties: Which to Use?
📊 Production Insight
In production, always separate Actuator endpoints onto a different port (e.g., 9091) to avoid exposing sensitive info via the main app port. Use firewall rules to restrict access to the Actuator port.
🎯 Key Takeaway
Actuator context path is separate from the main context path. Always set 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.

DockerfileDOCKERFILE
1
2
3
4
5
FROM openjdk:17-jdk-slim
COPY target/myapp.jar app.jar
ENV SERVER_PORT=9090
ENV SERVER_SERVLET_CONTEXT_PATH=/api/v1
ENTRYPOINT ["java", "-jar", "/app.jar"]
Output
Container runs on port 9090 with context path /api/v1
⚠ Environment Variable Naming Gotcha
📊 Production Insight
In Kubernetes, use ConfigMaps to inject environment variables. Never hardcode ports in Dockerfiles — use ARG or ENV with sensible defaults.
🎯 Key Takeaway
Use environment variables or command-line arguments for Docker/Kubernetes deployments to avoid rebuilding images for config changes.

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.

CustomPortConfig.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomPortConfig implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        // Read from a custom source (e.g., environment variable, DB)
        String port = System.getenv().getOrDefault("APP_PORT", "8080");
        String contextPath = System.getenv().getOrDefault("APP_CONTEXT_PATH", "/");
        
        factory.setPort(Integer.parseInt(port));
        factory.setContextPath(contextPath);
    }
}
Output
Application starts on port from APP_PORT env var, context path from APP_CONTEXT_PATH
🔥Generic vs Tomcat-Specific Customizer
📊 Production Insight
Avoid programmatic configuration unless absolutely necessary — it makes debugging harder because the config is not visible in application.properties. Use it only for dynamic values from external sources.
🎯 Key Takeaway
Programmatic configuration via WebServerFactoryCustomizer gives full control for dynamic port assignment.

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).

AppProperties.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private int port = 8080;
    private String contextPath = "/";

    // getters and setters
    public int getPort() { return port; }
    public void setPort(int port) { this.port = port; }
    public String getContextPath() { return contextPath; }
    public void setContextPath(String contextPath) { this.contextPath = contextPath; }
}
Output
Custom properties bound to AppProperties bean
⚠ @ConfigurationProperties Requires Setter
📊 Production Insight
Combine @ConfigurationProperties with @Validated to add validation (e.g., port range 1024-65535) — catch misconfiguration early.
🎯 Key Takeaway
Use @ConfigurationProperties for type-safe, centralized custom configuration that can be injected into customizers.

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.

PortConflictHandler.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class PortConflictHandler implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ServletWebServerApplicationContext ctx = (ServletWebServerApplicationContext) event.getApplicationContext();
        int port = ctx.getWebServer().getPort();
        System.out.println("Application running on port: " + port);
        // Log to monitoring system
    }
}
Output
Logs the actual port the app is running on
🔥Random Port Discovery
📊 Production Insight
In Kubernetes, always use server.port=0 and let the container runtime assign the port. Never use fixed ports in containerized microservices.
🎯 Key Takeaway
Handle port conflicts by using random ports or implementing a retry mechanism with port scanning.

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.

nginx.confNGINX
1
2
3
4
5
6
7
8
9
10
11
server {
    listen 80;
    server_name example.com;

    location /api/ {
        proxy_pass http://localhost:9090/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
Output
Nginx forwards /api/* to Spring Boot on port 9090
⚠ Trailing Slash in proxy_pass Matters
📊 Production Insight
Test proxy configuration with curl: curl -v http://localhost/api/actuator/health should return 200. If you get 404, check path stripping.
🎯 Key Takeaway
Match the context path with your reverse proxy configuration. Use 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.

PortContextPathTest.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class PortContextPathTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void testContextPath() {
        String response = restTemplate.getForObject("http://localhost:" + port + "/api/v1/hello", String.class);
        assertThat(response).contains("Hello");
    }
}
Output
Test passes if context path /api/v1/hello returns expected response
🔥TestRestTemplate vs RestTemplate
📊 Production Insight
Add a smoke test in your CI/CD pipeline that deploys the app, hits the health endpoint with the correct context path, and verifies the response. Catches misconfiguration before production.
🎯 Key Takeaway
Always use @SpringBootTest(webEnvironment = RANDOM_PORT) and @LocalServerPort in tests to avoid port conflicts.
● Production incidentPOST-MORTEMseverity: high

The Great Port 8080 War of 2021

Symptom
Multiple Spring Boot pods in Kubernetes kept crashing with 'Port 8080 already in use' or 'Address already in use' errors.
Assumption
The team assumed each service would automatically get a different port in Kubernetes because they used different deployment YAML files.
Root cause
All services had 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.
Fix
Changed each service's application.properties to use server.port=0 (random port) for internal services, and used environment variable injection via SERVER_PORT in the Kubernetes deployment manifests.
Key lesson
  • 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=0 for random port assignment in containerized environments
Production debug guideStep-by-step guide to resolve common misconfiguration problems3 entries
Symptom · 01
Application starts but returns 404 on all endpoints
Fix
Check the context path: look for 'Tomcat started on port(s): 8080 (http) with context path '/api' in logs. If context path is '/', your routes are at root. Verify with curl http://localhost:8080/api/actuator/health vs http://localhost:8080/actuator/health.
Symptom · 02
Port 8080 already in use error on startup
Fix
Run 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.
Symptom · 03
Actuator health check fails from load balancer
Fix
Verify that the load balancer is hitting the correct port and path. Check if management.server.port is set to a different port than the main app. Ensure firewall allows traffic to the management port.
★ Quick Debug Cheat Sheet: Port and Context PathCommon issues and immediate fixes for port/context path problems
App starts but returns 404
Immediate action
Check logs for 'Tomcat initialized with port(s):' and 'context path'
Commands
curl -v http://localhost:8080/actuator/health
grep -i 'context path' /var/log/app.log
Fix now
Set server.servlet.context-path=/ temporarily to verify routes work at root
Port conflict on startup+
Immediate action
Find and kill the process using the port
Commands
lsof -i :8080
kill -9 <PID>
Fix now
Add server.port=0 to application.properties for random port
Actuator endpoints not accessible+
Immediate action
Check management.server.port and management.server.servlet.context-path
Commands
curl -v http://localhost:9091/actuator/health
grep 'management' application.properties
Fix now
Set management.server.port=9091 and management.server.servlet.context-path=/actuator
Configuration MethodUse CaseFlexibilitySecurity
application.propertiesStatic, per-environment configLowMedium (visible in JAR)
Environment VariablesContainerized deploymentsHighHigh (injected at runtime)
Command-Line ArgumentsQuick overrides in scriptsMediumLow (visible in process list)
Programmatic CustomizerDynamic config from DB/APIVery HighMedium (code review needed)
⚙ Quick Reference
8 commands from this guide
FileCommand / CodePurpose
application.propertiesserver.port=9090Setting Port and Context Path via application.properties
application.ymlserver:What the Official Docs Won't Tell You
DockerfileFROM openjdk:17-jdk-slimUsing Command-Line Arguments and Environment Variables
CustomPortConfig.java@ConfigurationProgrammatic Configuration with WebServerFactoryCustomizer
AppProperties.java@ComponentUsing @Value and @ConfigurationProperties for Port Configura
PortConflictHandler.java@ComponentHandling Port Conflicts Gracefully
nginx.confserver {Context Path and Reverse Proxy Configuration
PortContextPathTest.java@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)Testing Port and Context Path Configuration

Key takeaways

1
Use server.port and server.servlet.context-path in application.properties for static configuration; override via environment variables for containerized deployments.
2
Actuator context path is independent
always set management.server.servlet.context-path separately to avoid exposing management endpoints on the main app path.
3
Test port and context path configuration with @SpringBootTest(webEnvironment = RANDOM_PORT) and @LocalServerPort to catch conflicts before production.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
How does Spring Boot resolve port configuration when multiple sources pr...
Q02SENIOR
Explain the difference between server.servlet.context-path and managemen...
Q03SENIOR
How would you implement a dynamic port assignment in Spring Boot based o...
Q01 of 03SENIOR

How does Spring Boot resolve port configuration when multiple sources provide it (application.properties, environment variables, command-line arguments)?

ANSWER
Spring Boot uses a well-defined precedence order (from highest to lowest): command-line arguments, environment variables, application.properties outside JAR, application.properties inside JAR, and default values. This is part of Spring Boot's externalized configuration mechanism. Understanding this order is crucial for debugging port conflicts in production.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
How do I change the port in Spring Boot 3?
02
What is the difference between server.context-path and server.servlet.context-path?
03
How do I set a random port in Spring Boot?
04
Does the context path apply to Actuator endpoints?
N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.

Follow
Verified
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
🔥

That's Spring Boot. Mark it forged?

4 min read · try the examples if you haven't

Previous
Spring Boot Filters: Servlet Filters, OncePerRequestFilter, and FilterRegistrationBean
60 / 121 · Spring Boot
Next
Custom Error Pages in Spring Boot: Whitelabel Error Page and ErrorController