Hi everyone,
erlang_quic 2.2.1 has just been released, with quite a lot of changes since the last version announced here (1.8.0).
For those not familiar with it, erlang_quic is a QUIC (RFC 9000/9001/9002) and HTTP/3 implementation written entirely in Erlang.
This release continues a substantial effort to make the library more reliable in real network conditions. Beyond new features, much of the work has focused on RFC compliance, interoperability with other QUIC implementations, connection migration and recovery under packet loss or reordering.
The result is a more mature implementation, tested against 18 other QUIC stacks, with improved performance, better flow control and more robust connection handling.
Here are the main changes since 1.8.0.
{deps, [{quic, "2.2.1"}]}.
RFC compliance and interoperability
A detailed review of RFC 9000, 9001 and 9002 resulted in around 60 fixes, covering frame validation, flow control, connection IDs, recovery and timeout handling.
erlang_quic was also tested against 18 other implementations using the QUIC Interop Runner. This exposed issues with handshake loss, key updates, rebinding and QUIC v2 negotiation, which have since been fixed.
These tests have been particularly useful to improve how the library behaves when packets are lost, reordered, or when peers don’t behave exactly as expected.
Connection migration
Connection migration has been largely improved. An existing connection can move to another network address without a new handshake or losing its streams.
For example, a client switching from Wi-Fi to cellular can migrate its connection:
{ok, Conn} = quic:connect(
"example.com", 443,
#{alpn => [<<"h3">>]},
self()
),
%% Later, after a network change
ok = quic:migrate(Conn).
The server validates the new path before using it, limits traffic to unvalidated addresses and falls back to the previous path if validation fails. Congestion control is also restarted for the new path.
Server preferred addresses are now supported, allowing a server to suggest another address after the handshake.
Migration requires a confirmed handshake and an available connection ID.
Flow control and performance
Receive backpressure is now available with flow_control => manual. Using quic:consume/3 or quic_h3:consume/3, applications can control how much data they receive. This prevents a slow reader from filling its process mailbox.
On the sending side, send_ready events notify applications when they can retry after send_queue_full.
Packet processing has also been improved with batched sends, reduced per-packet state copies and ACKs sent together with data packets.
An optional crypto NIF (QUIC_OFFLOAD=1) can accelerate packet encryption and decryption. The library remains fully functional in pure Erlang.
Recovery fixes also brought several times better download performance on lossy networks with packet reordering.
Security and other changes
A few other changes worth mentioning:
-
Post-quantum key exchange: support for
x25519mlkem768, opt-in throughgroups. -
0-RTT: returning clients can send data without waiting for a new handshake. Session tickets now preserve the server’s limits for early data.
-
QUIC distribution: fixed GHSA-h2qx-fxx7-7r6j, where
{verify, verify_peer}was ignored. Upgrading is recommended if using QUIC distribution with certificate verification. -
Session tickets: resumption is now restricted to the listener that issued the ticket.
-
Fixes for listener stalls, mailbox growth and connection lifecycle issues.
There are also some changes to consider when upgrading, notably HTTP/3 close notifications, ALPN validation and migration before handshake confirmation. See the changelog for details.
Final notes
Most of the work since 1.8.0 has been about making erlang_quic more reliable and interoperable, beyond simply adding features. The RFC review and interoperability tests helped identify issues that are difficult to catch with regular tests alone.
A large part of this work, particularly around RFC compliance, interoperability and migration, was contributed by Johan Bevemyr. Many thanks to him.
Feedback and testing are welcome, especially from people using QUIC or HTTP/3 in Erlang applications. It would be interesting to hear about existing use cases and what could still be improved.
Thanks!
Make the release claims more preciseClarify the upgrade guidance