grpc-quic-rs
gRPC over HTTP/3 for tonic — enables standards-compliant gRPC transport over HTTP/3 (h3) and QUIC while preserving full gRPC semantics and API compatibility.
Motivation
Standard gRPC runs over HTTP/2 over TCP. While HTTP/2 solves head-of-line blocking at the application layer, TCP still suffers from HOL blocking at the transport layer. A single lost packet stalls all multiplexed streams.
QUIC (RFC 9000) eliminates TCP HOL blocking by giving each stream independent loss recovery. Combined with TLS 1.3 built into the handshake, QUIC offers:
- Lower connection establishment latency (0-RTT resumption)
- No transport-level HOL blocking across streams
- Connection migration (survives IP changes, e.g. mobile roaming)
- Built-in encryption — no separate TLS layer
grpc-quic-rs gives tonic services all of this with zero changes to your
protobuf definitions or service implementations.
Architecture
flowchart TB
subgraph Application
S[tonic Service]
P[protobuf codec]
end
subgraph grpc-quic-rs
C[grpc-quic-client<br/>QuicChannel]
V[grpc-quic-server<br/>QuicServer]
K[grpc-quic-core<br/>h3 transport + body]
T[grpc-quic-transport<br/>QUIC primitives]
M[grpc-quic-metrics<br/>Prometheus + tracing]
D[grpc-quic-discovery<br/>Resolver trait]
end
subgraph Network
H[HTTP/3 · h3 + h3-quinn]
Q[QUIC · quinn · UDP<br/>TLS 1.3 via rustls]
end
S --> C
S --> V
C --> K
V --> K
K --> T
T --> Q
C -.-> M
V -.-> M
C -.-> D
Key design principle
grpc-quic-rs does NOT modify gRPC semantics. It replaces HTTP/2/TCP with HTTP/3/QUIC (h3 + h3-quinn). All gRPC payload bytes are forwarded verbatim — never interpreted or re-encoded.
Crate structure
| Crate | Role |
|---|---|
grpc-quic |
Public façade — re-exports everything |
grpc-quic-transport |
Raw QUIC primitives (quinn + rustls). No tonic dependency. |
grpc-quic-core |
HTTP/3 + gRPC core — h3 connection builders, body adapters, error types |
grpc-quic-client |
QuicChannel — tonic-compatible tower::Service |
grpc-quic-server |
QuicServer — accepts QUIC connections, delegates to tonic Router |
grpc-quic-metrics |
Prometheus counters + tracing spans |
grpc-quic-discovery |
Resolver trait + StaticResolver |
Getting Started
Cargo.toml:
[] = { = "0.1", = ["full"] }
Server (development — self-signed cert)
use ;
let tls = server_self_signed?;
builder
.tls
.build
.serve
.await?;
Server (production — PEM files)
let tls = server_from_pem?;
Client (development — accepts any cert)
use ;
let channel = builder
.tls
.connect
.await?;
let mut client = new;
let response = client.say_hello.await?;
Client (production — webpki roots)
let channel = builder
.tls
.connect
.await?;
Streaming support
All four gRPC streaming modes are supported via HTTP/3 data frames + trailers:
| Mode | Transport |
|---|---|
| Unary | HTTP/3 request/response with trailers (grpc-status, grpc-message) |
| Client Streaming | HTTP/3 request stream, single response |
| Server Streaming | Single request, HTTP/3 response stream |
| Bidirectional | Full-duplex HTTP/3 stream |
Development
# Install just (task runner)
# Install mdbook for docs
License
Licensed under either of:
at your option.