- rtshkmr's digital garden/
- References/
- Architecture Design Basics/
- Pattern Taxonomy/
- Communication & API Design/
- Web-gRPC Proxy/
Web-gRPC Proxy
Table of Contents
π P1 — decoupling internal gRPC from external REST via a stateless proxy
Problem #
Modern browsers can’t make gRPC calls directly (gRPC/2 requires HTTP/2 with special framing).
External API consumers often expect REST.
We need a translation layer.
Architecture #
Common implementations: gRPC-Gateway, Envoy proxy, custom reverse proxy.
Browser/External Client
β
[REST Endpoint]
β
gRPC Proxy (translates REST β gRPC)
β
Internal gRPC ServicesKey Tradeoffs #
Latency & Protocol Overhead #
| Aspect | gRPC (Internal) | REST + Proxy | REST Direct |
|---|---|---|---|
| Serialisation | Binary protobuf (~fast) | Binary β JSON β Binary | JSON only (~slower) |
| Frame overhead | Minimal (HTTP/2 framing) | HTTP/1.1 or HTTP/2 | HTTP/1.1 (~higher) |
| Typical impact | Baseline | +5-10ms per hop | +20-30% larger payloads |
Instinct:
- If your external API traffic is <5% of total, the proxy overhead is noise.
- If >30%, reconsider the boundary (maybe expose gRPC directly, or move work internal).
Complexity & Operational Burden #
- Direct gRPC to external: Clients need gRPC libs + protobuf knowledge. Harder on-boarding.
- REST proxy layer: Clients use standard HTTP; you own translation complexity.
- Tradeoff: Add a service, gain simplicity for consumers.
- Failure mode: Proxy becomes a bottleneck or single point of failure.
Instinct:
- Run the proxy stateless & replicated. Make it thin β let it delegate routing/auth, not business logic.
Bi-directional Streaming & Real-time #
- gRPC: HTTP/2 multiplexing + server push = natural streaming.
- REST + Proxy: HTTP/1.1 long-polling, or WebSocket sidecar (adds another layer).
Instinct:
- If you need bidirectional streaming to external clients, gRPC-Web (gRPC over HTTP/1.1) is worth the proxy cost.
- REST long-polling gets ugly at scale.
API Surface and Consistency #
Proxy approach: Design for gRPC internally (performance, streaming), expose REST facade (compatibility).
- Cost: One more layer to maintain & debug.
- Benefit: Decouples internal & external APIs.
No proxy: Standardise on REST everywhere.
- Cost: Lose gRPC performance internally, or force clients to use gRPC (friction).
Instinct: At Stripe’s scale, the proxy cost is justified by API surface flexibility.
Security, Debugging #
- gRPC Proxy: Easier to inspect & rate-limit at one point. But binary protobuf is harder to debug (need tools like
grpcurl). - REST: Human-readable JSON, easier curl/Postman debugging. But larger attack surface if you expose many endpoints.
Tradeoff: Proxy simplifies enforcement (auth, rate-limiting in one place), but complicates visibility (need gRPC-aware monitoring).
Framing: Use-cases #
| Scenario | Recommendation | Why |
|---|---|---|
| Internal-only backend | gRPC directly | No translation needed; pure speed & efficiency |
| Public API, mostly reads | REST | Clients don’t need streaming; simplicity wins |
| Mixed (internal gRPC + external REST) | gRPC-Gateway proxy | Centralise translation, keep internal fast |
| Real-time external updates | gRPC-Web proxy | Streaming to browser/mobile clients |
| High-throughput batch APIs | gRPC directly | Protocol overhead dominates |
Instinct #
Here’s how we might articulate our instinct on this:
I’d design the internal service mesh on gRPCβit gives us HTTP/2 efficiency and streaming primitives. For external APIs, I’d run a thin, stateless gRPC-Gateway proxy that translates REST to our internal proto. This decouples the API contract (what partners see) from the implementation (what’s fast internally). The proxy is a deliberate complexity boundary: it costs us ~5-10ms per external request, but it buys us: (1) API evolution freedom, (2) operational simplicity β one place for auth, rate-limiting, observability, (3) protocol flexibility β we can add gRPC-Web later if we need browser streaming.
DDIA 2e Reference #
- Chapter 4 (Encoding and Evolution): Serialisation formats, schema evolution, compatibility
- Chapter 8: Network faults, partial failures informing proxy resilience