How to implement API versioning in Express.js?
API Versioning in Express.js
As your API evolves, you need to make breaking changes without disrupting existing clients. API versioning solves this by maintaining multiple API versions simultaneously.
Versioning Strategies
1. URL Path Versioning (Most Common)
js
const v1Router = require('./routes/v1');
const v2Router = require('./routes/v2');
app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);GET /api/v1/users β returns { name: 'John' }
GET /api/v2/users β returns { firstName: 'John', lastName: 'Doe' }Pros: Simple, explicit, easy to test Cons: URL pollution, code duplication
2. Header Versioning
js
app.use('/api/users', (req, res, next) => {
const version = req.headers['api-version'] || '1';
switch (version) {
case '1':
return v1UserController.getAll(req, res, next);
case '2':
return v2UserController.getAll(req, res, next);
default:
return res.status(400).json({ error: `Unknown API version: ${version}` });
}
});GET /api/users
Headers: { "Api-Version": "2" }Pros: Clean URLs Cons: Harder to discover, test in browser
3. Query Parameter Versioning
js
app.get('/api/users', (req, res) => {
const version = req.query.version || '1';
if (version === '2') {
return res.json(getUsersV2());
}
return res.json(getUsersV1());
});GET /api/users?version=2
Recommended: URL Path with Shared Logic
src/
βββ routes/
β βββ v1/
β β βββ index.js
β β βββ users.routes.js
β β βββ products.routes.js
β βββ v2/
β βββ index.js
β βββ users.routes.js β only changed endpoints
β βββ products.routes.js β re-exports v1 if unchanged
βββ controllers/
β βββ v1/
β βββ v2/
βββ services/ β shared business logicjs
// routes/v2/products.routes.js
// No changes from v1 β re-export
module.exports = require('../v1/products.routes');Deprecation Headers
When deprecating a version, inform clients via headers:
js
// Middleware for deprecated v1
function deprecationWarning(req, res, next) {
res.set('Deprecation', 'true');
res.set('Sunset', 'Sat, 01 Jun 2026 00:00:00 GMT');
res.set('Link', '</api/v2>; rel="successor-version"');
next();
}
app.use('/api/v1', deprecationWarning, v1Router);Best Practices
| Practice | Description |
|---|---|
| Start with versioning | Add /v1 from the beginning |
| Maintain max 2 versions | Current + previous |
| Deprecate properly | Set sunset dates, notify users |
| Share business logic | Only version the API layer |
| Document changes | Changelog for each version |
| Semantic versioning | Major = breaking, minor = additions |
Recommendation: Use URL path versioning β it's the most explicit, easiest to implement, and works well with API documentation tools like Swagger. Start with
/api/v1from day one, even if you don't plan to version initially.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.