envoyproxy/envoy
QUIC and HTTP/3
QUIC is a UDP-based transport that combines TLS 1.3 with stream multiplexing, low-latency handshake, and connection migration. HTTP/3 is HTTP over QUIC. Envoy delegates the protocol implementation to Google's QUICHE library and wires it through Envoy's listener/dispatcher/codec abstractions in source/common/quic/.
What QUIC means for Envoy
- UDP, not TCP — listeners and connection pools are UDP variants.
- Crypto in the protocol — there is no "TLS layer" beneath QUIC; the stack itself terminates TLS 1.3.
- Streams — like HTTP/2 but at the transport layer, with no head-of-line blocking across streams.
- Connection migration — clients can move between IPs without resetting the connection.
- 0-RTT — once a session is cached, the next request can ride on the first packet.
Where the code lives
| Concern | Path |
|---|---|
| Server-side listener | active_quic_listener.cc, envoy_quic_dispatcher.cc |
| Server session/stream | envoy_quic_server_session.cc, envoy_quic_server_stream.cc |
| Client connection / pool | envoy_quic_client_connection.cc, envoy_quic_client_session.cc, source/common/http/http3/conn_pool.cc |
| HCM codec | server_codec_impl.cc, client_codec_impl.cc |
| Transport-socket bridges | quic_server_transport_socket_factory.cc, quic_client_transport_socket_factory.cc |
| Crypto bridges | envoy_quic_proof_source.cc, envoy_quic_proof_verifier.cc |
| GSO / IO | udp_gso_batch_writer.cc |
| QUIC extension factories | source/extensions/quic/ — proof source, connection ID generator, server preferred address, crypto stream. |
The QUICHE source is vendored under bazel/external/quiche.BUILD.
Server-side flow
sequenceDiagram
participant Listener as ActiveQuicListener
participant Disp as EnvoyQuicDispatcher
participant Sess as EnvoyQuicServerSession
participant FilterMgr as Network filter chain<br/>(starts with HCM)
participant HCM as ConnectionManagerImpl
participant Stream as EnvoyQuicServerStream
Listener->>Disp: incoming UDP datagram
Disp->>Sess: route to existing or new session
alt new session
Sess->>Sess: TLS 1.3 handshake
Sess->>FilterMgr: instantiate filter chain (incl. HCM)
end
Sess->>Stream: new HTTP/3 stream
Stream->>HCM: codec emits headers/body to HCM
HCM->>Stream: encodes responseThe QUIC listener uses a UDP ActiveListenerBase (under source/common/listener_manager/) and dispatches incoming datagrams to QUICHE's QuicDispatcher via the Envoy bridge in EnvoyQuicDispatcher.
Client-side flow
The client side is reached through Http::ConnectionPool::Instance for HTTP/3, configured via cluster transport socket. HttpConnPoolGrid (see connection pools) decides whether to try HTTP/3 first.
Crypto
QUIC requires its own TLS handshake in-protocol. Envoy bridges to BoringSSL via:
EnvoyQuicProofSource— server-side cert chain provider.EnvoyQuicProofVerifier— client-side cert verifier.
These are wired with the same Ssl::ContextConfig plumbing as the TLS transport socket, so SDS-driven cert rotation works for QUIC.
Stat scopes
QUIC emits its own stats under listener.<addr>.http3.* and cluster.<name>.http3.*. The stat names are pre-allocated in quic_stat_names.h for hot-path efficiency.
GSO
On Linux, the UDP send path uses Generic Segmentation Offload (GSO) — multiple QUIC packets in one sendmmsg. udp_gso_batch_writer.cc implements the writer. This is a major throughput win on busy edges.
Connection ID generators
QUIC connections survive client IP changes because they are keyed by a connection ID, not the 4-tuple. The way the server allocates IDs is pluggable so deployments can encode routing information into them (e.g. AWS NLB-friendly IDs, deterministic IDs for sharding). See envoy_deterministic_connection_id_generator.cc and the factory interface in envoy_quic_connection_id_generator_factory.h.
HTTP/3 codec
Server and client codecs (server_codec_impl.cc, client_codec_impl.cc) implement Http::ServerConnection / Http::ClientConnection so the HCM and router can talk to QUIC streams without knowing they aren't HTTP/2.
CONNECT-UDP and HTTP datagrams
Envoy supports CONNECT-UDP tunnelling and HTTP datagrams (http_datagram_handler.cc) for proxying QUIC over QUIC and for WebTransport-style datagrams.
Mobile relevance
Envoy Mobile ships the QUIC client stack for iOS / Android. The connection migration semantics matter especially on mobile where networks change frequently.
Configuration
Enable HTTP/3 on a listener:
listeners:
- name: h3_listener
address:
socket_address: { protocol: UDP, address: 0.0.0.0, port_value: 443 }
udp_listener_config:
quic_options: {}
downstream_socket_config:
prefer_gro: true
filter_chains:
- transport_socket:
name: envoy.transport_sockets.quic
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport
downstream_tls_context: { common_tls_context: { ... } }
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: HTTP3
http3_protocol_options: {}
...See also
- HTTP connection manager
- Connection pools — alt-svc grid.
- Transport sockets — TLS sibling.
- Envoy Mobile — QUIC on the client.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.