Network communication between services requires manual serialization, addressing, protocol handling, and error management — this is complex, error-prone, and obscures business logic.
RPC makes a remote procedure call look indistinguishable from a local call. The client calls a local stub that marshals the function name and arguments into a network message, sends it to the server, which unmarshals and executes the function, and returns the result — all transparent to the application code.
- Client calls a local stub function as if it were a local procedure.
- The client stub marshals the procedure ID and arguments into a binary or structured message.
- The client OS sends the message over the network to the server.
- The server OS passes the message to the server stub.
- The server stub unmarshals the message, locates and calls the actual procedure.
- The procedure executes and returns a result to the server stub.
- The response follows the reverse path back to the client.
Popular RPC frameworks include Protocol Buffers (gRPC), Apache Thrift, and Apache Avro.
- Hides network complexity behind a familiar local-call abstraction
- Request-response protocol — synchronous by default
- Automatically marshals/unmarshals parameters and return values
- Tight client-server coupling (interface contract is shared)
- Better suited for internal service-to-service communication than public APIs
- Contrasts with: REST — RPC exposes behaviors (functions); REST exposes resources (nouns)
- Related: Microservices Architecture — RPC is a common inter-service communication pattern
- Related: Service Discovery — RPC clients need to locate server instances dynamically
- Related: Message Queues — RPC is synchronous; message queues enable async communication
- Network failures are invisible: The local-call abstraction hides network partitions, timeouts, and partial failures. RPC calls can fail silently or hang.
- Versioning hell: Evolving the interface contract requires coordinated deployment of both client and server. Use schema evolution features (e.g., Protobuf field tags) to mitigate.
- Performance overhead: Marshaling, network round-trips, and connection management add latency compared to in-process calls. Batch calls or use streaming for high-throughput scenarios.