tezvyn:

API versioning: URL vs header strategies

AI-drafted, machine-checkedSource: interviewadvanced
WHAT IT TESTS

managing breaking changes.

OUTLINE

version via URL path (/v1/), a custom or Accept header, or a query param; URL is visible and cache-friendly, headers keep URLs clean but are less discoverable.

WHAT THIS TESTS This evaluates whether you can evolve a public contract safely and reason about the tradeoffs between versioning placements.

A GOOD ANSWER COVERS The goal is to let old and new clients coexist while you make a breaking change. The main strategies are URL-path versioning, where the version lives in the path like /v1/products and /v2/products; header-based versioning, using either a custom header (X-API-Version) or proper content negotiation via the Accept header (application/vnd.myapi.v2+json); and query-parameter versioning (?version=2). URL versioning is highly visible, trivial to test in a browser or curl, cache friendly, and unambiguous, but it arguably violates REST purity by encoding versions in resource identifiers and can lead to route duplication. Header versioning keeps a single clean URL per resource and is considered more RESTful, but versions are hidden, harder to discover and test, and can complicate caching since proxies must key on the header (Vary). A pragmatic answer notes URL versioning is the most common in practice, and pairs versioning with a deprecation policy and sunset timeline.

COMMON WRONG ANSWERS Making the breaking change in place with no version. Claiming one strategy is universally correct. Ignoring caching implications of header versioning. Forgetting a deprecation and sunset plan for old versions. Versioning everything when an additive, backward-compatible change would suffice.

LIKELY FOLLOW-UPS When is a change actually breaking versus additive? How long do you support old versions? How does Vary affect caching with header versioning? Could you avoid versioning by evolving additively?

ONE CONCRETE EXAMPLE With URL versioning you mount app.use('/v1', v1Router) and app.use('/v2', v2Router), so legacy clients keep hitting /v1/products while new clients move to /v2/products with the restructured resource. With header versioning the same /products URL serves either shape based on an Accept header, requiring the cache to Vary on Accept, which is cleaner but harder to debug from a browser.

Read the original → postman.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.