Introduction: Is REST Dead? No, You Just Have a Choice Now
\n\nEvery Java developer has written a REST API at least once. It's convenient, familiar, and JSON is human-readable. But when load increases and latency becomes critical, REST starts to creak. And that's when gRPC enters the stage — a technology from Google that promises speed comparable to a local call, serialization speed 10 times faster than JSON, and built-in streaming support.
\n\nIn this article, we'll figure out when gRPC in Java is truly justified and when it's better to stick with REST. No fluff — only real scenarios, code examples, and honest benchmarks.
\n\nWhat is gRPC and Why Is Everyone Talking About It?
\n\ngRPC is a framework for remote procedure calls (RPC). Instead of JSON, it uses Protocol Buffers (protobuf) — a binary serialization format. Instead of HTTP/1.1 — HTTP/2 with multiplexing and header compression.
\n\nFor Java, this means:
\n- \n
- Strictly typed contracts via
.protofiles \n - Automatic generation of clients and servers \n
- Four types of interaction: unary, server streaming, client streaming, bidirectional streaming \n
- Built-in support for timeouts, deadlines, and load balancing \n
What Does a Typical .proto File Look Like?
\n\nsyntax = "proto3";\n\npackage com.pythonlib.example;\n\nservice UserService {\n rpc GetUser (UserRequest) returns (UserResponse);\n rpc ListUsers (UserListRequest) returns (stream UserResponse);\n rpc UpdateUser (stream UserUpdateRequest) returns (UserResponse);\n rpc Chat (stream ChatMessage) returns (stream ChatMessage);\n}\n\nmessage UserRequest {\n int32 id = 1;\n}\n\nmessage UserResponse {\n int32 id = 1;\n string name = 2;\n string email = 3;\n}\n\nmessage UserListRequest {\n int32 page = 1;\n int32 size = 2;\n}\n\nmessage UserUpdateRequest {\n int32 id = 1;\n string name = 2;\n}\n\nmessage ChatMessage {\n string user = 1;\n string text = 2;\n}\n\n\nAfter compilation with protoc, you'll get a ready-made Java class with builders — no manual mappers required.
When is gRPC in Java the Best Choice? 5 Scenarios
\n\n1. High-Load Microservices
\n\nIf you have 50+ microservices communicating thousands of times per second, gRPC reduces latency by 30-50% compared to REST. Protobuf takes up less space, and HTTP/2 allows keeping a single connection for all requests.
\n\nReal-world example: We migrated an internal recommendation service from REST to gRPC. Response time dropped from 12 ms to 4 ms, and traffic was reduced by 3 times.
\n\n2. Real-Time Data Streaming
\n\ngRPC natively supports server-side streaming, client-side streaming, and bidirectional streaming. This is ideal for:
\n- \n
- Logs and metrics (agent sends a stream of data) \n
- Chat systems and notifications \n
- Processing large files in chunks \n
Server implementation with server streaming in Java:
\n\nimport io.grpc.stub.StreamObserver;\n\npublic class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {\n\n @Override\n public void listUsers(UserListRequest request,\n StreamObserver<UserResponse> responseObserver) {\n for (int i = 0; i < 10; i++) {\n UserResponse user = UserResponse.newBuilder()\n .setId(i)\n .setName("User_" + i)\n .setEmail("user" + i + "@pythonlib.ru")\n .build();\n responseObserver.onNext(user);\n try {\n Thread.sleep(200); // simulate delay\n } catch (InterruptedException e) {\n responseObserver.onError(e);\n }\n }\