Back to blog

How to Implement API Versioning: URL Path, Query Parameter, and Custom Header Strategies

As your software application grows, requirements change. You will need to modify database schemas, rename parameters, or alter response layouts.

If you push these changes to a production API directly, you will trigger Breaking Changes that crash active mobile applications and third-party developer integrations.

To evolve backend services safely, you must implement API Versioning.

In this guide, we will analyze the three dominant API versioning strategies—URL Path, Query Parameter, and Custom Header—compare their impact on caching engines, and implement code setups for each in Node.js.

Strategy 1: URL Path Versioning (URI Routing)

URL path versioning inserts the version identifier directly into the entry point path structure.

GET https://api.example.com/v1/users
GET https://api.example.com/v2/users

Advantages

  • Simple Caching: Highly compatible with Content Delivery Networks (CDNs) and reverse proxies. Because the paths are completely distinct, caching keys resolve without configuration.
  • Easy Testing: Developers can request specific versions directly from any standard web browser address bar.

Code Implementation (Express Router)

import express from 'express';
const app = express();

// Version 1 Controller
const v1Router = express.Router();
v1Router.get('/users', (req, res) => {
  res.json({ users: [{ id: 1, name: 'Alex' }] });
});

// Version 2 Controller (Returning modified field naming)
const v2Router = express.Router();
v2Router.get('/users', (req, res) => {
  res.json({ data: [{ userId: 1, userName: 'Alex' }] });
});

// Route binding
app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);

Strategy 2: Query Parameter Versioning

This strategy preserves a clean URL path and defines the target API version inside a query variable parameter.

GET https://api.example.com/users?version=2

Advantages

  • Clean Paths: The resource route (/users) remains constant.
  • Default Fallbacks: You can configure your gateway to route requests lacking parameters to a default active version (e.g., falling back to v1 automatically).

The Downside: Caching Issues

Many corporate proxy servers and CDNs ignore query parameters when generating caching keys. If not configured correctly, a cached v1 response might be served to a user requesting v2.

Strategy 3: Custom Header Versioning (Media Type / Content Negotiation)

Also called "Accept Header Versioning", this approach keeps the URL completely clean. The version is requested inside custom HTTP headers.

GET https://api.example.com/users
Accept: application/vnd.myapi.v2+json

Advantages

  • Strict REST Compliance: Follows the REST design philosophy that URLs should identify the resource location, not the representation version.
  • Clean API Schema: The URL namespace remains untouched.

Code Implementation (Express Middleware)

import express from 'express';
const app = express();

const userControllerV1 = (req: any, res: any) => {
  res.json({ users: [{ id: 1, name: 'Alex' }] });
};

const userControllerV2 = (req: any, res: any) => {
  res.json({ data: [{ userId: 1, userName: 'Alex' }] });
};

app.get('/users', (req, res) => {
  // Read target version from Accept Header
  const acceptHeader = req.headers['accept'] || '';
  
  if (acceptHeader.includes('vnd.myapi.v2+json')) {
    return userControllerV2(req, res);
  }

  // Fallback to V1
  return userControllerV1(req, res);
});

The Downside: Testing and Caching Complexity

  • Testing requires client tools (like Postman or curl) to modify request headers manually.
  • To cache these routes, you must configure your reverse proxy to vary responses using the Vary: Accept header, increasing configuration maintenance.

Versioning Strategies Comparison

Metric URL Path Query Parameter Custom Header
URL Cleanliness Poor (cluttered) Moderate Excellent (clean)
CDN Cache-Friendliness Excellent Moderate Poor (requires Vary setup)
Browser Accessibility Yes Yes No (requires custom headers)
API Path Bloat High Low Low

Conclusion

Choose URL Path versioning for public web APIs where caching compatibility, routing, and testing simplicity are paramount. Select Custom Header versioning for enterprise microservices ecosystems where you want to maintain clean resource URLs and handle content representations dynamically.