Hello! Let's begin our next lesson in the "API Security and Best Practices" module.
In our last session, we focused on securing the data coming into our API by strengthening input validation and sanitization. We ensured that our serializers act as diligent gatekeepers. Now, we'll shift our focus from the content of a single request to the long-term evolution of the API itself.
As applications grow and business needs change, your API will inevitably need to change too. You might add new fields, remove old ones, or restructure data entirely. This raises a critical question: how do you introduce these changes without breaking existing client applications that depend on the old structure?
This brings us to today's learning outcome: Describe common API versioning strategies (URL, header, query parameter). We'll explore the "why" and "what" of API versioning, setting the foundation for a key practice in professional backend development.
1. The Inevitability of Change
Imagine your application has a User model, and your API currently returns user data like this:
{
"first_name": "Alex",
"last_name": "Williams"
}
A mobile app is built to consume this API, displaying first_name and last_name in separate fields. Now, a new requirement comes from the product team: they want to replace first_name and last_name with a single full_name field for all new development.
If you simply change the API to return this:
{
"full_name": "Alex Williams"
}
You've just broken the existing mobile app. It's still looking for first_name and last_name, which are no longer there. This is known as a breaking change. API versioning is the solution to this problem. It allows you to release new, improved versions of your API while maintaining older versions for existing clients, giving them time to upgrade.
API Versioning with FastAPI Made EASY (Do This Before It’s Too Late)
The video 'API Versioning with FastAPI Made EASY' provides an excellent introduction to this exact problem. Although it uses a different framework (FastAPI), the initial problem statement is universal and clearly illustrates why versioning is necessary.
Please watch from the beginning to 02:59. The presenter sets up a scenario where adding an 'email' field to an existing API response creates a versioning challenge, which is precisely the problem we are discussing.
2. Explicit Versioning and SemVer
The core idea behind versioning is to explicitly maintain multiple, callable versions of your API. This allows you to evolve your API in a structured way. But what do version numbers like v1, v2, or v3.1.1 actually mean?
For this, many developers follow a specification called Semantic Versioning (SemVer). It provides a formal system for assigning meaning to version numbers.
Web API - Explicit Versioning | URI vs Headers vs Request Params | SemVer | Sunset Headers
The video 'Web API - Explicit Versioning' provides a concise explanation of both explicit versioning and the SemVer system.
First, watch from 00:47 to 01:54 to understand the concept of explicit versioning. Then, watch from 04:49 to 06:16 to learn about Semantic Versioning (Major, Minor, Patch) and what each number signifies.
To summarize SemVer (MAJOR.MINOR.PATCH):
- MAJOR version (e.g.,
v1->v2): You increment this when you make incompatible, breaking changes. This is a signal to all clients that they will need to modify their code to use the new version. - MINOR version (e.g.,
v1.0->v1.1): You increment this when you add new functionality in a backward-compatible way. For example, adding a new optional field to a response. Existing clients won't break. - PATCH version (e.g.,
v1.1.0->v1.1.1): You increment this for backward-compatible bug fixes.
Most public APIs only expose the MAJOR version (e.g., /v1, /v2), as minor and patch changes are backward-compatible and clients can typically be upgraded to them automatically.
3. Common Versioning Strategies
Now that we know why we version and what the numbers mean, let's explore how a client can request a specific version of an API. There are three primary strategies.
The following article from the Medium publication "CodeX" gives a great high-level overview of these strategies, including their advantages and disadvantages.
API Versioning Strategies: Backward Compatibility in REST ...
Please read the following article to get a concise summary of the different versioning strategies.
Read the section titled 'Common API Versioning Strategies', including its subsections for 'URI Versioning', 'Header-Based Versioning', and 'Query Parameter Versioning'. Focus on the examples and the pros and cons listed for each.
Let's break these down further, with a focus on how they relate to Django REST Framework. The official DRF documentation is the best source for this. We will be referencing its "Versioning" page.
A. URL Path Versioning
This is arguably the most common and straightforward strategy. The version number is embedded directly in the URL.
- Example:
https://api.example.com/v1/users/
This is the approach used by major API providers like Stripe and Slack.

The DRF documentation explains this strategy under two related schemes: URLPathVersioning and NamespaceVersioning. To a client, they look the same; the difference is in the server-side configuration.
Please read the sections 'URLPathVersioning' and 'NamespaceVersioning'. Note how both result in a URL like /v1/bookings/, but the underlying Django URL configuration is different.
- Pros:
- Highly visible and clear: It's immediately obvious which version of the API is being called.
- Easy to test: You can simply type different URLs into a browser or API client to test different versions.
- Bookmarkable: URLs for specific versions can be saved and shared easily.
- Cons:
- "Pollutes" the URI: Some argue this violates the REST principle that a URI should identify a unique resource, not a version of it. The resource is
/users/, and/v1/users/is just one representation. - Can lead to more complex routing logic: As you see in the DRF examples, it requires specific URL patterns.
- "Pollutes" the URI: Some argue this violates the REST principle that a URI should identify a unique resource, not a version of it. The resource is
This is the strategy we will implement in our next lesson due to its clarity and popularity.
B. Header Versioning
In this approach, the client requests a version via an HTTP header, keeping the URL itself "clean" and version-agnostic.
- Example 1 (Custom Header):
GET /users/with a headerX-API-Version: 1 - Example 2 (Accept Header):
GET /users/with the headerAccept: application/json; version=1.0

The DRF documentation covers this in the 'AcceptHeaderVersioning' section, which is often considered the most 'RESTful' approach.
Read the 'AcceptHeaderVersioning' section. Pay attention to the example HTTP request and the mention of 'vendor media types,' which is a more formal way to implement this.
- Pros:
- Clean URLs: The URI (
/users/) remains constant and purely represents the resource. - RESTful: Aligns well with the principles of content negotiation, where the client "negotiates" for the representation it wants.
- Clean URLs: The URI (
- Cons:
- Less visible: The version is "hidden" in the headers, making it harder to see at a glance or test in a browser's address bar.
- More complex for clients: Requires clients to know how to construct requests with custom headers.
C. Query Parameter Versioning
This strategy is a middle ground, keeping the URL path clean but making the version visible in the query string.
- Example:
https://api.example.com/users?version=1
Finally, let's look at the DRF documentation for this simple style.
Read the short 'QueryParameterVersioning' section to see an example of this straightforward method.
- Pros:
- Simple to implement and use.
- Keeps the URL path clean.
- Cons:
- Potential caching issues: Some proxy caches might not handle query parameters well or might treat
/users?version=1and/users?version=2as requests for completely different resources, leading to cache bloat. - Can be cluttered: If the endpoint already uses many query parameters for filtering and sorting, adding another for versioning can make the URL messy.
- Potential caching issues: Some proxy caches might not handle query parameters well or might treat
Test your understanding!
A colleague is designing a new public API for your company. The primary consumers will be developers at other companies. A key requirement is that it should be extremely easy for a developer to explore and test different API versions directly in their web browser.
Which versioning strategy would you recommend and why?
Show answer
URL Path Versioning would be the best recommendation in this scenario.
Reasoning: The key requirement is ease of exploration and testing in a web browser. URL Path Versioning makes the version explicit in the address bar (e.g., api.company.com/v1/products/ vs. api.company.com/v2/products/). A developer can simply change the v1 to v2 in their browser to see the new version's response.
Header and Query Parameter versioning are less ideal for this specific use case because you cannot easily change headers in a standard browser address bar, and while query parameters are visible, they are less conventional for major version changes and can be less intuitive than a clear path segment.
Conclusion
Today, we explored the critical concept of API versioning—a fundamental practice for building sustainable, professional-grade backend services. Understanding how to manage change without disrupting existing users is a hallmark of a skilled backend engineer.
Key Takeaways:
- Why Version? To introduce new features and breaking changes without breaking existing client applications, ensuring backward compatibility.
- What do versions mean? Semantic Versioning (
MAJOR.MINOR.PATCH) provides a standard for communicating the nature of changes. Major versions indicate breaking changes. - How do we version? There are three common strategies, each with trade-offs:
- URL Path Versioning (
/v1/resource): Most visible and easy to use, but "pollutes" the URL. - Header Versioning (
Accept: ...; version=1): Keeps URLs clean and is considered more "RESTful," but is less intuitive for clients. - Query Parameter Versioning (
/resource?version=1): A simple compromise, but can have caching implications.
- URL Path Versioning (
Preview of the Next Lesson:
We've covered the theory and described the common strategies. In the next lesson, we will put this knowledge into practice. We will implement URL-based versioning for a DRF API, as it is one of the most common and explicit methods for managing API evolution. You'll see how DRF's built-in tools make this a surprisingly manageable task.