Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

aiopquic - Async QUIC + WebTransport (picoquic)

aiopquic is a Python/Cython binding to picoquic, providing high-performance QUIC transport and WebTransport for asyncio applications.

Overview

aiopquic exposes picoquic's QUIC implementation through a lock-free SPSC ring buffer architecture that bridges the picoquic network thread with Python's asyncio event loop. It provides an asyncio QUIC/HTTP3 transport API in the spirit of aioquic (and its fork qh3) — similar shapes for QuicConfiguration, QuicConnection, connect / serve, and event types — plus a native WebTransport client/server layered on picoquic's H3 + h3zero. Not a drop-in replacement: semantics differ around backpressure (send_stream_data raises BufferError on full per-stream ring) and flow-control sizing.

Architecture

  • SPSC Ring Buffers -- Lock-free single producer/single consumer rings for event passing between threads, separate TX and RX rings per TransportContext.
  • TX path -- Asyncio pushes into per-stream byte ring; picoquic pulls at wire rate via prepare_to_send.
  • RX path -- picoquic pushes per-event StreamChunks; ownership transfers at pop for 1-copy delivery.
  • Cross-platform wake fd -- Linux eventfd for efficient asyncio add_reader() notification; pipe() self-pipe fallback on macOS / BSD.
  • Dedicated Network Thread -- picoquic runs in its own thread via picoquic_start_network_thread(). One worker thread per TransportContext; multiple contexts share the asyncio event loop within a single Python process.
  • Cython Bridge -- Thin Cython layer over C callbacks, minimal overhead.
  • WebTransport -- asyncio.webtransport.WebTransportSession (client + server) over picoquic's picowt_* API and h3zero.

Features

  • QUIC client and server: connect, serve, QuicConnectionProtocol
  • Stream data send/receive with FIN signaling, stream reset, stop_sending
  • WebTransport client + server: serve_webtransport, WebTransportSession
  • QUIC datagram TX + RX (note: WebTransport datagram TX not yet wired)
  • Connection migration / 0-RTT (inherited from picoquic)
  • Connection management: create, close, idle timeout, application close codes
  • Per-cnx multiplexing on the server side via QuicEngine
  • TLS keylog (NSS Key Log Format) for pcap decryption
  • Native picoquic_ct / picohttp_ct subprocess smoke (catches upstream regressions on every submodule update)

Performance

Multi-Gbps sustained throughput over loopback on commodity hardware: 2+ Gbps through the full asyncio API at the QUIC default MTU (where the kernel's sendmsg syscall rate is the wall), 11+ Gbps protocol-only. Numbers, methodology, reproduction commands, build flags, and runtime tuning (jemalloc, GSO, wake thresholds) live in PERFORMANCE.md. The TX/RX dataflow and flow-control model — including the TX backpressure configuration parameters — are documented in DATAFLOW.md.

Installation

Wheels for cp312 / cp313 / cp314 on Linux (manylinux_2_34, glibc 2.34+) and macOS arm64 are published to PyPI:

uv pip install aiopquic     # or: pip install aiopquic

For older Linux (glibc 2.28–2.33) install via sdist; build toolchain required.

From source

git clone https://github.com/gmarzot/aiopquic.git
cd aiopquic
./bootstrap_python.sh    # creates .venv with uv-managed Python 3.14 (GIL build) and pins cython 3.2+
source .venv/bin/activate
./build.sh               # reconcile submodules, build picotls/picoquic + drivers, relink + verify
uv pip install -e '.[dev]'    # add dev/test extras — or: pip install -e '.[dev]'

Re-run ./build.sh after any git checkout or submodule bump — it is idempotent (a matching fingerprint skips the compile) and guarantees the imported aiopquic reflects the current source, host-tuned. ./build.sh --check is a read-only doctor that reports submodule drift, a stale native build, or a portable wheel shadowing the editable install, and exits nonzero — handy as a pre-benchmark or CI gate.

On macOS, set OPENSSL_ROOT_DIR if Homebrew OpenSSL is not auto-detected (the build script tries openssl@3 then openssl@1.1).

Reporting issues

Include the full version report in any issue — it captures aiopquic plus the picoquic + picotls submodule SHAs the binding was built from:

python -m aiopquic.versions   # or the console script: aiopquic-versions

Sample output:

aiopquic:  0.3.7.dev12+g6eef9caf6 (~/Projects/moq/aiopquic/src/aiopquic) [2026-06-12 08:55]
  - picoquic:  1.1.49.2 (d6c5653d) [2026-06-05]
  - picotls:   master (bfa67875) [2026-04-20]

If you're running aiomoqt on top, prefer python -m aiomoqt.versions — it chains through to this report and includes the aiomoqt version too.

Usage

Low-level Transport API

from aiopquic._binding._transport import TransportContext

server = TransportContext()
server.start(port=4433, cert_file="cert.pem", key_file="key.pem", alpn="moq-00", is_client=False)

client = TransportContext()
client.start(port=0, alpn="moq-00", is_client=True)
client.create_client_connection("127.0.0.1", 4433, sni="localhost", alpn="moq-00")

Asyncio API

from aiopquic.asyncio.client import connect
from aiopquic.quic.configuration import QuicConfiguration

configuration = QuicConfiguration(alpn_protocols=["myproto"], is_client=True)

async with connect("server", 4433, configuration=configuration) as protocol:
    quic = protocol._quic
    stream_id = quic.get_next_available_stream_id()
    quic.send_stream_data(stream_id, payload, end_stream=True)

payload is opaque bytes; the library doesn't impose framing. Consumers that want HTTP/3 layer on top of aiopquic's picowt-backed h3zero plumbing; consumers that want WebTransport use serve_webtransport / connect_webtransport. Most direct users of the asyncio API ship their own protocol bytes (MoQT, custom binary frames, etc.).

Clients verify the server's certificate chain and name against certifi's roots. A private CA goes in QuicConfiguration.cafile (or load_verify_locations(cafile=...)), and connect_webtransport(ca_file=...) takes the same file. To accept any certificate, such as a self-signed test server, set verify_mode=ssl.CERT_NONE or pass connect_webtransport(verify_peer=False). Clients offer a classic key share first; QuicConfiguration.key_exchange_groups (or start(key_exchange_groups=...)) puts KEX_X25519MLKEM768 first for a post-quantum key exchange with servers that support it.

WebTransport

from aiopquic.asyncio.webtransport import (
    serve_webtransport, WebTransportSession,
)
# See src/aiopquic/asyncio/webtransport.py and tests/ for full examples.

Development

uv pip install -e '.[dev]'    # or: pip install -e '.[dev]'
python -m pytest tests/ -v -m "not interop and not native"

# Microbenches (opt-in)
python -m pytest tests/bench

Test-suite coverage, benchmark methodology, performance builds (AIOPQUIC_PERF=1, io_uring scaffolding), and runtime tuning are documented in PERFORMANCE.md.

Known Limitations

  • Free-threaded Python (3.14t) not yet supported -- the TX-ring producer side, TransportContext lifecycle, and the WebTransport engine state currently rely on the GIL for serialization. FT support deferred until a per-context locking audit lands.
  • STOP_SENDING error codes surface as 0 today: picoquic's public stream-error getter only returns the RESET_STREAM code. STOP_SENDING's code lives in stream->remote_stop_error in picoquic_internal.h (no public getter). A small helper that pulls the field is straightforward future work — see TODO in src/aiopquic/_binding/c/callback.h.

TODO

  • Windows support (eventfd alternative — IOCP / WSAEventSelect on the wake-fd path)
  • Free-threaded Python (3.14t) support after producer-side locking audit
  • STOP_SENDING error-code surfacing helper (read remote_stop_error from picoquic_internal.h)
  • WebTransport datagram TX path through the C bridge
  • Datagram benches: latency percentiles, payload-size sweep, loss / jitter under load (today's bench_datagram is fire-and-count throughput only)
  • Pure stream open/close microbench (lifecycle rate without payload, separate from bench_stream_churn_highlevel which bundles writes + FIN)
  • Submit aiopquic to the QUIC interop runner for cross-implementation coverage

Resources



A Marz Research project.
Author: G. S. Marzot <gmarzot@marzresearch.net>

License

MIT License -- see LICENSE

Metadata

Release files for aiopquic 0.5.0a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aiopquic 0.5.0a2
File Size Uploaded Provenance
aiopquic-0.5.0a2.tar.gz 3.6 MB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for aiopquic 0.5.0a2
File
aiopquic-0.5.0a2-cp314-cp314-manylinux_2_34_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.34+ x86-64 Details
aiopquic-0.5.0a2-cp314-cp314-manylinux_2_34_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.34+ ARM64 Details
aiopquic-0.5.0a2-cp314-cp314-macosx_14_0_arm64.whl CPython 3.14 CPython 3.14 macOS 14.0+ ARM64 Details
aiopquic-0.5.0a2-cp313-cp313-manylinux_2_34_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.34+ x86-64 Details
aiopquic-0.5.0a2-cp313-cp313-manylinux_2_34_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.34+ ARM64 Details
aiopquic-0.5.0a2-cp313-cp313-macosx_14_0_arm64.whl CPython 3.13 CPython 3.13 macOS 14.0+ ARM64 Details
aiopquic-0.5.0a2-cp312-cp312-manylinux_2_34_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.34+ x86-64 Details
aiopquic-0.5.0a2-cp312-cp312-manylinux_2_34_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.34+ ARM64 Details
aiopquic-0.5.0a2-cp312-cp312-macosx_14_0_arm64.whl CPython 3.12 CPython 3.12 macOS 14.0+ ARM64 Details

Total release size: 48.0 MB

Release files / aiopquic-0.5.0a2.tar.gz

Download URL aiopquic-0.5.0a2.tar.gz
Size 3.6 MB
Tags Source
SHA-256 checksum
How to use checksums
0e9e02c9d1cf07d8278ad20f8429d2e533c2dd8436eb9d8b1c10a07f6d090441
BLAKE2b-256 checksum
How to use checksums
cd07938662e2c94a889732505b3441ed4a28a8c5fd6c80beca381c956d4878f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp314-cp314-manylinux_2_34_x86_64.whl

Download URL aiopquic-0.5.0a2-cp314-cp314-manylinux_2_34_x86_64.whl
Size 5.5 MB
Tags CPython 3.14 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
43a49f2f7cade763cf6c1a9819a4edadacf0437b45aa1e76e626537e547f512d
BLAKE2b-256 checksum
How to use checksums
a4e3506edd0db0adeda2376b6c9d008cf04b7573c040a49f860074e67d480a55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp314-cp314-manylinux_2_34_aarch64.whl

Download URL aiopquic-0.5.0a2-cp314-cp314-manylinux_2_34_aarch64.whl
Size 5.2 MB
Tags CPython 3.14 Linux glibc 2.34+ ARM64
SHA-256 checksum
How to use checksums
2a8e0c494c5f2e4c222d3c5a05c5059021bcf63d58b39145566c3dfb0ea87e0c
BLAKE2b-256 checksum
How to use checksums
913e5e7d737e5874c81aff44e8a88bc07152c5544d13bb36925f6e6cb5cdc5ce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp314-cp314-macosx_14_0_arm64.whl

Download URL aiopquic-0.5.0a2-cp314-cp314-macosx_14_0_arm64.whl
Size 4.1 MB
Tags CPython 3.14 macOS 14.0+ ARM64
SHA-256 checksum
How to use checksums
33b97969bed1d22ccd1ec0ab3f52237ce5f69e83a047258a9828e36146e47036
BLAKE2b-256 checksum
How to use checksums
6c5d57e9e27137fc314be1427082c1e44ab7d2e1f807091a54f65e081d9b7d06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp313-cp313-manylinux_2_34_x86_64.whl

Download URL aiopquic-0.5.0a2-cp313-cp313-manylinux_2_34_x86_64.whl
Size 5.5 MB
Tags CPython 3.13 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
c6c4c1ae46d1f5a2f31c585f57e7a4cd9168005e60747d223fdaf166349a139e
BLAKE2b-256 checksum
How to use checksums
730ae79b09b563fab64241ee44ad96ec8ad11e4752487a8a8a11199d3e6bdec9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp313-cp313-manylinux_2_34_aarch64.whl

Download URL aiopquic-0.5.0a2-cp313-cp313-manylinux_2_34_aarch64.whl
Size 5.2 MB
Tags CPython 3.13 Linux glibc 2.34+ ARM64
SHA-256 checksum
How to use checksums
89ed75af02596cb6567e12d43f51adce733c1ba5f606d2e90ed7f2bde267f30d
BLAKE2b-256 checksum
How to use checksums
6d24e9844dacf7e9c5e3912df36492f833b59d54300b122452c1beefdbd9094e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp313-cp313-macosx_14_0_arm64.whl

Download URL aiopquic-0.5.0a2-cp313-cp313-macosx_14_0_arm64.whl
Size 4.1 MB
Tags CPython 3.13 macOS 14.0+ ARM64
SHA-256 checksum
How to use checksums
0a527b04937ba69e5ed9f19cefb79ad2602798a53c9bec41daeb517d437192bb
BLAKE2b-256 checksum
How to use checksums
1d599bffb9dad1050c1e5711735298ef0603b944bab6d8ad922b02ed6f6607a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp312-cp312-manylinux_2_34_x86_64.whl

Download URL aiopquic-0.5.0a2-cp312-cp312-manylinux_2_34_x86_64.whl
Size 5.5 MB
Tags CPython 3.12 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
11aea1d3fb2dd07a0d5def67e1a648e3d91712be725e3ca4794ee63ff0745cae
BLAKE2b-256 checksum
How to use checksums
6da8214c32750ce247423e2e22a87c73c23ffa7fbe14b93dfbd14ef0a19b4f67
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp312-cp312-manylinux_2_34_aarch64.whl

Download URL aiopquic-0.5.0a2-cp312-cp312-manylinux_2_34_aarch64.whl
Size 5.2 MB
Tags CPython 3.12 Linux glibc 2.34+ ARM64
SHA-256 checksum
How to use checksums
3da2868fca473942901f143f82d2081ec4aa1541567c81535a2a2ba31a681ef9
BLAKE2b-256 checksum
How to use checksums
5e80f61fc622890d38bad7b53dd32f88569cd55e06753da0d21cad6cec4610f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / aiopquic-0.5.0a2-cp312-cp312-macosx_14_0_arm64.whl

Download URL aiopquic-0.5.0a2-cp312-cp312-macosx_14_0_arm64.whl
Size 4.1 MB
Tags CPython 3.12 macOS 14.0+ ARM64
SHA-256 checksum
How to use checksums
42d1fb708ab692836a041fb55c2d1d9bc6304a83f5052c2842ade7a8c25947bc
BLAKE2b-256 checksum
How to use checksums
f35c89d2151df83b2a8c88669dde50e6dca6868cb3b6d775085d03f74ab8feb2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Security for aiopquic 0.5.0a2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page