quic-go: a pure Go QUIC and HTTP/3 stack for servers you compile yourself
A production-ready QUIC implementation in pure Go. FIPS 140-3 Starting with v0.60, quic-go supports use in FIPS 140-3 environments when built with Go 1.26 or newer, using Go standard library cryptography for the QUIC code paths relevant in FIPS mode; see FIPS140.md for details.
At a glance
- What is it?
- quic-go implements RFC 9000, 9001 and 9002 plus HTTP/3 in Go, with FIPS 140-3 support from v0.60 on Go 1.26 or newer. It is a library, not a daemon, and that shapes both its reach and its limits.
- Who is it for?
- Adopt quic-go if you are writing a Go server or client that needs QUIC or HTTP/3 in-process and you can track a moving Go toolchain: go.mod pins go 1.26.0, and FIPS mode additionally requires Go 1.26 or newer. Do not adopt it if you want a standalone proxy or tunnel binary with its own config file; that is what frp, gost or Hysteria are for, and quic-go is the layer they build on.
- Can I use it commercially?
- Yes. MIT 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 last received commits 8 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What quic-go actually solves, and who ends up using it
QUIC is a transport protocol, and someone has to implement it before your Go program can speak it. quic-go is that implementation: RFC 9000 for the transport, RFC 9001 for TLS integration, RFC 9002 for loss detection and congestion control, plus the Unreliable Datagram Extension (RFC 9221), DPLPMTUD (RFC 8899), QUIC Version 2 (RFC 9369) and qlog event logging. HTTP/3 sits on top, with QPACK (RFC 9204), the Extensible Prioritization Scheme (RFC 9218) and HTTP Datagrams with the Capsule Protocol (RFC 9297).
The audience is narrower than the protocol list suggests. The README's own table of projects using quic-go is a list of applications and proxies, not of end users: AdGuardHome, algernon, Caddy, cloudflared, frp, go-libp2p, gost, Hysteria, Mercure, nodepass, OONI Probe, reverst, RoadRunner, syncthing, traefik and v2ray-core. Every one of those is a Go program that vendors the library. If you are not writing or extending a Go program, quic-go is not a product you install and run; it is a dependency you compile in. That distinction decides most of the questions below.
The architecture: a library split into transport and http3 packages
The repository layout shows the split clearly. The top level holds the transport: connection.go, crypto_stream.go, crypto_stream_manager.go, conn_id_manager.go, conn_id_generator.go, flow_controller_base.go, flow_controller_connection.go and flow_controller_stream.go, framing in framer.go and frame_sorter.go, plus datagram_queue.go for the datagram extension. HTTP/3 lives in its own http3/ directory. config.go and interface.go are the entry points a caller touches; internal/ holds what the project does not promise to keep stable.
That structure tells you where the complexity sits. Connection IDs are generated and managed in separate files, which is what makes connection migration possible: the connection survives an address change because the identifier is not the address. Flow control is split three ways (base, connection, stream), matching QUIC's two-level credit model. The crypto stream is separate from application streams. If you are debugging behaviour, this is also where to look: a stalled transfer is usually a flow-control window, not a lost packet.
Two interfaces matter at the API level. The transport package gives you a connection-oriented QUIC endpoint; the http3 package gives you an HTTP/3 server and client on top of it. The example/ directory ships client/, echo/ and main.go, which is the project's own minimal demonstration of that layering.
Adding quic-go to a module and running the bundled echo example
There is no installer. You add the module to a Go module and compile. The go.mod in the repository declares the module path github.com/quic-go/quic-go and pins go 1.26.0, so your toolchain has to satisfy that. The commands below are the ordinary Go module workflow applied to the paths the repository actually contains; the README does not print an install snippet of its own.
Running the echo server from a checkout
The repository's own example lives in example/, with example/echo/ and example/client/ as the two halves. Running them from a checkout is the shortest path to seeing a handshake complete. The README does not document the exact invocation, so treat this as the natural Go way to build the packages that are present rather than a quoted snippet.
Connecting with the example client
In a second terminal, the client half connects to the echo server. The client directory is example/client/, so the same pattern applies. What you should see is the client printing the payload the server echoed back, which confirms the handshake, the stream and the TLS setup all worked on your machine.
FIPS 140-3 mode and the Go version constraint it imposes
The FIPS story is the most consequential constraint in the README, and it is easy to misread. Starting with v0.60, quic-go supports use in FIPS 140-3 environments when built with Go 1.26 or newer, using Go standard library cryptography for the QUIC code paths relevant in FIPS mode. The README defers the details to FIPS140.md.
Read that sentence carefully. FIPS support is conditional on the Go toolchain version, not on a quic-go build tag alone, and it covers the code paths relevant in FIPS mode rather than the whole library by assertion. If your compliance story depends on this, FIPS140.md is the document to read, and the exact Go version in your build image is the thing to verify. A team on an older Go release gets the library but not the FIPS claim. Note also that the repository's OSS-Fuzz integration is commented out in the README because OSS-Fuzz still uses Go 1.25 while quic-go requires Go 1.27; the project tracks that in a linked issue. Continuous fuzzing coverage and FIPS coverage therefore pull in opposite directions on toolchain version, which is worth knowing before you assume both are active at once.
Where quic-go is the wrong tool
The clearest failure mode is a category error: treating quic-go as an application. It has no config file, no service unit, no CLI, and no release binary. If you want a QUIC proxy or tunnel you can install and configure, the README's own list points elsewhere, and those projects embed quic-go rather than replace it.
The second limitation is the Go version floor. go.mod requires go 1.26.0, and FIPS mode raises that to Go 1.26 or newer in the README's wording. Distributions that ship older toolchains, or teams pinned to an older Go for other dependencies, will hit this before they hit anything protocol-related.
Third, the documentation surface is uneven. The README is explicit that detailed documentation is on quic-go.net, and the repository itself carries FIPS140.md, FUZZING.md and SECURITY.md but no getting-started guide. There is no rollback or migration guidance in the README for moving between the v0.59, v0.60 and v0.61 lines; if you need that, the release notes are the only source named. Finally, connection migration and datagram support are protocol features, not free wins: they change what your application has to handle, and the README documents the specifications rather than the operational consequences.
quic-go against quinn and the layers above it
The practical alternative for a Rust codebase is quinn, and the difference is not just language. Choosing between them means choosing an ecosystem: quic-go is a Go module that Caddy, Traefik, syncthing and go-libp2p already depend on, so its HTTP/3 support and its transport are exercised by those projects' test suites as well as its own. A Rust stack gives you Rust's ownership model and a different set of consumers.
The README's related-projects list is the more interesting comparison for Go users. webtransport-go implements WebTransport over HTTP/3, masque-go implements CONNECT-UDP (RFC 9298), and connect-ip-go implements CONNECT-IP (RFC 9484). These are not competitors to quic-go; they are layers above it, and they tell you what the project expects you to build. If your goal is WebTransport, you want webtransport-go on top of quic-go rather than quic-go alone. If your goal is a CONNECT-UDP proxy, masque-go is the named starting point. Picking quic-go when one of those three already covers your use case means writing code the project has already written.
Editorial conclusion
Adopt quic-go if you are writing a Go server or client that needs QUIC or HTTP/3 in-process and you can track a moving Go toolchain: go.mod pins go 1.26.0, and FIPS mode additionally requires Go 1.26 or newer. Do not adopt it if you want a standalone proxy or tunnel binary with its own config file; that is what frp, gost or Hysteria are for, and quic-go is the layer they build on. Before committing, confirm the exact Go version your build image provides, read FIPS140.md if the FIPS mode matters to you, and check the release notes for the API surface you plan to call, because the project's own docs point at quic-go.net/docs rather than the repository README.
Frequently asked questions
What is quic-go?
It is an implementation of the QUIC protocol (RFC 9000, RFC 9001, RFC 9002) written in pure Go, and it also implements HTTP/3 (RFC 9114). It ships as the Go module github.com/quic-go/quic-go rather than as a standalone program.
What is QUIC used for?
QUIC is the transport protocol quic-go implements, and the README lists extensions for unreliable datagrams, path MTU discovery, Version 2, qlog event logging and stream resets with partial delivery. On top of it, quic-go supports HTTP/3 with QPACK, the Extensible Prioritization Scheme and HTTP Datagrams.
Which apps use quic-go?
The README's table lists AdGuardHome, algernon, Caddy, cloudflared, frp, go-libp2p, gost, Hysteria, Mercure, nodepass, OONI Probe, reverst, RoadRunner, syncthing, traefik and v2ray-core. All of them are Go programs that depend on the library.
Does Google Chrome use QUIC?
The README does not say whether Chrome uses QUIC, and it does not state that Chrome uses quic-go. Its list of projects using quic-go names Go servers and proxies such as Caddy, traefik, syncthing and frp, not browsers.
Should we block QUIC?
The README does not discuss blocking QUIC or network policy around it. It documents the protocol specifications quic-go implements and the projects that depend on it, so this question cannot be answered from the README.
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/quic-go-quic-go)