HTTP/3 Reference
| HTTP/3 support is experimental. Configuration properties and behavior may change in future releases. |
1. Overview
HTTP/3 is the latest version of the HTTP protocol. It replaces TCP with QUIC, a transport protocol built on UDP that provides built-in encryption, reduced connection setup latency, and elimination of head-of-line blocking.
From an application perspective, HTTP/3 is transparent: request and response handling is identical to HTTP/1.1 and HTTP/2. The same handlers, filters, and endpoints work across all three protocols. The only differences are at the transport level — QUIC uses UDP instead of TCP, and TLS 1.3 is mandatory.
Quarkus serves HTTP/1.1, HTTP/2, and HTTP/3 on the same port.
Clients discover HTTP/3 availability through the Alt-Svc response header on HTTP/1.1 and HTTP/2 responses, then upgrade to QUIC/UDP for subsequent requests.
2. Getting started
Add the quarkus-http3 extension to your project:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-http3</artifactId>
</dependency>
implementation("io.quarkus:quarkus-http3")
HTTP/3 requires TLS. In dev and test mode, a TLS certificate is auto-generated if none is configured (see Auto-TLS in dev and test mode). In production, you must configure TLS explicitly — see the TLS registry reference for details.
With TLS in place, HTTP/3 is enabled automatically. No additional configuration is needed.
3. Configuration
| Configuration property | Type | Default | Description |
|---|---|---|---|
|
boolean |
|
Whether HTTP/3 (QUIC) support is enabled. When enabled and the native QUIC library is on the classpath, HTTP/3 is added to the set of supported HTTP versions on the HTTPS server. |
|
boolean |
|
Whether to add the |
|
Duration |
|
The |
4. Auto-TLS in dev and test mode
When the HTTP/3 extension is on the classpath and no TLS configuration is detected, Quarkus auto-generates a certificate in dev and test mode:
-
If the Quarkus Dev CA exists at
~/.quarkus/quarkus-dev-root-ca.pem, the certificate is signed by it. Browsers and clients that trust the Dev CA will accept the certificate without warnings. -
Otherwise, a self-signed certificate is generated. Browsers will show a certificate warning, which is acceptable for development.
Run quarkus tls generate-quarkus-ca --install to create the Dev CA and install it in your system trust store for the best developer experience.
|
When auto-TLS is active, plain HTTP requests are redirected to HTTPS by default. To allow plain HTTP alongside HTTPS, set:
quarkus.http.insecure-requests=enabled
In production mode, no auto-generation occurs. If TLS is not configured, the server fails at startup with a clear error message.
5. Native QUIC library
HTTP/3 relies on Quiche, a native QUIC implementation provided through Netty. The library is platform-specific: a separate artifact is required for each OS and CPU architecture combination.
The following variants are available:
| Platform | Classifier |
|---|---|
Linux x86_64 |
|
Linux aarch64 |
|
macOS x86_64 |
|
macOS aarch64 (Apple Silicon) |
|
Windows x86_64 |
|
5.1. Automatic dependency selection (Maven only)
When you add the quarkus-http3 extension with Maven, the native QUIC library matching your build-time OS and architecture is included automatically using Maven profile activation.
No manual dependency configuration is needed for typical development and single-platform deployments.
| Gradle does not support conditional profile activation. Gradle users must always declare the native QUIC dependency manually — see Adding the native QUIC dependency (Gradle). |
5.2. Adding additional platform dependencies (Maven)
If you build on one platform but deploy to another (for example, building on macOS but deploying to Linux), you need to explicitly add the dependency for the target platform:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>linux-x86_64</classifier>
</dependency>
You can add as many platform variants as needed. The extension detects available libraries at build time and logs which variants were found.
5.3. Excluding the automatic dependency (Maven)
If you want full control over which native library variants are included, you can exclude the automatic selection and list them explicitly:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-http3</artifactId>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Manually select the platform(s) you need -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>linux-aarch_64</classifier>
</dependency>
| If you exclude the automatic dependency, you must provide at least one platform variant manually. The server will fail to start if no native QUIC library is found on the classpath. |
5.4. Adding the native QUIC dependency (Gradle)
Gradle does not support Maven profile activation, so the native QUIC library is not selected automatically. You must always add the dependency for your target platform(s) explicitly:
implementation("io.quarkus:quarkus-http3")
// Add the native QUIC library for your platform(s)
implementation("io.netty:netty-codec-native-quic::linux-x86_64")
If you build and deploy on the same platform, add only that platform’s classifier. If you build on one platform but deploy to another, add both:
implementation("io.quarkus:quarkus-http3")
// Build platform (e.g., macOS) + deployment platform (e.g., Linux)
implementation("io.netty:netty-codec-native-quic::osx-aarch_64")
implementation("io.netty:netty-codec-native-quic::linux-x86_64")
6. How it works
6.1. Same port, dual transport
The Quarkus HTTP server listens on the HTTPS port (default 8443) for both TCP (HTTP/1.1, HTTP/2) and UDP (HTTP/3 over QUIC) traffic.
There is no separate port for HTTP/3.
6.2. Alt-Svc discovery
When HTTP/3 is enabled, the server automatically adds an Alt-Svc header to HTTP/1.1 and HTTP/2 responses:
Alt-Svc: h3=":8443"; ma=86400
This tells clients that HTTP/3 is available on the same port. Browsers and HTTP clients that support HTTP/3 will upgrade to QUIC for subsequent requests.
To disable the Alt-Svc header:
quarkus.http3.alt-svc=false
7. Using HTTP/3 with the REST Client
The Quarkus REST Client can connect to HTTP/3 servers. To enable HTTP/3 for a specific client, set:
quarkus.rest-client.my-client.http3=true
To enable HTTP/3 for all REST clients:
quarkus.rest-client.http3=true
The target server must support HTTP/3 and the connection must use TLS. Make sure the client’s TLS configuration trusts the server’s certificate:
quarkus.rest-client.my-client.url=https://my-server:8443
quarkus.rest-client.my-client.http3=true
quarkus.rest-client.tls-configuration-name=my-tls-config
See the REST Client guide for more details on REST Client configuration.
8. Limitations
-
Experimental — This feature is under active development. APIs and behavior may change.
-
UDP in containers — HTTP/3 uses UDP. If your application runs in a container (Docker, Kubernetes), ensure UDP port forwarding is configured for the HTTPS port. Some corporate firewalls may also block UDP traffic.
-
No WebSocket over HTTP/3 — WebSocket connections use HTTP/1.1 or HTTP/2. This is a Vert.x limitation, not specific to Quarkus.
-
Native image — HTTP/3 requires a platform-specific native QUIC library (
netty-codec-native-quic). The correct classifier for your platform must be on the classpath.
9. Verifying your HTTP/3 setup
9.1. Using curl
If your curl build supports HTTP/3 (check with curl --version — look for HTTP3 in the features list):
curl --http3 -k https://localhost:8443/hello
The -k flag skips certificate verification (useful with self-signed certificates in dev mode).
9.2. Using browser DevTools
Open your browser’s developer tools, go to the Network tab, and enable the Protocol column.
Requests served over HTTP/3 will show h3.
9.3. Using the Vert.x HTTP client
You can verify HTTP/3 programmatically using the Vert.x HTTP client:
Vertx vertx = ...; // Inject or obtain the Vert.x instance
int port = 8443;
HttpClientConfig clientConfig = new HttpClientConfig();
clientConfig.setVersions(HttpVersion.HTTP_3);
clientConfig.setHttp3Config(new Http3ClientConfig());
ClientSSLOptions sslOptions = new ClientSSLOptions()
.setTrustAll(true); // For dev mode only
HttpClientAgent client = vertx.httpClientBuilder()
.with(clientConfig)
.with(sslOptions)
.build();
client.request(HttpMethod.GET, port, "localhost", "/hello")
.compose(HttpClientRequest::send)
.compose(resp -> {
System.out.println("Protocol: " + resp.version()); // HTTP_3
return resp.body();
})
.compose(body -> {
System.out.println("Body: " + body);
return client.close();
})
.await(10, TimeUnit.SECONDS);