Back to Articles
Backend Feb 15, 2026 · 7 min read

How I handle API versioning without losing my mind

Daniel

Software Developer

Should I use URL versioning (/v1/users) or header versioning (Accept: application/vnd.app.v1+json)? We tried both. Here is what worked.

Option 1: URL Path (/v1/users)

Pros: Simple, visible, cacheable

Cons: Need to route to same handler

GET /v1/users
GET /v2/users

Option 2: Header (Accept)

Pros: Cleaner URLs, same endpoint for different versions

Cons: Harder to test, not visible in browser

GET /users
Accept: application/vnd.app.v1+json

Option 3: Query Parameter (?version=1)

Not recommended - it breaks HTTP caching and looks messy.

What We Use

URL path versioning for major versions, query for minor tweaks:

GET /api/v1/users?fields=id,name  -- v1 with optional fields
GET /api/v2/users                  -- breaking changes get new version
GET /api/v2/users/123/vip          -- resource-specific versioning

Deprecation Strategy

When we release v2, we don’t kill v1 immediately:

  1. Ship v2, keep v1 working
  2. Add deprecation headers: Deprecation: true
  3. Announce timeline (6 months)
  4. Return warnings in responses
  5. Turn off v1 after timeline

One More Tip

Use OpenAPI/Swagger to document all versions. Make it easy for consumers to migrate.