Stop 09 · API DesignTopics · 2/12

API Versioning

Part of the Backend Developer Roadmap

In short

The day you rename one JSON field, every old app on someone's phone can break. Versioning lets you change your API without pulling the rug from under existing users.

Strategies for evolving an API without breaking existing clients — URL versioning (`/v1/`), header versioning, or additive-only changes.

The blob character compares an old worn textbook with a shiny new edition.

Think of it like this

Old edition, new edition

When a new textbook edition comes out, seniors keep studying from the old one until their exams end. Both editions exist side by side for a while. API versions work the same: /v1 keeps working while new clients move to /v2.

Watch it happen

Two app versions, one API

Old app
New app
API

GET /v1/users/7

1/5An old app version, still installed on someone's phone, calls v1.

The big ideas

What you need to know

Adding is free, changing is not

A new field or a new endpoint breaks nobody. Removing, renaming or retyping a field does.

URL versioning is simplest

/v1/orders is easy to spot in logs, test in a browser and route in a gateway. Most teams start here.

Header versioning is tidier

Some APIs read a header like Accept: application/vnd.myapp.v2+json. Clean URLs, but harder to test by hand.

Retire versions on a schedule

Announce a sunset date, watch who still calls v1, then switch it off. Never surprise people.

See it in code

Walk through the code

ts
1import express from "express";2const app = express();3 4const v1 = express.Router();5v1.get("/users/:id", async (req, res) => {6  const u = await db.users.find(req.params.id);7  res.json({ id: u.id, name: `${u.firstName} ${u.lastName}` });8});9 10const v2 = express.Router();11v2.get("/users/:id", async (req, res) => {12  const u = await db.users.find(req.params.id);13  res.json({ id: u.id, firstName: u.firstName, lastName: u.lastName });14});15 16app.use("/v1", v1).use("/v2", v2);

1/3v1 keeps the old shape: one combined name string. Old apps never notice a thing.

Same database, two response shapes. Once v1 traffic drops to zero in your logs, you can delete the v1 router.

Save yourself the pain

Common mistakes

Oops

Renaming a field in place because the frontend team will update anyway.

Do this instead

Old mobile app versions stay installed for months. Add the new field, keep the old one, or ship a new version.

Oops

Creating /v2, /v3, /v4 for every small change.

Do this instead

Only bump the version for breaking changes. New optional fields and new endpoints can go into the current version.

Your mission

Ship a v2 without breaking v1

~25 min

Quick check

Which change can safely go into the current API version?

Go deeper

  1. 1Compare URL-based versioning vs header-based versioning trade-offs.
  2. 2Design how you'd introduce a breaking change to an endpoint without breaking existing clients.
  3. 3Learn why 'never remove a field, only add' is a common additive-versioning strategy.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge