Every style can be secured; they differ in how visible old versions are. Path versions are easiest to see in logs and to block at a gateway. Header and date based versions are cleaner for clients but need better tooling to know who still calls what. Pick the style your monitoring can see.
The three common styles, defined
- Path versioning: the version is part of the URL, such as a v1 or v2 segment.
- Header versioning: the client sends the version in a request header, often a custom one or a media type parameter.
- Date based versioning: the client pins a release date, and the server maps it to the behavior in force on that day.
Whichever style you choose, the security question is the same. When you fix a vulnerability, does the fix reach every version customers still use, and can you tell who is still on the old one?
Comparison on security properties
| Property | Path | Header | Date based |
|---|---|---|---|
| Version visible in access logs | Yes, by default | Only if you log the header | Only if you log the pin |
| Gateway rules per version | Simple routing | Needs header matching | Needs mapping logic |
| Fix reaches all versions | Needs deliberate backport | Same code often serves all | Same code serves all, behavior toggled |
| Risk of unpatched legacy branch | Higher, branches diverge | Lower | Lower, but many behavior flags |
| Clarity for customers | High | Medium | High once explained |
| Retiring a version | Remove the route | Reject the header value | Retire a date range |
The pattern: styles that keep one code base serving many versions reduce the chance of a forgotten, unpatched branch, but they make it harder to see and cut off a version. Styles that split the code make cutting off easy but require you to patch several branches.
Steps to decide
- Count how many versions you expect to support at once. A small number tolerates separate branches.
- Check what your logging and metrics can see. If you cannot group traffic by version today, fix that before choosing a style.
- Decide how fixes will propagate. If each version is a separate code path, add each one to your release checklist and your support policy.
- Define what counts as a breaking change, and what counts as a security change that is allowed to alter behavior inside a version. State both publicly.
- Make the version a first class field in your metrics, alerts and incident tooling.
- Add deprecation signals per version, using the headers described in the Deprecation and Sunset guide.
- Rehearse a retirement on a low traffic version to test the process.
A note on stability tracks
Kubernetes labels API versions with alpha, beta and v1 style names and attaches different lifetimes to each, as its deprecation policy documents. Putting a stability label in the version name sets customer expectations about how long a version lives, which is a useful trick whatever style you adopt.
The wrong reasons to choose
Choosing path versioning because it looks tidy, then never retiring v1, leaves an old surface exposed. Choosing date versioning because it avoids major bumps, then accumulating dozens of behavior flags, makes the code hard to reason about and hard to review for security. In both cases the cost shows up in patch time, so measure it.
Quick check
Does versioning style change security?
Not the underlying risks, but it changes how visible old versions are and how many code paths you must patch.
Can a security fix change behavior inside a version?
It can, if you publish that rule in advance. Otherwise treat behavior changes as a new version.
Safeguard's asset discovery and dependency scanning can help you find which services expose old API versions, and policies and gates can enforce the rules you set. See the free scan.
Sources
Last reviewed: 19 October 2026.