Spring Boot REST to gRPC Migration Guide (With Code)

Moving from REST to gRPC can be a powerful decision for teams looking to improve the performance, scalability, and efficiency of their microservices. While REST has been the go-to protocol for years, modern application demands—such as real-time communication and reduced latency—make gRPC an appealing upgrade. This guide will walk you through the process of migrating from REST to gRPC in a Spring Boot application, step-by-step, with practical examples.

By the end of this tutorial, you’ll understand how to map endpoints, use .proto files to define services, and convert existing REST controllers into gRPC services—all while ensuring a smooth transition without disrupting existing clients.

Table of Contents

  1. Why Migrate from REST to gRPC?
  2. Mapping Endpoints (GET/POST to Unary RPC)
  3. Creating .proto Files Matching REST DTOs
  4. Converting Controllers to gRPC Services
  5. Handling Exceptions with StatusRuntimeException
  6. Supporting Legacy REST Temporarily
  7. Enabling grpc-web for Browser Clients
  8. Adding Monitoring with Prometheus and Grafana
  9. Updating CI/CD Pipelines
  10. Sample Migration Repository
  11. FAQs
  12. Summary

Why Migrate from REST to gRPC?

While REST is widely used and has near-universal compatibility, there are several reasons why gRPC could be a better fit for modern microservices:

1. Performance and Efficiency

  • gRPC uses HTTP/2, which supports multiplexing and bidirectional streaming, compared to REST’s reliance on single-direction HTTP/1.1.
  • It employs Protocol Buffers (Protobuf) for serialization, which generates compact, binary messages that are far smaller and faster than JSON.

2. Streaming Capabilities

gRPC excels in scenarios requiring real-time communication, such as:

  • Real-time analytics dashboards
  • Live notifications
  • Video or audio streaming

3. Better Scalability for Internal Microservices

gRPC’s efficient data serialization and low latency make it ideal for inter-service communication at scale.

For more on the benefits of gRPC, refer to the official gRPC documentation.


Mapping Endpoints (GET/POST to Unary RPC)

REST APIs typically rely on HTTP verbs such as GET, POST, PUT, and DELETE. These can be mapped directly to gRPC unary RPC methods.

Example Mapping

REST EndpointgRPC MethodPurpose
GET /api/resourcerpc GetResource (Request) returns (Response);Fetch resources
POST /api/resourcerpc CreateResource (Request) returns (Response);Create a new resource
PUT /api/resourcerpc UpdateResource (Request) returns (Response);Update a resource
DELETE /api/resourcerpc DeleteResource (Request) returns (Response);Delete a resource

Define these methods in .proto files, as shown in the next section.


Creating .proto Files Matching REST DTOs

The .proto file defines the contract between client and server in a gRPC service. It serves a similar purpose to the object model in REST (e.g., DTOs in Spring Boot).

Example .proto File

Here’s an example for a service that interacts with a “User” resource:

   syntax = "proto3";

   package user;

   service UserService {
       rpc GetUser (UserRequest) returns (UserResponse);
       rpc CreateUser (UserRequest) returns (UserResponse);
   }

   message UserRequest {
       int32 id = 1;
       string name = 2;
   }

   message UserResponse {
       int32 id = 1;
       string name = 2;
       string status = 3;
   }

Save this file under src/main/proto/.

Run Maven to generate the gRPC stubs:

   mvn clean compile

Generated Java classes (e.g., UserServiceGrpc.java) will be available under target/generated-sources.

Learn more about defining Protobufs here.


Converting Controllers to gRPC Services

Convert your REST controllers into gRPC services by implementing the generated stubs.

Example REST Controller

   @RestController
   public class UserController {
       @GetMapping("/api/user/{id}")
       public User getUser(@PathVariable int id) {
           return new User(id, "John Doe");
       }
   }

Converted gRPC Service

   @GrpcService
   public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
       @Override
       public void getUser(UserRequest request, StreamObserver<UserResponse> responseObserver) {
           UserResponse response = UserResponse.newBuilder()
               .setId(request.getId())
               .setName("John Doe")
               .setStatus("Success")
               .build();
           responseObserver.onNext(response);
           responseObserver.onCompleted();
       }
   }

The @GrpcService annotation registers the service with the gRPC server.

Refer to Spring Boot gRPC Starter


Handling Exceptions with StatusRuntimeException

Spring Boot’s exception handling can often be replicated in gRPC using StatusRuntimeException.

Example

   @Override
   public void getUser(UserRequest request, StreamObserver<UserResponse> responseObserver) {
       try {
           if (request.getId() <= 0) {
               throw new IllegalArgumentException("Invalid ID");
           }

           UserResponse response = UserResponse.newBuilder()
               .setId(request.getId())
               .setName("John Doe")
               .setStatus("Success")
               .build();
           responseObserver.onNext(response);
           responseObserver.onCompleted();
       } catch (IllegalArgumentException e) {
           responseObserver.onError(Status.INVALID_ARGUMENT.withDescription(e.getMessage()).asRuntimeException());
       }
   }

Explore gRPC Error Handling


Supporting Legacy REST Temporarily

During migration, you may need to support both REST and gRPC simultaneously. Use the following strategy:

  1. Host gRPC on a Separate Port: Run gRPC and REST services concurrently.
  2. API Gateway: Use an API Gateway (e.g., Envoy) to route requests based on client type (REST/gRPC).

This ensures minimal disruption for existing clients.

Learn About Envoy Proxy


Enabling grpc-web for Browser Clients

Browsers don’t natively support gRPC. Use grpc-web, which acts as a proxy to translate HTTP/2 gRPC requests into standard HTTP/1.1.

Setup with Envoy

Configure Envoy as your grpc-web proxy:

   envoy:
     filter_chains:
       - filters:
           - name: envoy.filters.network.http_connection_manager
             config:
               codec_type: AUTO
               stat_prefix: ingress_http
               route_config:
                 ...

Learn More About grpc-web


Adding Monitoring with Prometheus and Grafana

Monitoring becomes critical in production environments. Add metrics collection to your gRPC services using Prometheus and dashboards using Grafana.

  1. Add dependencies:
   <dependency>
       <groupId>io.micrometer</groupId>
       <artifactId>micrometer-registry-prometheus</artifactId>
   </dependency>
  1. Configure an endpoint for Prometheus scraping:
   management.endpoints.web.exposure.include=prometheus

Set Up Prometheus and Grafana Monitoring


Updating CI/CD Pipelines

Update your CI/CD pipeline to:

  1. Generate Protobuf files.
  2. Build and deploy both REST and gRPC services.
  3. Add linting for .proto schema compliance.

Sample CI step for Protobuf:

   - name: Generate Protobuf
     run: mvn clean compile

Learn More About CI/CD for Spring Boot


Sample Migration Repository

Explore the complete migration example here:

GitHub – REST-to-gRPC Migration Example


FAQs

Why switch to gRPC from REST?

gRPC offers better performance, lower latency, and built-in streaming, making it ideal for microservices and real-time communication.

Can REST and gRPC coexist in one application?

Yes, you can run REST and gRPC services together during the migration.

What tools can test gRPC APIs?

Use tools like grpcurl, grpcui, or GUI clients like BloomRPC.

Is gRPC suitable for public APIs?

For public APIs exposed to client-side applications, use gRPC with grpc-web for compatibility.

What’s the learning curve for gRPC?

There is a moderate learning curve, but gRPC’s benefits outweigh the initial complexity.


Summary

Migrating from REST to gRPC in Spring Boot is a strategic decision to enhance API performance, scalability, and capabilities. By following the step-by-step guidance in this post—from mapping endpoints to implementing gRPC services—you’ll ensure a smooth transition. For a hands-on experience, clone the GitHub example repository and start experimenting today!

Similar Posts