typescriptintermediate
API Versioning Strategy
Implement API versioning with URL path, header-based, and content negotiation strategies.
typescriptPress ⌘/Ctrl + Shift + C to copy
import http from 'http';
type Handler = (req: http.IncomingMessage, res: http.ServerResponse) => void;
type VersionedHandlers = Record<string, Handler>;
// Strategy 1: URL path versioning (/v1/users, /v2/users)
function urlVersionRouter(routes: Record<string, VersionedHandlers>): Handler {
return (req, res) => {
const url = req.url ?? '/';
const match = url.match(/^\/v(\d+)(\/.*)/);
if (!match) { res.writeHead(400); res.end('Missing version'); return; }
const version = `v${match[1]}`;
const path = match[2];
const handler = routes[path]?.[version];
if (!handler) { res.writeHead(404); res.end('Not found'); return; }
handler(req, res);
};
}
// Strategy 2: Header versioning (Accept-Version: 2)
function headerVersionRouter(
routes: Record<string, VersionedHandlers>,
defaultVersion = 'v1',
): Handler {
return (req, res) => {
const vHeader = req.headers['accept-version'] as string | undefined;
const version = vHeader ? `v${vHeader}` : defaultVersion;
const path = req.url ?? '/';
const handler = routes[path]?.[version];
if (!handler) {
res.writeHead(404);
res.end(JSON.stringify({ error: `${path} not available in ${version}` }));
return;
}
res.setHeader('API-Version', version);
handler(req, res);
};
}
// Example handlers
const usersV1: Handler = (_, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify([{ id: 1, name: 'Alice' }]));
};
const usersV2: Handler = (_, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: [{ id: 1, firstName: 'Alice', lastName: 'Smith', email: 'alice@example.com' }],
meta: { version: 'v2', total: 1 },
}));
};
// URL versioning server
const routes = { '/users': { v1: usersV1, v2: usersV2 } };
const server = http.createServer(urlVersionRouter(routes));
server.listen(3000, () => console.log('Versioned API on :3000'));
// GET /v1/users → compact response
// GET /v2/users → enriched responseUse Cases
- API backward compatibility
- Gradual migration between versions
- Multi-version REST APIs
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
Request Validation Schema Builder
Build a lightweight request validation layer with type inference for API endpoints.
Best for: API request body validation
#nodejs#validation
typescriptintermediate
Node.js Token Bucket Rate Limiter
Implement an in-memory token bucket rate limiter for controlling API request throughput.
Best for: Protecting APIs from abuse and DDoS
#nodejs#rate-limiting
typescriptbeginner
Native HTTP Server
Create a lightweight HTTP server using Node.js built-in http module with routing and JSON responses.
Best for: Lightweight API server without frameworks
#nodejs#http
typescriptintermediate
Event-Driven Architecture Pattern
Build loosely coupled systems with typed event bus, async event handlers, and domain event patterns.
Best for: Microservice communication
#nodejs#events