The three dominant options are REST (HTTP/JSON), gRPC (HTTP/2 + Protobuf), and message queues (Kafka/RabbitMQ). REST and gRPC are synchronous; queues are asynchronous.
The three dominant options are REST (HTTP/JSON), gRPC (HTTP/2 + Protobuf), and message queues (Kafka/RabbitMQ). REST and gRPC are synchronous; queues are asynchronous.
| Aspect | REST | gRPC | Message Queue |
|---|
| Style | Sync | Sync | Async |
| Payload | JSON (text) | Protobuf (binary) | Any (often binary) |
| Performance | Good | High | High throughput |
| Contract | OpenAPI (loose) | .proto (strict) | Schema/event |
| Streaming | Limited | Native (bidi) | Pub/sub |
| Best for | Public APIs, browsers | Internal hot paths | Decoupling, events |
service OrderService {
// strongly-typed RPC, generated client + server stubs
rpc GetOrder (OrderId) returns (Order);
}
message OrderId { string id = 1; }
message Order { string id = 1; double total = 2; }
Order Service ─publish→ [ "OrderPlaced" topic ] ─▶ Inventory
└────▶ Notifications
(producer doesn't know or wait for consumers)
Using sync gRPC/REST everywhere recreates tight coupling; using async for a user's immediate read adds needless latency.
The transport choice sets the coupling and performance ceiling for each interaction, so picking per use case — not globally — is what keeps the system both fast and resilient.
Mature systems deliberately blend all three: gRPC on internal hot paths, REST at the edge, and queues for workflows.