Your API will change. How you handle that change determines whether clients curse your name or barely notice.
The Three Approaches
1. URL Path Versioning
Pros:
- Obvious and explicit
- Easy to route in any framework
- Simple load balancer rules
- Easy to deprecate (just turn off the route)
Cons:
- URL changes when version changes
- Cache keys differ per version
- Feels “un-RESTful” to purists
This is the most common approach. It works.
2. Header Versioning
Or custom header:
Pros:
- Clean URLs
- Same resource, different representations
- More “correct” REST interpretation
Cons:
- Invisible in browser/logs
- Harder to test (need to set headers)
- Some clients don’t handle custom headers well
3. Query Parameter
Pros:
- Easy to test in browser
- Obvious in logs
Cons:
- Pollutes the URL
- Query params are for filtering, not versioning
- Cache complications
My Recommendation: URL Path
| |
Clear, simple, works everywhere.
Version Numbering
Don’t use semver for APIs. Use integers.
Semver implies patch compatibility that HTTP APIs can’t guarantee. Keep it simple.
What Counts as a Breaking Change?
Breaking (requires new version):
- Removing a field
- Renaming a field
- Changing a field’s type
- Changing response structure
- Removing an endpoint
- Changing authentication
Not breaking (same version is fine):
- Adding a new optional field
- Adding a new endpoint
- Adding a new optional parameter
- Increasing rate limits
- Performance improvements
Deprecation Strategy
| |
Timeline:
- Announce deprecation (6+ months before)
- Add deprecation headers
- Log usage of deprecated endpoints
- Contact heavy users directly
- Reduce rate limits on old version
- Return 410 Gone (final)
Supporting Multiple Versions
Approach A: Separate Codebases
Works for major rewrites. Painful for bug fixes.
Approach B: Version Adapters
| |
One source of truth, multiple representations.
Approach C: Feature Flags
| |
Gradual migration without separate routes.
Version Discovery
Let clients know what’s available:
| |
Testing Across Versions
| |
The Philosophy
- Default to the latest version for new clients
- Support at least one previous version in production
- Deprecate loudly, remove quietly
- Breaking changes should be rare (additive changes usually suffice)
- Your version strategy should be decided before v1 ships
The best versioning strategy is the one that lets your clients sleep at night.