Excellent question. When we say AWS ALB “downgrades HTTP/2 → HTTP/1.1”, it means that although the client connects to ALB over HTTP/2, ALB then connects to your backend (e.g., EKS service or pod) using HTTP/1.1.
This causes loss of several core gRPC features, because gRPC requires HTTP/2 end-to-end to function properly.
📉 What’s Lost During the Downgrade (HTTP/2 → HTTP/1.1)
gRPC Feature | Lost or Broken? | Why It Matters |
---|---|---|
Streaming (client/server/bidi) | ❌ Lost | HTTP/1.1 can’t multiplex or maintain bidirectional streams |
HTTP/2 Trailers | ❌ Lost | gRPC uses trailers for grpc-status , grpc-message → clients can’t detect errors correctly |
Multiplexing | ❌ Lost | HTTP/2 can handle multiple streams over one connection, HTTP/1.1 cannot |
Header Compression (HPACK) | ❌ Lost | Increases payload size and latency |
Flow Control per Stream | ❌ Lost | HTTP/1.1 has global flow control → less efficient |
Binary Framing | ⚠️ May break | gRPC uses strict framing over HTTP/2 → framing can get corrupted |
gRPC Metadata Headers | ⚠️ Incomplete | Custom headers like grpc-timeout may be stripped or altered |
✅ What Gets Passed (But Not Fully gRPC-Compatible)
Element | Passed by ALB? | Note |
---|---|---|
HTTP POST | ✅ Yes | gRPC uses POST method |
Content-Type | ✅ Yes | application/grpc usually retained |
Basic Protobuf Payload | ⚠️ Partially | Still sent, but streaming/chunking could corrupt it |
TLS Termination | ✅ Yes | ALB can terminate TLS and forward plaintext internally |
Status Code (e.g., 200, 500) | ✅ Basic | But not the gRPC-specific status like grpc-status |
🧠 What Happens in Practice?
A native gRPC client (e.g., Go, Python, Node) expects:
- Streaming support
grpc-status
andgrpc-message
in HTTP/2 trailers- Correct gRPC error handling
But with ALB in the path:
- Streaming breaks — long-lived calls are prematurely closed
- Status trailers are lost — client receives only
200 OK
even on failure - Interceptors and retry logic in gRPC client fail silently
🔎 Example of Broken gRPC Call via ALB
Expected gRPC Response (over HTTP/2):
:status: 200
content-type: application/grpc
grpc-status: 5
grpc-message: Not Found
ALB Response (after downgrade):
HTTP/1.1 200 OK
content-type: application/grpc
(no grpc-status trailer!)
Result: gRPC client sees it as success (
OK
), even though the call failed on the server.
✅ Summary Table
Feature | HTTP/2 Required | Passed via ALB (HTTP/1.1) | Outcome |
---|---|---|---|
Unary gRPC Calls | ❌ Optional | ✅ Yes | May work |
gRPC Streaming (all types) | ✅ Yes | ❌ No | Broken |
gRPC Trailers (grpc-status ) | ✅ Yes | ❌ No | Broken |
Metadata headers | ⚠️ Often required | ⚠️ Incomplete | Unpredictable |
Observability (otel/metrics) | ✅ Yes | ❌ Incomplete | Partial / broken |
🔧 How to Prevent This
Use NLB + Envoy Gateway or a gRPC-aware ingress like:
- Envoy Gateway with HTTP/2
- Istio IngressGateway
- Gateway API with
GRPCRoute
I’m a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I am working at Cotocus. I blog tech insights at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at I reviewed , and SEO strategies at Wizbrand.
Do you want to learn Quantum Computing?
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at PINTEREST
Rajesh Kumar at QUORA
Rajesh Kumar at WIZBRAND