REST API versioning in Go

Published: Oct 6, 2024

When developing APIs that are used by external applications, e.g., from customers, it is always important to version them to create a stable system.

You should not simply change the API, as this could lead to breaking changes in the client systems. Instead, create new versions and let the client update to the new version when they are ready.

To create such a system, I tried out multiple architectures, and in this blog post, I want to show you the best practice that I could determine.

In this blog post, I will write a REST server using the web framework Gin and add a versioning system to it.

• • •
• • •

What is the requirement?

Before I started, I had to define the requirements my solution should meet. Here are my thoughts about the topic.

Versionize Endpoints or the whole API

What I've seen most often is that the API is versioned, like /api/v1/books. But when you modify code, usually you don't change the whole API, you change the endpoint. From one version to another, endpoints can change, but some endpoints may stay the same.

Versioning the API endpoint can be done using the path like /api/books/v1, but this looks weird, especially when you add subpaths, which may also be versioned. Another way would be to handle the version using query parameters or headers.

I've chosen to version the endpoints internally, because they can change, but pack the newest versions of those endpoints in a versioned API, because this is the easiest way to use the API from the client.

How to deprecate endpoints

You should be able to set an endpoint as deprecated. Sometimes older versions should not be used, e.g., when you want to change the system, or it becomes not secure enough.

But I think there should be two types of "deprecated": a warning and an error.

The warning should be a header, which the client can then log to detect that an endpoint will become deprecated, so the developer has time to update the API call.

The error should be an HTTP Status Code 410 Gone error, which states that the endpoint cannot be used anymore because it is deprecated, and tells the developer what should be done to fix the issue.