Please don't break public APIs

, 3 minutes to read, 50 views

If you’ve visited my blog before, you might have noticed that each post displays its view count. This little feature is powered by Umami, a privacy-focused, self-hosted analytics platform that I run on my server. It’s a simple touch that I enjoy having — seeing which posts resonate with readers gives me valuable feedback.

But recently, this seemingly straightforward feature caused me some unexpected headaches.

What happened

Last week, I decided to update my Umami installation to the latest version. Nothing unusual there — keeping software updated is just good practice for security and performance reasons.

However, after the update, I noticed something odd: all my post view counters were not showing up. A quick investigation revealed that the API calls were failing with error messages about a missing parameter.

It turns out that the Umami API now requires a timezone parameter for every request. This parameter wasn’t required in the previous version — it was an optional field that defaulted to UTC if not specified. Now, suddenly, it’s mandatory.

The fix was relatively straightforward — I just needed to add the timezone parameter to my API calls.

But while the solution was simple, the principle of the matter still bothers me.

Public APIs should not be changed unexpectedly

API changes are inevitable as software evolves. New features get added, old ones get improved or deprecated. That’s the natural lifecycle of software development.

However, there’s a crucial distinction between internal APIs (used only within your system) and public APIs (used by external systems or users):

When you provide a public API, other developers build their systems around your interface. They rely on the stability of that contract. Breaking changes unexpectedly or migration paths is like changing the locks on your house without giving your family members new keys.1 What should be done instead

There are established patterns for evolving APIs without breaking existing integrations:

  1. API versioning is the gold standard approach. As Troy Hunt explains in his excellent post on API versioning, this allows you to introduce breaking changes in a new version while maintaining the old one for existing users.2

  2. Deprecation periods give users time to adapt. If you must change an existing API, mark the old behaviour as deprecated, communicate clearly about the upcoming change, and provide a generous timeline (months, not days) before the old behaviour stops working.

  3. Backward compatibility should be maintained whenever possible. In my case, the Umami API could have easily continued to support requests without the timezone parameter by falling back to the previous default behaviour.

For small projects like my blog, these kinds of breaking changes are merely annoying. But for businesses relying on third-party APIs for critical functions, unexpected changes can cause significant disruption and cost real money to fix.

So please, if you maintain a public API: version it, communicate changes clearly, and remember that stability is a feature, not a limitation.3


  1. I’ve seen this pattern repeatedly across the industry. Even major companies like Twitter (now X) have been criticised for breaking API changes that affected thousands of developers and businesses. ↩︎

  2. There are multiple approaches to API versioning: URL paths (/api/v2/resource), query parameters (/api/resource?version=2), or HTTP headers (Accept: application/vnd.company.v2+json). Each has pros and cons, but any versioning is better than none. ↩︎

  3. If you’re interested in API design best practices, I highly recommend The Design of Web APIs by Arnaud Lauret. It covers these principles in much more depth. ↩︎

Tags: Technical, Web Development