REST API Versioning: Why It’s Needed and How to Implement Four Methods in Spring Boot

This article explains the necessity of RESTful API versioning and demonstrates four practical versioning techniques—URI, request‑parameter, custom header, and media‑type—using a Spring Boot example with code snippets and discusses factors for choosing the appropriate approach.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
REST API Versioning: Why It’s Needed and How to Implement Four Methods in Spring Boot

In this article we explain why RESTful API versioning is necessary and compare four common versioning strategies.

Why version a RESTful API

The best approach is to avoid versioning by building backward‑compatible services, but many real‑world scenarios require explicit version control.

Build backward‑compatible services to avoid versioning whenever possible.

We illustrate the need with a Student service that evolves from returning a single name string to returning a structured name object. { "name": "Bob Charlie" } Later the service splits the name into first and last name:

{ "name": { "firstName": "Bob", "lastName": "Charlie" } }

To support both versions the API must be versioned.

Four versioning methods in a Spring Boot Maven project

Below are the Maven dependencies needed:

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

URI versioning

@RestController
public class StudentUriController {

    @GetMapping("v1/student")
    public StudentV1 studentV1() {
        return new StudentV1("javadaily");
    }

    @GetMapping("v2/student")
    public StudentV2 studentV2() {
        return new StudentV2(new Name("javadaily", "JAVA日知录"));
    }
}

Requests: http://localhost:8080/v1/student returns {"name":"javadaily"}. http://localhost:8080/v2/student returns {"name":{"firstName":"javadaily","lastName":"JAVA日知录"}}.

Request‑parameter versioning

@RestController
public class StudentParmController {

    @GetMapping(value="/student/param", params="version=1")
    public StudentV1 studentV1() {
        return new StudentV1("javadaily");
    }

    @GetMapping(value="/student/param", params="version=2")
    public StudentV2 studentV2() {
        return new StudentV2(new Name("javadaily", "JAVA日知录"));
    }
}

Requests with .../student/param?version=1 or .../student/param?version=2 return the corresponding payloads.

Custom header versioning

@RestController
public class StudentHeaderController {

    @GetMapping(value="/student/header", headers="X-API-VERSION=1")
    public StudentV1 studentV1() {
        return new StudentV1("javadaily");
    }

    @GetMapping(value="/student/header", headers="X-API-VERSION=2")
    public StudentV2 studentV2() {
        return new StudentV2(new Name("javadaily", "JAVA日知录"));
    }
}

Clients set the header X-API-VERSION: 1 or 2 to select the version.

Media‑type (Accept header) versioning

@RestController
public class StudentProduceController {

    @GetMapping(value="/student/produce", produces="application/api-v1+json")
    public StudentV1 studentV1() {
        return new StudentV1("javadaily");
    }

    @GetMapping(value="/student/produce", produces="application/api-v2+json")
    public StudentV2 studentV2() {
        return new StudentV2(new Name("javadaily", "JAVA日知录"));
    }
}

Clients specify Accept: application/api-v1+json or application/api-v2+json to obtain the desired version.

Factors influencing the choice of versioning strategy

URI pollution – URL‑based versioning can clutter the URI space.

Header misuse – the Accept header was not designed for versioning.

Caching – header‑based versioning requires cache variation on custom headers.

Browser friendliness – URL‑based versions are easier for non‑technical consumers.

API documentation – how to document multiple URLs for the same service.

There is no perfect solution; select the method that fits your project.

Typical usage by major API providers

Media‑type versioning – GitHub

Custom header – Microsoft

URI path – Twitter, Baidu, Zhihu

Request‑parameter – Amazon

These examples demonstrate how to implement and choose REST API versioning in a Spring Boot application.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaAPISpringBootrestVersioning
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.