Skip to main content
Practice Problems

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
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 logic
js
// 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

PracticeDescription
Start with versioningAdd /v1 from the beginning
Maintain max 2 versionsCurrent + previous
Deprecate properlySet sunset dates, notify users
Share business logicOnly version the API layer
Document changesChangelog for each version
Semantic versioningMajor = 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/v1 from day one, even if you don't plan to version initially.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems