Latest / Tech Leadership with Fexingo: Engineering Managers, CTOs, and Technical Leadership Conversations / How One CTO Uses API Versioning to Avoid Breaking Changes
Transcript
- Lucas: If you're a developer, you've probably felt that moment of dread when an API call you've relied on for months suddenly returns a 400 and you realize a team upstream changed the contract without telling anyone. Luna: Right, the famous 'works on my machine' but then the integration breaks in staging. Lucas: Exactly. And for CTOs, every breaking change is a trust tax. You lose credibility with internal teams, with partners, sometimes with customers. So how do you avoid it? The most practical answer I've seen is disciplined API versioning. Luna: We've talked about a lot of CTO tactics on this show, but I don't think we've done a deep dive on versioning yet. Let's fix that today. Lucas: So I want to anchor this in a specific story. I've been following Sarah Chen, CTO at a mid-size fintech called PayBridge — roughly 80 engineers, they handle payment processing for about 200 merchants. Luna: And she's been vocal about API versioning on her blog. I've read a few of her posts. Lucas: Exactly. She took over a stack that had zero versioning. Every endpoint was just /api/v1/ — but the v1 was a lie because the contract changed whenever a team needed a new field. She inherited a mess. Luna: And I'm guessing the first incident was a payment integration failing because a merchant's system expected an old response format. Lucas: That's exactly what happened. A major merchant's recurring billing integration broke because PayBridge changed a response field from a string to an integer. The merchant's parser threw an error and payments failed for about four hours before they caught it. Luna: Ouch. So Sarah's response was to implement a proper versioning strategy. Lucas: Right. She went with url based versioning — the simplest approach. So instead of /api/transactions, you'd have /api/v1/transactions and /api/v2/transactions. She told me she considered header versioning and parameter versioning, but for her team's maturity level, URL versioning was the least cognitive overhead. Luna: What's the trade-off there? I've heard people argue that URL versioning clutters the endpoint namespace. Lucas: It does. But the benefit is visibility. Any developer can look at a URL and immediately know which version they're hitting. With header versioning, it's hidden in the request headers, and debugging becomes harder — you have to check the header to know what contract is in play. For a team that's still building discipline, that's friction. Luna: Makes sense. So she went with v1, v2, v3. But how did she handle the transition without breaking existing integrations? Lucas: She introduced a sunset policy. Every version has a minimum support window of one year from the date a newer version is released. So when v2 ships, v1 is still fully supported for twelve months. During that time, they add a deprecation header to v1 responses: 'Sunset: Sat, 1 Dec 2026 00:00:00 GMT'. Luna: That gives consumers a clear deadline. Did they use semantic versioning for the API itself? Lucas: Yeah, they adopted a loose semantic versioning: major version for breaking changes, minor version for additive changes that are backward compatible. And they publish a changelog with every release. Sarah said the key rule is: never remove a field, never change a field's type, never make a required field optional. Only add, never subtract. Luna: That's a hard discipline. But doesn't that lead to bloat over time? Old responses carrying deprecated fields forever? Lucas: It does. But Sarah's position is: bloat is better than breakage. And after the sunset period, they can clean up. She told me that after the first year, they had only two consumers still on v1 — both small integrations — and they worked with them to migrate before the deadline. Luna: So the sunset policy isn't just theoretical; they actually forced the migration. Lucas: Exactly. And they automated it. They built a dashboard that shows which clients are on which version, and when their last call was. So the engineering team can proactively reach out to stragglers. Luna: That's a pretty nice operational loop. How did the team react to the extra overhead? I imagine some developers felt it slowed them down. Lucas: There was pushback at first. Some engineers argued that versioning added ceremony — you have to maintain multiple controller files, duplicate tests, etc. But Sarah framed it as a reliability investment. She showed data: in the six months before versioning, they had eight incidents caused by breaking changes. In the six months after, zero. Luna: That's a compelling number. Eight to zero. Lucas: And that's not even counting the near-misses. Developers started to see versioning as a safety net. If they needed to change a response, they didn't have to worry about breaking someone — they just bumped the version and moved forward. Luna: I think a lot of CTOs would love that kind of peace of mind. But implementing it requires a cultural shift, not just a technical one. Lucas: Absolutely. And Sarah emphasized that the biggest hurdle wasn't the technology — it was communication. She put in place a policy: any team that introduces a new version must send a brief migration guide to all known consumers at least 90 days before the old version's sunset. Luna: That's proactive. And she also added a response header with a link to the migration docs, right? Lucas: Yes, the 'Link' header with rel='sunset' pointing to a changelog. So any developer who sees a deprecation warning can click through immediately. It's a small touch, but it reduces friction. Luna: I want to ask about internal APIs versus external. Do they version differently? Lucas: Good question. For internal microservices, they use a lighter versioning: just a major version number, no sunset policy enforced automatically. Teams can deprecate quickly if they have no external consumers. But any API that's exposed to merchants gets the full treatment. Luna: That's pragmatic. Not all APIs need the same rigor. Lucas: Sarah also shared a nice trick: she has a rule that any new endpoint must include a version from day one, even if it's v1. That way, versioning is never an afterthought. It's built into the template. Luna: I've seen teams skip that and then retrofitting versioning is a nightmare. Lucas: It is. And you end up with the situation she inherited — a faux v1 that's actually multiple contracts in disguise. Luna: You know, this conversation reminds me why I appreciate shows like this. They dig into the real mechanics of engineering leadership. And it's content that stays ad-free because of listener support. Lucas: Yeah, it's a good point. A couple of dollars a month from people who find value in these episodes genuinely keeps the lights on here. If you've gotten something out of today's versioning deep dive, you can find us at buy me a coffee dot com slash fexingo. Luna: Small contributions, big difference. And it means we never have to run interruptive ads. Lucas: Exactly. So back to versioning — one more detail I found interesting. Sarah's team measures version adoption as a key metric. They track how quickly consumers migrate from v1 to v2, and they set targets. For example, they aim for 80 percent adoption within six months of a new version release. Luna: That's a good leading indicator. Low adoption suggests the migration docs aren't clear enough. Lucas: Right. And if adoption is slow, they invest in better communication or even offer to help with the migration. The goal is to make upgrading easy, not just possible. Luna: I think a lot of teams focus on the technical versioning mechanics but neglect the human side — telling people what changed and why. Lucas: Sarah's approach is a reminder that versioning is a contract between the API provider and the consumer. And like any contract, clarity and trust matter more than the specific syntax. Luna: So if a CTO is listening and thinking about starting versioning from scratch, what's the first step Sarah would recommend? Lucas: She says: pick a simple versioning scheme — URL is fine — and commit to a sunset policy. Then communicate it widely. You don't need to get it perfect; you need to get it started. Versioning is iterative too. Luna: And the cost of not doing it is incidents and eroded trust. Lucas: Exactly. PayBridge had eight incidents in six months before versioning. Since then, zero. That's not just a number — it's the difference between merchants trusting your platform and looking for alternatives. Luna: Good point. Thanks for breaking down Sarah's approach. I think a lot of engineering leaders will find something practical here. Lucas: Glad to dig into it. Versioning isn't glamorous, but it's one of those foundational practices that separates mature engineering orgs from chaotic ones. Luna: And it's a topic we haven't covered before, so I'm glad we did today. Lucas: Thanks for listening. We'll be back next week with another deep dive into a CTO's specific playbook.