cloudflare/quiche: a low-level QUIC and HTTP/3 library in Rust
🥧 Savoury implementation of the QUIC transport protocol and HTTP/3
At a glance
- What is it?
- quiche implements the QUIC transport protocol and HTTP/3 for applications that bring their own sockets and event loop. The library is current, the command-line tools are explicitly not for production, and the API asks you to configure flow control yourself.
- Who is it for?
- Adopt quiche if you are building a QUIC or HTTP/3 endpoint and you already own the socket loop, the timer wheel and the flow control policy; the crate expects the application to provide all three. Do not adopt it if you want a finished HTTP/3 server with routing, TLS certificate management and configuration files, because quiche-client and quiche-server are documented as unsuitable for production.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What quiche solves, and who it is actually for
QUIC moves retransmission, congestion control, stream multiplexing and TLS into the transport itself, which means an application cannot simply hand bytes to the kernel and forget them. Something has to own the connection state machine, and that something is usually a library. quiche is Cloudflare's Rust implementation of the QUIC transport protocol and HTTP/3 as specified by the IETF, and it is deliberately positioned at the bottom of the stack. The README states that it "provides a low level API for processing QUIC packets and handling connection state", and that "the application is responsible for providing I/O (e.g. sockets handling) as well as an event loop with support for timers".
That sentence defines the audience. quiche is for engineers writing a network service, a proxy, a client library or an embedded endpoint who are willing to write the socket loop themselves. It is not a framework that hands you a running HTTP/3 server. The README lists three consumers: Cloudflare's own edge network HTTP/3 support, Android's DNS resolver for DNS over HTTP/3, and curl, which can be built against quiche for HTTP/3 support. Those are all cases where the surrounding application already had its own I/O model and needed the protocol engine, not a server.
The repository is a Cargo workspace rather than a single crate. Alongside the quiche crate itself, the members list includes apps, h3i, qlog, qlog-dancer, tokio-quiche, buffer-pool, datagram-socket, netlog, octets and task-killswitch. Anyone evaluating the project should read that list before deciding what they are adopting, because the crate on crates.io is only one of the pieces.
The mechanism: Config, connect, recv, send, timeout
The data flow is explicit and small. You create a Config object with quiche::Config::new(quiche::PROTOCOL_VERSION), set the application protocols with set_application_protos, and then create a connection with quiche::connect for a client or quiche::accept for a server. The Config object controls QUIC version, ALPN IDs, flow control, congestion control and idle timeout, and the README notes it can be shared among multiple connections.
From there the loop is yours. Incoming packets go through conn.recv with a RecvInfo carrying the from and to addresses. Outgoing packets come out of conn.send, which returns a SendInfo alongside the number of bytes written, and the loop terminates when send returns quiche::Error::Done. Time is the part people underestimate: the application must maintain a timer, read the deadline from conn.timeout(), and call conn.on_timeout() when it fires, then drain send again because the timeout may have produced new packets.
One detail worth attention is pacing. The README recommends that applications pace outgoing packets to avoid bursts that cause short-term congestion and loss, and quiche exposes pacing hints through the at field of SendInfo. That field is a timestamp for when a packet should go out. Acting on it is left to the caller, using something like the SO_TXTIME socket option on Linux or a custom mechanism. A library that tells you when to send but not how to wait is a deliberate split of responsibility, and it means a naive implementation that ignores at will still work but will behave worse under load.
Building quiche and running the example client and server
The README points at a building section for cloning the project, then shows the command-line tools from the apps crate. The client is run against a URL, and the server needs a certificate and key. The certificate shipped in the repository is self-signed and the README says plainly that it should not be used in production.
cargo run --bin quiche-client -- https://cloudflare-quic.com/The server form takes the certificate and key paths as flags:
cargo run --bin quiche-server -- --cert apps/src/bin/cert.crt --key apps/src/bin/cert.keyBoth tools accept a --help flag, which the README recommends for the full option list. If you would rather not build locally, the Dockerfile builds the release binaries in a rust:1.88 stage and copies quiche-client and quiche-server into a Debian image; the Makefile exposes that as make docker-base, which runs docker build --target quiche-base. The Dockerfile installs clang and cmake because boring-sys needs them to build BoringSSL, so a plain Rust toolchain is not sufficient on its own.
For a first real connection in your own code, the README's minimal setup is a Config with an ALPN identifier. Note that the README warns several properties default to zero and applications most likely need to change them.
let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
config.set_application_protos(&[b"example-proto"]);The six setters named in the README as commonly needing non-zero values are set_initial_max_streams_bidi, set_initial_max_streams_uni, set_initial_max_data, set_initial_max_stream_data_bidi_local, set_initial_max_stream_data_bidi_remote and set_initial_max_stream_data_uni. If a connection opens but immediately stalls, those defaults are the first place to look.
The defaults are zero, and that is a real failure mode
The most consequential limitation is stated in the README rather than hidden: quiche defaults several properties to zero, and the text says applications most likely need to set them to something else. A QUIC connection with no permitted streams and no flow control credit is not useful. This is a reasonable choice for a transport library, since the right values depend entirely on the application, but it converts a configuration mistake into a connection that appears to establish and then does nothing. Anyone integrating quiche should treat the six initial-max setters as mandatory reading, not optional tuning.
The second constraint is architectural. Because quiche does not own sockets or timers, it cannot run anywhere on its own. You need an event loop, a timer implementation, and a mapping from packet metadata back to connections. The README acknowledges that the timer "can be specific to the operating system or networking framework used", which is another way of saying quiche will not choose for you. For a team without prior experience writing a UDP server with timer-driven state, the integration cost is the dominant cost.
The third is scope. The README describes the apps crate tools as examples and states they are not suitable for production environments. There is no configuration file format, no certificate reloading story and no operational surface described for those binaries. If what you want is a deployable HTTP/3 server, quiche is the engine, not the product.
Where quiche sits next to a full server implementation
The natural comparison is with an HTTP/3 server that ships its own runtime, such as one built on a QUIC implementation that includes the event loop, the socket handling and the HTTP/3 framing in one package. The difference is not protocol correctness, since both target the same IETF specifications. The difference is where the boundary of responsibility falls.
With quiche, the boundary is at the packet. You call recv and send, you own the timer, and you decide how to pace using the at hint. With a batteries-included server, the boundary is at the request: you register a handler and the runtime deals with connections, streams and timers. The first model gives you control over threading, buffer reuse and packet scheduling, which is why Cloudflare's edge, Android's DNS resolver and curl all chose it. The second model gets you to a working endpoint faster and is the right answer if HTTP/3 is a feature of your product rather than the product itself.
There is also a middle path inside the repository: the workspace includes tokio-quiche, which is not described in the README excerpt but sits alongside the core crate as a separate member. If you are on Tokio and do not want to hand-write the timer and socket loop, that member is worth reading before you commit to the bare API. The README does not document it, so treat the crate's own documentation as the source.
Licence and the cost of tracking releases
quiche is BSD-2-Clause, both in the repository and in the workspace package metadata. That is a permissive licence, and it is the same family used by many networking libraries, but this is not legal advice and the COPYING file in the repository is the authoritative text. The practical implication for most teams is that linking quiche into a product does not impose source disclosure on the rest of the codebase, which is one reason it is viable for a commercial endpoint.
The upgrade cost is more interesting than the licence. The workspace depends on boring and boring-sys with the range ">=4.19, <6", and the Cargo.toml comments explain that quiche's build.rs detects which major version the resolver selected and emits cfg(boring_v5) so source can switch on it. Because boring-sys uses links = "boringssl", only one major version can be in the dependency graph at a time. That means a BoringSSL major bump is a workspace-wide event, and the Dockerfile's need for clang and cmake follows from it. Release cadence looks steady, with 0.30.0, 0.29.3 and 0.29.2 appearing at intervals through 2026, and the workspace release metadata sets publish = false, so the workspace members are released through their own process rather than a single cargo publish. The last push to master was on 2026-09-21.
Editorial conclusion
Adopt quiche if you are building a QUIC or HTTP/3 endpoint and you already own the socket loop, the timer wheel and the flow control policy; the crate expects the application to provide all three. Do not adopt it if you want a finished HTTP/3 server with routing, TLS certificate management and configuration files, because quiche-client and quiche-server are documented as unsuitable for production. Before committing, verify what set_initial_max_streams_bidi, set_initial_max_data and the other default-zero limits need to be for your workload, confirm which BoringSSL major version your lockfile selects, and read the disclaimers section of the README in full.
Frequently asked questions
What is cloudflare/quiche written in?
It is a Rust project, and the primary language listed for the repository is Rust. The repository is a Cargo workspace with members including quiche, apps, h3i, qlog, tokio-quiche and several others.
Is quiche a QUIC and HTTP/3 library or a ready-to-run server?
It is a library. The README states that it provides a low-level API for processing QUIC packets and handling connection state, and that the application is responsible for providing I/O and an event loop with timer support. The command-line tools in the apps crate are described as examples that are not suitable for production environments.
How do I install or build cloudflare/quiche?
The README points to a building section for cloning the project, and the tools are run through Cargo, for example cargo run --bin quiche-client -- https://cloudflare-quic.com/. The Dockerfile builds the release binaries in a rust:1.88 stage and installs clang and cmake because boring-sys needs them to build BoringSSL.
Why does a quiche connection open but never transfer data?
The README warns that quiche defaults several properties to zero, including the initial maximum stream counts and data limits, and that applications most likely need to set them. The setters named are set_initial_max_streams_bidi, set_initial_max_streams_uni, set_initial_max_data and the three set_initial_max_stream_data variants.
What licence does cloudflare/quiche use?
The repository and the workspace package metadata both list BSD-2-Clause. The COPYING file in the repository is the authoritative licence text.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cloudflare-quiche)
Community notes