Spring Boot 4 API Versioning with Path Segments
API versioning is essential when your API evolves and you need to support multiple clients without breaking existing integrations, and Spring Boot 4 makes path-based versioning straightforward with built-in support.
Why API versioning matters
When a REST API is shared by multiple clients, a small change in the contract can turn into a production outage. If you change the response structure, rename a field, or tighten validation rules, older clients may break unexpectedly.
That is why versioning is often part of long-lived API design. It gives teams a controlled way to introduce new behavior while continuing to support older clients.
The Spring team has now added official API versioning support in the Spring ecosystem, and the pattern is very practical for Spring Boot applications. The goal is not to reinvent custom routing logic in every controller, but to let the framework handle version resolution consistently.
The path-based approach
Path-based versioning is still the easiest style to understand and debug. It is explicit, visible in the URL, and simple for clients and support teams to reason about.
A common pattern is:
1 | /api/v1/greeting |
The version is part of the URL path, so a client can clearly see which contract it is using.
This is the exact pattern used in the sample project at SpringBoot/api-versioning: version is read from a path segment, and the controller version is selected by Spring based on the request URL.
Spring Boot 4 configuration
The key configuration is ApiVersionConfigurer with usePathSegment(1). This tells Spring that the version lives in the first path segment after the base path.
1 |
|
This is equivalent to the property-based setup:
1 | spring.mvc.api-versioning.enabled=true |
In plain terms, Spring expects a URL like /api/v1/... and resolves the version from that segment automatically.
Controller example
The controller in the sample project uses a route prefix with {version} in the path:
1 |
|
This is a clean pattern because the version appears in the URL and the handler method declares the matching API version explicitly.
What Spring is doing for us
With this setup, the framework does the heavy lifting:
- it reads the version from the URL path segment
- it validates whether that version is supported
- it matches the request to the correct controller method
- it falls back to the configured default version when needed
This means we no longer need to write custom logic such as if (version.equals("v1")) { ... } throughout the controller layer.
Example requests
Once configured, the endpoints are very easy to call:
1 | curl http://localhost:8080/api/v1/greeting |
Example responses might look like this:
1 | { |
1 | { |
Why path-based versioning is a strong choice
For public-facing APIs, path-based versioning has a lot of advantages:
- easy to read in logs and debug output
- obvious to clients and developers
- simple to document in OpenAPI and API specifications
- easy to test in staging and production environments
If a client calls /api/v1/..., it is immediately clear which API contract is in use.
When to prefer header-based versioning instead
Path-based versioning is great for visibility, but some teams prefer headers for cleaner URLs. Spring also supports header-based versioning, but that is a different style.
For example, you could configure:
1 | configurer.useRequestHeader("X-API-Version"); |
This keeps the route clean, such as /api/greeting, while the version is provided in a request header. The trade-off is that it is less visible and can be easier to forget when troubleshooting requests.
For most public APIs, I still prefer path-based versioning because the contract is obvious.
Best practices for Spring Boot API versioning
When using path-based versioning, a few practices make the API easier to maintain:
- Keep the version in a stable prefix, such as
/api/v1/...and/api/v2/.... - Avoid mixing version-specific logic into unrelated business code.
- Use separate controller logic or service boundaries per major version when breaking changes are required.
- Plan a migration window before removing an old version.
- Document which versions are supported and when they are deprecated.
This approach keeps versioning predictable and makes it much easier to support old clients while introducing new functionality.
Final thoughts
Spring Boot 4 provides a clean, built-in way to support API versioning at the framework level, and path-segment versioning is the most natural and readable strategy for many teams.
The pattern from the sample project is simple but powerful:
- configure the version position using
usePathSegment(1) - declare the version on the request mapping
- expose URLs such as
/api/v1/...and/api/v2/... - let Spring resolve the correct handler automatically
If you are building a public API that needs long-term compatibility, path-based versioning is still one of the clearest and most maintainable choices.