This episode covers gRPC and modern protocols: the HTTP/2 requirement for gRPC, reverse proxying with the h2c transport, gRPC load balancing, gRPC-Web for browsers, and enabling HTTP/3 (QUIC) with UDP configuration.

Modern microservices often communicate with gRPC — an RPC framework using HTTP/2 and protobuf. gRPC promises high performance and two-way streaming, but it comes with one requirement: HTTP/2 is mandatory. Episode 26 covers how Caddy serves and proxies gRPC.
You'll also learn gRPC-Web for browser clients, gRPC-specific load balancing, and HTTP/3 (QUIC) — the next-generation protocol Caddy enables automatically.
After this episode, you'll be able to make Caddy an API gateway for gRPC services while supporting the most modern protocols available.
gRPC uses HTTP/2 features that don't exist in HTTP/1.1:
Without HTTP/2, gRPC doesn't run at all. Caddy handles the client side automatically (browsers or gRPC clients connecting over HTTPS), but the backend side needs to be set up.
gRPC backends typically speak HTTP/2 cleartext (h2c). The configuration:
grpc.example.com {
reverse_proxy localhost:50051 {
transport http {
versions h2c 2
}
}
}transport http { versions h2c 2 } forces the backend connection to use HTTP/2 without TLS. Caddy handles TLS with the client (HTTPS), then forwards to the backend over h2c.
Caddy detects the application/grpc content type and handles streams correctly. Streaming, unary, and bidirectional calls all work through the same configuration. No special matchers needed.
http transport with tls enabled.gRPC uses long-lived HTTP/2 connections with many streams. When using multiple backends:
grpc.example.com {
reverse_proxy {
to grpc-a:50051 grpc-b:50051 grpc-c:50051
lb_policy round_robin
transport http {
versions h2c 2
}
health_uri /healthz
health_interval 10s
}
}health_uri /healthz probes gRPC backends periodically. Failed backends are removed from the pool — long-lived HTTP/2 connections need proactive health checks.
Standard gRPC services expose a health-check protocol. Make sure the /healthz endpoint is configured in the application, or use grpc-health-probe. Healthy backends are detected automatically and re-registered after recovery.
Browsers can't use native gRPC (it needs full HTTP/2 control). The solution is gRPC-Web:
Caddy supports gRPC-Web by proxying those requests as usual. What you need to watch is CORS — because requests come from a different origin:
grpc.example.com {
@preflight {
method OPTIONS
}
handle @preflight {
header Access-Control-Allow-Origin *
header Access-Control-Allow-Methods "POST"
header Access-Control-Allow-Headers "content-type, x-grpc-web"
respond 204
}
header Access-Control-Allow-Origin *
reverse_proxy localhost:50051 {
transport http {
versions h2c 2
}
}
}header Access-Control-Allow-Headers "content-type, x-grpc-web" allows the gRPC-Web-specific headers on preflight. Without proper CORS, browsers block calls from the web app.
HTTP/3 runs over UDP with the QUIC protocol. Caddy enables it automatically:
{
servers {
protocols h1 h2 h3
}
}
example.com {
root * /var/www
file_server
}protocols h1 h2 h3 includes HTTP/3. The only external requirement: UDP port 443 open in the firewall. Without it, Caddy still runs on HTTP/2.
Caddy sends the Alt-Svc: h3=... header, which tells browsers that HTTP/3 is available. Browsers that support it automatically use QUIC on subsequent requests. This header is handled automatically — no configuration needed.
Episode 26 covered gRPC and modern protocols: the HTTP/2 requirement, gRPC reverse proxying with transport http { versions h2c 2 }, load balancing with health checks, gRPC-Web with CORS for browsers, and HTTP/3 (QUIC) with UDP port 443 and the Alt-Svc header.
Key takeaways:
versions h2c 2 in the transport enables HTTP/2 cleartext.x-grpc-web header.In the next episode, episode 27, we'll cover Docker integration — the official Caddy image, multi-stage builds, Docker Compose with volumes and networks, certificate persistence, service discovery between containers, and Caddy as a reverse proxy for many applications.