Background
Sections
IntroductionRequirements & Problem AnalysisConstraints & AssumptionsEstimation TechniquesFunctional vs Non-Functional RequirementsMoSCoW PrioritizationSystem Design FundamentalsArchitecture DiagramClass DiagramComponent DiagramData Flow Diagram (DFD)ER Diagram (Entity-Relationship Diagram)High Level Design (HLD)Low Level Design (LLD)Sequence DiagramState DiagramUse Case DiagramData StorageDocument StoresFile StorageGraph DatabasesIn-Memory DatabasesKey-Value StoresNewSQLNoSQL DatabasesObject StorageSQL Databases (RDBMS)Time-Series DatabasesWide-Column StoresDatabase ConceptsACID PropertiesCAP TheoremConsistency ModelsIndexingNormalization & DenormalizationReplicationSharding & PartitioningTransactions & Isolation LevelsScalabilityAuto-Scaling & ElasticityConsensus & Leader ElectionLoad BalancingReplication & Read ReplicasSharding & PartitioningVertical vs Horizontal ScalingAvailability & ReliabilityBackup & Data DurabilityCircuit BreakerData ConsistencyDisaster RecoveryFault Tolerance & FailoverGraceful DegradationHigh AvailabilityNetworkingCDNDNSFirewalls & VPNHTTP & HTTPSLoad Balancer & Reverse ProxyTCP/IP & UDPWebSocketsCachingCache InvalidationCache Read/Write PatternsCaching LayersEviction PoliciesRedis vs MemcachedMessaging & CommunicationDead-Letter QueueIdempotencyKafka vs RabbitMQ vs SQSMessage QueuesPub/SubCompute & ServicesAPI GatewayContainers & OrchestrationMonolith vs MicroservicesServerlessService DiscoveryService MeshWeb Server & App ServerAPI DesignAPI Versioning & IdempotencyAuthentication & AuthorizationGraphQLgRPCPaginationRate Limiting & ThrottlingRESTSecurityAuthentication & AuthorizationData PrivacyEncryptionInput Validation & InjectionOAuth2 & JWTSecrets ManagementXSS & CSRFStorage & File SystemsBackup & RetentionBlock vs File vs Object StorageData Lakes & WarehousesDistributed File SystemsEphemeral StorageObservability & MonitoringDistributed TracingHealth ChecksLoggingMetricsSLI, SLO, SLADesign PatternsBulkhead PatternCircuit Breaker PatternCreational PatternsRate Limiter PatternRetry PatternStructural & Behavioral Patterns

gRPC

7 min read

In a Nutshell

gRPC is a high-performance framework for service-to-service communication built by Google. Instead of sending JSON over HTTP like REST, it uses Protocol Buffers (a compact binary format) over HTTP/2, and you define your API as a set of typed service methods in a .proto file — actual function calls, not resource URLs. From that contract, gRPC generates strongly-typed client and server code in many languages. The result is fast, efficient, strongly-typed remote procedure calls with built-in streaming. gRPC shines for internal microservice communication where performance and strong contracts matter more than the human-readability and browser-friendliness that make REST dominant at the public edge.

2D minimalistic diagram showing a .proto contract file in the center defining service methods, with arrows generating strongly-typed client code (left) and server code (right); the client calls a method like a local function, and the request travels as compact binary Protocol Buffers over HTTP/2 to the server, illustrating typed RPC

How It Actually Works

Contract-First with Protocol Buffers

You define the service and messages in a .proto file — the single source of truth:

syntax = "proto3";

service OrderService {
  rpc GetOrder(GetOrderRequest) returns (Order);
  rpc ListOrders(ListOrdersRequest) returns (stream Order);   // server streaming
}
message GetOrderRequest { string order_id = 1; }
message Order {
  string id = 1;
  double total = 2;
  repeated Item items = 3;
}

From this, gRPC generates client and server stubs in Go, Java, Python, etc. The client calls GetOrder() as if it were a local function; gRPC handles serialization, transport, and deserialization. The typed contract means breaking changes are caught at compile time.

Why It's Fast

Feature Benefit
Protocol Buffers (binary) Much smaller + faster to serialize than JSON text
HTTP/2 Multiplexing, header compression, persistent connections
Streaming Native bidirectional streaming over one connection
Code generation No hand-written serialization; strongly typed
REST/JSON:   {"id":"42","total":19.5}   → ~verbose text, parse overhead
gRPC/Protobuf: 0x0A 02 34 32 11 ...       → compact binary, tiny + fast

Four Call Types (Streaming Is Native)

Type Shape Use
Unary 1 request → 1 response Normal RPC
Server streaming 1 request → stream of responses Live feed, large result sets
Client streaming Stream of requests → 1 response Uploads, telemetry batches
Bidirectional streaming Stream ↔ stream Chat, real-time sync

Streaming is first-class in gRPC (via HTTP/2), unlike REST where it's awkward.

gRPC vs REST vs GraphQL

Aspect REST GraphQL gRPC
Format JSON (text) JSON (text) Protobuf (binary)
Transport HTTP/1.1+ HTTP HTTP/2
Contract Loose (OpenAPI optional) Schema Strict .proto
Performance Good Good Excellent
Browser support Native Native Limited (needs gRPC-Web proxy)
Streaming Awkward Subscriptions Native, all directions
Human-readable Yes Yes No (binary)
Best for Public/web APIs Flexible client data Internal microservices

The Browser Problem

gRPC's main limitation: browsers can't speak gRPC directly (no raw HTTP/2 frame access from JS). You need a gRPC-Web proxy to translate. This is why gRPC dominates internal east-west communication but rarely faces the public web directly — where REST/GraphQL remain the norm.

When to Choose gRPC

Great fit:
  ✅ Internal microservice-to-microservice calls (performance matters)
  ✅ Low-latency, high-throughput systems
  ✅ Polyglot backends (generate clients in many languages)
  ✅ Streaming workloads (real-time, large datasets)
  ✅ Strict, versioned contracts across teams

Prefer REST/GraphQL when:
  ✅ Public-facing / browser-facing APIs
  ✅ Human-readability and easy debugging matter
  ✅ Broad third-party ecosystem / simple integration

2D minimalistic diagram comparing the four gRPC call types as four small panels: unary (one arrow each way), server streaming (one request, multiple response arrows), client streaming (multiple request arrows, one response), and bidirectional streaming (multiple arrows flowing both directions simultaneously), all over a single HTTP/2 connection

Seeing It in Action

Scenario: Choosing gRPC for internal microservices, REST at the edge.

Architecture: a public API with many internal microservices behind it.

Public edge (browser + mobile + third parties):
  → REST / GraphQL via an API gateway.
    Human-readable, browser-native, cache-friendly, easy to integrate.

Internal service-to-service (east-west):
  → gRPC.
    order-service → inventory-service.GetStock(product_id)
    order-service → pricing-service.CalculatePrice(cart)
    Each is a typed function call over HTTP/2 with binary Protobuf.

Why gRPC internally:
  ✅ Performance: binary Protobuf + HTTP/2 multiplexing → lower latency
     and CPU than JSON, which compounds across millions of internal calls.
  ✅ Strong contracts: the .proto is the shared source of truth. If
     inventory-service changes a field, order-service fails to COMPILE
     rather than breaking mysteriously at runtime.
  ✅ Polyglot: inventory (Go), pricing (Java), order (Python) all generate
     native clients from the same .proto — no hand-written HTTP clients.
  ✅ Streaming: a real-time stock feed uses server streaming natively.

Why NOT gRPC at the edge:
  ✗ Browsers can't speak gRPC without a gRPC-Web proxy.
  ✗ Third-party developers expect REST/JSON; binary is hard to debug.

The pattern that emerges: use the right protocol for each traffic type. gRPC's speed, strong typing, and streaming make it ideal for the high-volume internal calls between services, where both ends are yours and performance compounds. REST/GraphQL's readability and universal client support make them ideal at the public edge, where humans, browsers, and third parties are involved. Many mature systems run exactly this split — REST/GraphQL north-south, gRPC east-west — because it optimizes each boundary for what actually matters there.

Interview Questions

  1. Q: What makes gRPC faster than REST/JSON? Hint: It serializes with Protocol Buffers (compact binary, faster to encode/decode than verbose JSON text) and runs over HTTP/2 (multiplexing many calls on one connection, header compression, persistent connections). It also generates serialization code rather than parsing text. Across high-volume internal calls, the lower payload size and CPU cost compound significantly.

  2. Q: What does "contract-first with Protocol Buffers" mean and why is it valuable? Hint: You define services and messages in a .proto file, the single source of truth, and generate strongly-typed client/server code in many languages. Value: the contract is enforced at compile time — a breaking change makes callers fail to compile rather than break at runtime — and polyglot teams share one authoritative definition, eliminating hand-written, drift-prone HTTP clients.

  3. Q: Describe gRPC's four call types. Hint: Unary (1 request → 1 response, normal RPC), server streaming (1 request → stream of responses, e.g., live feed/large results), client streaming (stream of requests → 1 response, e.g., uploads/telemetry), and bidirectional streaming (both directions simultaneously, e.g., chat/real-time sync). Streaming is native via HTTP/2, unlike REST where it's awkward.

  4. Q: Why is gRPC used mostly for internal services rather than public/browser APIs? Hint: Browsers can't speak gRPC directly (no raw HTTP/2 frame access from JS) — you need a gRPC-Web proxy. Its binary format isn't human-readable, making third-party integration and debugging harder. So gRPC dominates internal east-west service-to-service traffic (where both ends are yours and performance matters), while REST/GraphQL remain the norm at the public, browser-facing edge.

  5. Q: How do you decide between REST, GraphQL, and gRPC? Hint: gRPC for internal microservice communication needing high performance, strong contracts, streaming, and polyglot clients. GraphQL for flexible, client-driven data needs with many clients and complex nested data. REST for simple, resource-oriented, cache-friendly, browser/third-party-facing public APIs. Many systems combine them: REST/GraphQL north-south at the edge, gRPC east-west internally.

References

Dive Deeper