Picture this: you've got fifteen microservices talking to each other. Each one exposes its own REST API, each one has its own JSON with its own naming conventions, and every time someone changes a field in the payments service, three other teams find out when everything blows up in production. You document with Swagger, but the Swagger goes stale. You write HTTP clients by hand, or generate something with OpenAPI that works "more or less." And when you need service A to ask service B something ten thousand times a second, the overhead of JSON + HTTP/1.1 starts hurting your infrastructure bill.
That specific pain — inter-service communication with contracts that break silently and performance that doesn't scale — is exactly what gRPC comes to solve. It's not a trend. Google designed it to solve that exact problem inside its own infrastructure, and then released it as an open source project. Today it shows up in three independent awesome lists, which, in the curation system I've been building out through this series, is a strong signal: it's not noise, it's real community consensus.
If you've been working with REST your whole career (like I spent a good chunk of time managing infrastructure before diving fully into development), the first time you see gRPC in action it changes how you think. It's not "another HTTP framework." It's a different paradigm for how your services talk to each other.
What it does
gRPC is a Remote Procedure Call framework that runs over HTTP/2 and uses Protocol Buffers (protobuf) as its default serialization mechanism. Instead of exposing REST endpoints and letting every client build its own request, you define a contract — a .proto file — and from that you generate client and server code in whatever language you need. Go, Java, Python, C++, Node, whatever. Same contract, multiple languages, and the field names and types are enforced by the generated code instead of living only in a doc someone forgot to update.
Here's what a basic contract looks like:
// pedidos.proto
// We define the service and the messages it will exchange
syntax = "proto3";
package pedidos;
// The service exposes an RPC method, as if it were a remote function
service PedidosService {
rpc ObtenerPedido (PedidoRequest) returns (PedidoResponse);
}
// Messages are like DTOs, but typed and versionable
message PedidoRequest {
string id_pedido = 1;
}
message PedidoResponse {
string id_pedido = 1;
double monto_total = 2;
string estado = 3;
}
From that file, the protobuf compiler (protoc) automatically generates serialization classes and client/server stubs. If you come from the Java world (like me, where I started my career as a developer), this is going to sound similar to what SOAP did with WSDL, but without the dead weight of XML and with noticeably better performance.
On the server side in Java, the implementation looks like this:
// We implement the service automatically generated from the .proto
public class PedidosServiceImpl extends PedidosServiceGrpc.PedidosServiceImplBase {
@Override
public void obtenerPedido(PedidoRequest request,
StreamObserver<PedidoResponse> responseObserver) {
// The real logic would go here, querying the database
PedidoResponse response = PedidoResponse.newBuilder()
.setIdPedido(request.getIdPedido())
.setMontoTotal(1500.50)
.setEstado("CONFIRMADO")
.build();
// onNext sends the response, onCompleted closes the stream
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
Notice there's no JSON anywhere. The payload is serialized in binary, which means smaller payloads and faster parsing. And since it runs over HTTP/2, you get multiplexing of requests over a single TCP connection, native bidirectional streaming, and header compression — the structural reasons gRPC tends to outperform REST under high load.
Why it's on the list
The consensus signal — three independent awesome lists mentioning it — isn't a coincidence. gRPC solves a problem that comes up fast with microservices: the lack of strong contracts between services. With REST + JSON, the contract is a convention that lives in devs' heads and in documentation that goes stale. With gRPC, the contract is generated code. If you break a field, you find out at compile time, not in production on a Friday at six in the evening.
The other big reason is performance. Code generation eliminates manual serialization boilerplate — you don't write JSON parsers by hand, you don't maintain duplicate DTOs in every language. And binary protobuf over HTTP/2 is the combination that gives gRPC an edge over traditional REST under high load, which is exactly the scenario where microservices start to struggle.
It's the kind of tool that doesn't shine in a five-minute demo, but becomes indispensable when you have dozens of services talking to each other at real volume. That's where the JVM ecosystem (if you work with Spring Boot, there's solid support via grpc-spring-boot-starter) benefits from this approach versus maintaining fifteen hand-built REST clients.
When NOT to use it
Now, let's be honest: gRPC isn't free, and this is the part people skip. Protobuf and the async/streaming model are a different mental model from request/response REST — if your team hasn't touched this before, budget real ramp-up time for it, not an afternoon. Debugging is also more tedious: you can't just hit a gRPC endpoint with curl like you did with REST, you need extra tools like grpcurl or BloomRPC to inspect traffic.
It also doesn't make sense if you're going to consume your API directly from a browser (you need gRPC-Web with an intermediate proxy, another layer of complexity) or if you're building a public API that third parties will consume without any control over their stack — there, REST + OpenAPI is still more friendly. If your system is two or three services with low traffic, you're probably adding complexity you don't need. For those cases, stick with REST or look at lighter alternatives like tRPC if you're in a TypeScript monorepo.
Wrap-up
gRPC is the kind of tool you shouldn't adopt because it's trendy, but because you have the specific problem it solves: inter-service communication at scale, with strong contracts and performance that matters. That's why it made it through this series' filters — it's not hype, it's real technical consensus, and it comes with a real learning cost you should plan for, not skip.
If you liked this analysis, this is just entry #13 of Awesome Curated: The Tools, where I go through tools that passed our curation system's filter. If you're into infrastructure and runtimes, you might also like the post on Node.js and its event loop, or if you're into networking, Sniffnet for monitoring network traffic without losing your mind. The full series is at /blog/series/awesome-curated-tools.
This article was originally published on juanchi.dev
Top comments (1)
tr.ee/dev-to