CDN gRPC-Web Proxy: Binary Protocol Translation at Edge
gRPC is efficient inside your data center, but it breaks at the browser edge. Browsers cannot speak native gRPC. A CDN gRPC-Web proxy solves this by translating between the browser's limited HTTP stack and your origin's binary HTTP/2 gRPC service — without sacrificing streaming, flow control, or protobuf efficiency.
Why gRPC Needs Translation at the Edge
Native gRPC relies on HTTP/2 features that the Fetch API and XMLHttpRequest do not expose: trailing headers (trailers), full control over binary framing, and bidirectional streaming. The gRPC-Web protocol is a deliberate adaptation that encodes the same protobuf payloads over HTTP/1.1 or HTTP/2 in a way browsers can handle.
Without an edge proxy, you have two bad options: expose a REST gateway that re-serializes to JSON (losing 30-40% payload efficiency) or run a self-managed Envoy fleet just for translation. A CDN edge proxy eliminates both by handling translation within PoPs, close to users. For background on how PoPs handle protocol termination, see our CDN architecture overview and edge computing guide.
gRPC vs gRPC-Web vs REST at the Edge
| Feature | Native gRPC | gRPC-Web (via CDN Proxy) | REST / JSON |
|---|---|---|---|
| Transport | HTTP/2 only, trailers required | HTTP/1.1 or HTTP/2, no trailers needed in browser | HTTP/1.1 or HTTP/2 |
| Payload | Protobuf binary, 5-byte frame header | Same protobuf binary + gRPC-Web framing | JSON text, 2-4x larger |
| Streaming | Full bidi streaming | Server streaming + unary (bidi via websockets) | Server-sent events / polling |
| Browser Support | None | All modern browsers | All browsers |
| CDN Cacheable | No (trailers break cache) | Unary: Yes with custom key | Yes, natively |
| Edge Overhead | N/A | 1-5ms translation | JSON serialization 5-15ms |
How Edge Translation Works
The proxy performs three critical translations in the data path:
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
- Protocol downgrade/upgrade: Accepts
content-type: application/grpc-web+protoover HTTP/1.1 from the browser, then re-emitsapplication/grpcover HTTP/2 to origin. - Framing conversion: Strips the gRPC-Web 1-byte flag + 4-byte length prefix wrapper and re-adds standard gRPC length-prefixed messages, handling
grpc-statusandgrpc-messagetrailers. - Connection coalescing: Multiplexes thousands of browser HTTP/1.1 connections onto a small pool of warm HTTP/2 connections to origin, reducing TLS and TCP handshake cost.
Binary Framing: What the Proxy Actually Rewrites
Both protocols use the same 5-byte frame: 1 byte compressed flag + 4 bytes big-endian message length + protobuf bytes. The difference is trailer handling.
gRPC-Web text mode base64-encodes frames for proxies that buffer binary. gRPC-Web proto mode sends raw binary and is preferred at the edge for lower CPU. The edge proxy must:
- Detect
content-type: application/grpc-web-textvsgrpc-web+protoand decode if needed. - Buffer until a full frame length is available before forwarding — never forward partial protobuf messages.
- Convert the terminal data frame containing
grpc-status:0into a proper HTTP/2 trailer. Browsers read this as a header because trailers are not exposed.
Configuring the Edge Proxy
Most teams use Envoy's grpc_web filter at the edge, or a CDN-native toggle. Below are production-ready patterns.
Option 1: Envoy at CDN Edge (Recommended for control)
Option 2: CDN-Native (Cloudflare / Fastly / CloudFront)
Enable gRPC-Web in the dashboard and set origin protocol to h2c or h2. Ensure your origin speaks HTTP/2 without TLS termination mismatch. For CloudFront, put an ALB or NLB with HTTP/2 target group in front of your gRPC servers.
Client Example (grpc-web JS)
Performance Tuning at the Edge
Translation is cheap, but misconfiguration is not. Apply these settings to keep p95 under 30ms:
- Keepalive: Set origin HTTP/2 keepalive to 30s with 10s timeout. Edge should hold 10-20 persistent connections per PoP per origin, not per request.
- Timeouts: Use per-method timeouts. Unary search: 2-5s. Streaming: 30-60s with idle timeout 15s. Never use Envoy's default 15s for streaming.
- Buffer limits: Cap
initial_stream_window_sizeat 1MB andconnection_window_sizeat 4MB to prevent one large message from starving multiplexed streams. - Compression: Prefer
grpc-encoding: gziponly for messages >1KB. Small protobufs compress poorly and waste CPU at edge. Disable compression for <512B. - CORS: Handle CORS at the edge, not origin. Add
Access-Control-Allow-Headers: x-grpc-web, grpc-timeout, content-typeand cache preflight for 86400s.
Measure with CDN performance metrics and correlate with Core Web Vitals — gRPC-Web streaming improves INP by avoiding polling waterfalls, but unoptimized framing can regress LCP if the proxy buffers too aggressively.
access_log with %GRPC_STATUS% and %RESPONSE_CODE_DETAILS% at the edge. A 200 HTTP with grpc-status:14 (unavailable) is invisible to standard CDN dashboards that only track HTTP status.Security and Reliability
Binary protocols obscure payloads from traditional WAFs. Configure edge security explicitly:
- mTLS to origin: Terminate browser TLS at edge with modern ciphers, then use mTLS or private network +
X-Origin-Verifyto origin. Never forward browser certs as gRPC metadata. - Payload validation: Enforce
max_request_bytes: 4MBat edge and validate protobuf field sizes via Envoy'smax_request_headers_kb. See CDN security guide for header overflow protections. - DNS and failover: Use health checks that send a real gRPC health probe (
grpc.health.v1.Health/Check), not just TCP. Combine with CDN DNS resolution to fail over PoP-to-origin quickly. - Retry safely: Only retry idempotent unary methods. Never auto-retry streaming or methods with side effects. Use
x-retry-attemptheader to make retries observable.
When Not to Use gRPC-Web at the Edge
Avoid gRPC-Web if you need true bidirectional streaming from the browser (use WebSockets or Connect protocol instead), or if your payloads are already JSON and <500B (REST overhead is negligible). For edge caching of large unary responses, consider Connect's application/proto with GET support, which maps better to CDN cache keys.
Edge Checklist
- ✓ Origin speaks HTTP/2 with trailers, health-checked via gRPC health protocol
- ✓ Edge filter order:
grpc_webbeforecorsbeforerouter - ✓ Persistent h2 pool, per-method timeouts, no retry on streams
- ✓ CORS and compression handled at edge, not origin
- ✓ Logging includes
grpc-status, not just HTTP 200
Frequently Asked Questions
References & Standards: RFC 7234 · HTTP/2 specification