As an API evolves, breaking changes are sometimes unavoidable. Versioning lets you introduce them without breaking existing clients. This lesson covers the most common Express versioning strategies.
Why APIs Need Versioning
Once external clients depend on your API's shape, changing a field name or response structure can break their integrations. Versioning gives you a safe way to introduce breaking changes behind a new version identifier while keeping the old version running unchanged.
The most common and easiest-to-understand approach in Express is URL path versioning, mounting an entirely separate router (or router tree) for each version prefix.
URL path versioning (/api/v1/...) is the simplest to implement and the easiest for clients to reason about.
Header-based versioning keeps URLs stable but requires custom middleware to branch on a header value.
Whichever strategy you choose, keep each version's router tree as self-contained as possible.
Deprecate old versions loudly (docs, response headers, changelogs) well before removing them.
API Versioning Cheatsheet
Trade-offs between the common versioning strategies.
Strategy
Example
Trade-off
URL path
/api/v1/users
Simple, visible, but duplicates routers per version
Query param
/api/users?version=2
Easy to add, easy for clients to forget
Custom header
X-API-Version: 2
Clean URLs, but less discoverable/testable in a browser
Accept header
Accept: application/vnd.myapi.v2+json
Standards-friendly, more complex to implement
Structuring Versioned Routers
A practical folder layout keeps each version's routes, and only the controllers that actually changed, separate, while sharing unaffected code between versions.
routes/
├── v1/
│ ├── users.router.js
│ └── index.js
└── v2/
├── users.router.js // only rewritten because the shape changed
└── index.js
// app.js
app.use('/api/v1', require('./routes/v1'));
app.use('/api/v2', require('./routes/v2'));
Deprecating an Old Version
Instead of removing an old version abruptly, add a deprecation warning header so well-behaved clients can detect and react to the upcoming removal.
Introducing breaking changes to an existing version instead of releasing a new one.
Versioning the entire API when only one endpoint actually changed shape.
Removing an old version without any deprecation notice or transition period.
Duplicating an entire version's codebase when only a handful of routes actually differ.
Key Takeaways
Versioning protects existing clients from breaking changes as an API evolves.
URL path versioning (/api/v1) is the simplest and most common strategy in Express apps.
Keep each version's router tree self-contained, but share unaffected code where possible.
Communicate deprecation clearly before removing an old version entirely.
Pro Tip
Only version the specific resource that changed shape when possible, run /api/v1/orders alongside a new /api/v2/orders while every other /api/v1/... route keeps serving both versions unchanged.
You now understand common API versioning strategies. Next, put routing knowledge into practice by building a full Express REST API.