Thursday, July 3, 2025

Client-Side Streaming gRPC : A Real-World File Upload Example

This project demonstrates client-side streaming using gRPC with a Spring Boot application. It includes:

  • A gRPC server that receives file chunks via stream and reconstructs them.

  • A REST client that accepts multipart/form-data uploads and streams the file to the server over gRPC.

πŸ”§ Technologies Used

  • Java 11
  • Spring Boot 2.7.x
  • gRPC (1.54.0)
  • Protocol Buffers (proto3)
  • Maven
  • WebFlux + Server-Sent Events (SSE) for REST integration

βœ…Code Repository LinkΒ 

LinkΒ -Β grpc-client-streaming

1. Start gRPC Server

  • cd grpc-client-streaming-upload-server mvn spring-boot:run

2. Start REST Client

  • cd grpc-client-streaming-upload-client mvn spring-boot:run

3. Upload a File via REST

  • curl -X POST http://localhost:8080/upload -H "Content-Type: multipart/form-data" -F "file=@/path/to/your/file.txt"

βœ… Project Structure

Server: grpc-client-streaming-upload


  • grpc-client-streaming-upload/ β”œβ”€β”€ src/ β”‚ └── main/ β”‚ β”œβ”€β”€ java/com/example/grpc/ β”‚ β”‚ β”œβ”€β”€ GrpcApplication.java # Spring Boot main class β”‚ β”‚ └── FileUploadService.java # gRPC service implementation β”‚ β”œβ”€β”€ proto/upload.proto # gRPC service and message definitions β”‚ └── resources/application.properties # gRPC + HTTP port config └── pom.xml # Maven config with protobuf plugin

Client: grpc-client-streaming-upload-client


  • grpc-client-streaming-upload-client/ β”œβ”€β”€ src/ β”‚ └── main/ β”‚ β”œβ”€β”€ java/com/example/grpc/ β”‚ β”‚ β”œβ”€β”€ GrpcClientApplication.java # Spring Boot main class β”‚ β”‚ └── FileUploadController.java # REST endpoint that calls gRPC client β”‚ β”œβ”€β”€ proto/upload.proto # Same proto for stub generation β”‚ └── resources/application.properties # gRPC target address config └── pom.xml # Maven config with protobuf plugin

πŸ” Quick Explanation of Key Classes


🧬 Proto File 


  • syntax = "proto3";
    option java_multiple_files = true;
    option java_package = "com.example.grpc";
    option java_outer_classname = "FileUploadProto";
    service FileUploader {
    rpc UploadFile (stream FileChunk) returns (UploadStatus);
    }
    message FileChunk {
    string filename = 1;
    bytes content = 2;
    }
    message UploadStatus {
    bool success = 1;
    string message = 2;
    }


πŸ” Diagram: REST β†’ gRPC Flowe


  • [User/Client] ──HTTP/POST──> REST Controller (Spring Boot) └──▢ Reads multipart file └──▢ Opens gRPC stream └──▢ Sends file chunks └──▢ gRPC Server handles each chunk └──▢ On complete, sends UploadStatus

βœ… When to Use gRPC Client-Side Streaming

🚫 Anti-Patterns / When Not to Use It

🚫 gRPC Anti-Patterns & When Not to Use It


πŸš€ gRPC Streaming Performance Comparison

πŸ“‘ Mastering Advanced gRPC Communication Patterns

Modern distributed systems demand high-performance, language-agnostic communication. gRPCβ€”Google’s high-speed RPC frameworkβ€”has become a core enabler of service-to-service communication in microservices architectures. While Unary RPCs serve simple request-response models, gRPC shines in more complex, real-time communication through streaming patterns.


In this post, we deep dive into four powerful gRPC communication patterns:

  • Unary RPC

  • Server Streaming RPC

  • Client Streaming RPC

  • Bidirectional Streaming RPC

1️⃣ Unary RPC – The Standard Request-Response

Unary RPC is the simplest form of gRPC where the client sends one request and gets one response from the server.

πŸ“Š Use Case

  • Get user profile by ID

  • Calculate tax for a product

  • Health check API

πŸ“ Diagram

Β  Β Β Β  Β 

πŸ“œ Protobuf Definition

  • rpc GetUser(UserRequest) returns (UserResponse);

🧩 Real-world Example

  • message UserRequest { string user_id = 1; } message UserResponse { string name = 1; string email = 2; }
    βœ…Β Real-world ExampleΒ Code Repository Link

    2️⃣ Server Streaming RPC – One Request, Many Responses

    The client sends a single request to the server and receives a stream of responses.

    πŸ“Š Use Case

    • Real-time stock updates

    • Event logs streaming

    • Download large files in chunks

    πŸ“ Diagram

    Β Β  Β Β Β  Β 

    πŸ“œ Protobuf Definition
    • rpc StreamStockPrices(StockRequest) returns (stream StockPrice);
    🧩 Real-world Example
    • message StockRequest { string symbol = 1; } message StockPrice { string symbol = 1; double price = 2; string timestamp = 3; }
    πŸš€ Java Server Snippetl
    • @Override public void streamStockPrices(StockRequest request, StreamObserver<StockPrice> responseObserver) { for (int i = 0; i < 5; i++) { StockPrice price = StockPrice.newBuilder() .setSymbol(request.getSymbol()) .setPrice(Math.random() * 1000) .setTimestamp(Instant.now().toString()) .build(); responseObserver.onNext(price); Thread.sleep(1000); // Simulate delay } responseObserver.onCompleted(); }

    βœ…Server Streaming RPCΒ blog post LinkΒ 

      3️⃣ Client Streaming RPC – Many Requests, One Response

      The client sends a stream of requests, and once done, the server processes the input and responds with a single response.

      πŸ“Š Use Case

      • File upload in chunks

      • Sensor data aggregation

      • Log batch processing

      πŸ“ Diagram

      Β Β  Β Β Β  Β 

      πŸ“œ Protobuf Definition:
      • rpc UploadFile(stream FileChunk) returns (UploadStatus);
      🧩 Real-world Example:
      • message FileChunk { bytes data = 1; } message UploadStatus { string status = 1; int64 total_bytes = 2; }
      πŸš€ Java Server Snippet:
      • @Override public StreamObserver<FileChunk> uploadFile(StreamObserver<UploadStatus> responseObserver) { return new StreamObserver<FileChunk>() { long totalBytes = 0; @Override public void onNext(FileChunk chunk) { totalBytes += chunk.getData().size(); } @Override public void onCompleted() { UploadStatus status = UploadStatus.newBuilder() .setStatus("SUCCESS") .setTotalBytes(totalBytes) .build(); responseObserver.onNext(status); responseObserver.onCompleted(); } @Override public void onError(Throwable t) { responseObserver.onError(t); } }; }

      βœ…Server Streaming RPCΒ blog post LinkΒ 

        4️⃣ Bidirectional Streaming RPC – Many-to-Many Messaging

        The client and server both send streams of messages. Both operate independently, allowing real-time duplex communication.

        πŸ“Š Use Case

        • Chat applications

        • Multiplayer gaming

        • Real-time trading systems

        πŸ“ Diagram

        Β Β  Β Β Β  Β 

        πŸ“œ Protobuf Definition:
        • rpc Chat(stream ChatMessage) returns (stream ChatMessage);
        🧩 Real-world Example:
        • message ChatMessage { string sender = 1; string message = 2; string timestamp = 3; }
        πŸš€ Java Server Snippet:
        • @Override public StreamObserver<ChatMessage> chat(StreamObserver<ChatMessage> responseObserver) { return new StreamObserver<ChatMessage>() { @Override public void onNext(ChatMessage msg) { System.out.println("Received: " + msg.getMessage()); ChatMessage reply = ChatMessage.newBuilder() .setSender("Server") .setMessage("Echo: " + msg.getMessage()) .setTimestamp(Instant.now().toString()) .build(); responseObserver.onNext(reply); } @Override public void onCompleted() { responseObserver.onCompleted(); } @Override public void onError(Throwable t) { responseObserver.onError(t); } }; }

        βœ…Server Streaming RPCΒ blog post LinkΒ 

          πŸ“Œ Summary ComparisonΒ 

          🚫 When Not to Use Streaming RPCs 

          • While powerful, streaming adds complexity. Avoid them when:

            • You don’t need real-time communication.

            • You’re behind intermediaries that don’t support HTTP/2.

            • You require retry logic per message (streaming retries are complex).

            • You need precise observability and tracing per operation.

          πŸ“Ž Final Thoughts

          • Understanding these advanced patterns lets you choose the right tool for the right communication problem. gRPC’s streaming capabilities go far beyond what REST can offer for real-time, high-throughput systems.

          • If you're building a microservices platform, data pipeline, or real-time analytics dashboard, mastering these patterns will make your communication scalable, resilient, and blazing fast.

          πŸ“š Further ReadingΒ 


          Building a Server-Side Streaming gRPC Service in Spring Boot: A Stock Ticker Demo

          🧠What is gRPC and Why Use It?

          This project demonstrates how to implementΒ server-side streamingΒ usingΒ gRPCΒ in aΒ Spring BootΒ application withΒ Java 11. The use case simulates a stock ticker that streams real-time stock prices to the client.


          πŸ”§ Technologies Used

          • Java 11
          • Spring Boot 2.7.x
          • gRPC (1.54.0)
          • Protocol Buffers (proto3)
          • Maven
          • WebFlux + Server-Sent Events (SSE) for REST integration

          Wednesday, July 2, 2025

          Getting Started with gRPC and Spring Boot β€” A Beginner’s Guide

          As microservices become the backbone of modern backend architecture, efficient communication between services becomes more critical. In this post, we’ll explore how gRPC fits into the picture and how you can get started with it using Spring Boot.

          Wednesday, June 4, 2025

          Unlocking Spring Boot Performance: A Guide to Effective JVM Tuning

          🧠 Why JVM Settings Matter

          When we think about speeding up an application, we often think about optimizing code, changing architecture, or rewriting services. But sometimes the real bottleneck is much deeper β€” in how the Java Virtual Machine (JVM) manages memory, garbage collection, and system resources.

          Spring Boot apps run on the JVM. That means by tweaking the JVM's configuration, you can unlock massive performance improvements β€” without changing your code.

          Spring Boot apps run inside the Java Virtual Machine (JVM). The JVM is responsible for managing:

          • Memory allocation

          • Garbage collection (GC)

          • Thread scheduling

          • JIT (Just-In-Time) compilation

          • Native I/O handling

          Most developers never touch JVM flags, but the default settings are designed for general-purpose use β€” not high-performance production environments.

          Tuning the JVM is like customizing your engine to your terrain. For server applications, especially ones running in Docker or Kubernetes, JVM tuning can unleash massive improvements in throughput, latency, and reliability.

          Friday, April 12, 2024

          Navigating the Service Mesh Landscape: A Journey with Istio πŸš€

          A service mesh is a crucial component in modern application architectures. It acts as a dedicated infrastructure layer responsible for managing communication between microservices within an application.

          Wednesday, December 20, 2023

          Building RESTful APIs with Spring Boot and OpenAPI Generator

          • In this Post, we will explore how to create RESTful APIs using Spring Boot and OpenAPI Generator. OpenAPI Generator simplifies the process of building APIs by generating server stubs and client SDKs from OpenAPI Specifications.Β 
          • We'll go through the steps of setting up a Spring Boot project, integrating OpenAPI Generator, and creating a real-time example API.

          You may also like

          Kubernetes Microservices
          Python AI/ML
          Spring Framework Spring Boot
          Core Java Java Coding Question
          Maven AWS