GitHub: moqtail/moqtail
Maintainers: Zafer Gürel, Ali C. Begen
Draft support: draft-16 on main, with a draft-18 alignment sprint underway (July–August 2026) — ALPN bumped to moqt-18, Extension Headers renamed to Properties, single unified SETUP (CLIENT_SETUP/SERVER_SETUP collapsed), split delivery timeouts, control-message-type table + LOC property ids renumbered to draft-18, and draft-18 constants + varint conformance vectors added; the sprint reached the Rust side in July and the moqtail-ts (TypeScript) side began landing the same wire changes Aug 10 (Kerem Bekmez), working down the ~20-issue moqtail-ts API-break backlog (draft-14 docs removed May 4 2026)
Overview
MOQ Transport protocol libraries for publisher, subscriber, and relay components. Features real-time, live, and on-demand demo applications using both LOC and CMSF formats. Libraries are published as moqtail-rs (Rust) and moqtail-ts (TypeScript).
Components
- Relay — public relays at
relay.moqtail.dev(draft-14) andrelay18.moqtail.dev(draft-18, online July 23 2026 for IETF-126 conformance testing, with a public Grafana dashboard; see interop-endpoints) - Publisher — media publishing library
- Subscriber — media subscription library
- Demo apps — real-time, live, and on-demand examples, plus
apps/client-js(browser subscriber) andapps/meet(WebRTC-over-MoQ video-conferencing demo) - Transports — WebTransport and raw QUIC (raw-QUIC support added June 2026, PR #204 / #205)
Draft support
draft-16 on main — full draft-ietf-moq-transport-16 compliance landed May 4 2026 via the umbrella PR #145 (open since March 6, +17k/−11k). draft-14 documentation was removed the same day, making moqtail a single-draft project. The draft-16 work brought:
- ALPN-based ClientSetup/ServerSetup negotiation
- typed MessageParameter control parameters (replacing VersionParameter), plus Track and Object Extensions
- a unified request-ID registry correlating REQUEST_OK / REQUEST_ERROR / REQUEST_UPDATE with their source requests
- the finalized FETCH-object wire format (bitmask serialization flags, delta encoding, end-of-range markers)
draft-17 features shipped ahead of full adoption:
- the §7.2 relay scheduling algorithm (PR #178, Apr 30) — relay priorities computed from subscriber and publisher priorities; first moqtail merge of a draft-17-specific feature
- the SUBSCRIBE_NAMESPACE / SUBSCRIBE_TRACKS stream split (PR #180, May 1) — merged ~10h before upstream moq-transport PR #1542, the first implementation to ship the split design
Recent Highlights
Day-by-day PR/issue history lives in the wiki log; this section keeps only durable milestones.
- moqtail-ts draft-18 alignment (Aug 2026): after the July sprint aligned the Rust side, the TypeScript library (
libs/moqtail-ts) began landing the same draft-18 wire changes on Aug 10 — all Kerem Bekmez: CLIENT_SETUP/SERVER_SETUP collapsed into a single SETUP (PR #334, +506/−434), the control streams reworked per draft-18 (PR #335, +191/−70), and request types moved onto their own bidirectional stream (PR #336, +718/−124) — the moqtail-ts counterpart of the RS-side 297 work, drawing down the ~20-issue moqtail-ts API-break backlog; the sprint continued Aug 11 with PR #355 (“feat/ts10-11”, +657/−94, closes 266). - Relay conformance/hardening sprint (Aug 11 2026): the relay’s runtime correctness got a concentrated ~11-PR pass, all Zafer Gürel — build the relay’s own SETUP parameters instead of forwarding them upstream (#359, +307/−100), end a namespace announcement when its request stream ends (#358), deduplicate Objects + raise Forward State (#356), wait for a track alias on notification (#354), reset a cancelled subscription’s streams (#353), report the true
LARGEST_OBJECTdownstream (#352), reject a duplicate SUBSCRIBE withDUPLICATE_SUBSCRIPTION(#351), apply forward state + subscription filter to datagrams (#350), pin the FETCH object layout to the wire (#349), and a subscribe-error-after-accept fix (#348). Zafer also opened imquic #35 (fix FETCH object parsing of subgroup flags + object status), cross-pollinating the FETCH-layout work into Miniero’s C library. No new relay release — relay@0.14.1 stands. - draft-18 alignment sprint (July 2026): after months at draft-16, moqtail began converging on the interop-runner’s draft-18 target. Day 1 (July 15): ALPN bumped to
moqt-18(PR #280) and Extension Headers renamed to Properties (PR #281, the -18/-19 terminology). Day 2 (July 16) landed the bulk of the wire changes: CLIENT_SETUP/SERVER_SETUP collapsed into a single SETUP (PR #286), delivery timeouts split into object/subgroup + rendezvous/fill with param numbers aligned (PR #287), the control-message-type table moved to draft-18 (PR #284), LOC property ids renumbered (PR #285, pairing with loc #25), plus draft-18 constants + varint conformance vectors shared for cross-impl testing (PR #283). Day 3 (July 17) closed the wire work: the FIRST_OBJECT SUBGROUP_HEADER bit (PR #290, MERGED) and the moqtail-ts control-message-type table (PR #291, Kerem Bekmez, MERGED). Then a large control-plane-restructure wave landed over the July-19/20 Hackathon weekend — ~11 PRs (#292–#302) working down the RS-/CL-/RL- task list (issues #230–#242): request types moved onto their own bidirectional streams (#297), the control plane onto a pair of uni streams (#294), PUBLISH_OK folded into REQUEST_OK + Track Properties added (#299), MAX_REQUEST_ID / REQUESTS_BLOCKED removed (#298), Request ID removed from response messages (#302), REQUEST_UPDATE rejection/failure handling (#301), stream reset codes + reset path (#300), GREASE + reserved Property ranges (#296),moqt://as the unified selectable-transport scheme (#295), Mandatory Track Properties enforced (0x4000–0x7FFF) (#293), and delta-encoded Group/Object IDs in FETCH responses (#292). The sprint continued through July 20 (#303–#308): the SUBSCRIBE_NAMESPACE / SUBSCRIBE_TRACKS split (#305), removal of the cancel/teardown message family (#303, −857 LOC), zero-element track namespaces (#306), and the PUBLISH_BLOCKED message (#308, merged July 21 — see the relay-resilience batch below). Themoqtail-tsAPI break —moqt://URL scheme, the SUBSCRIBE_NAMESPACE / SUBSCRIBE_TRACKS split, PUBLISH_BLOCKED, GREASE — is tracked in a ~20-issue backlog, with Kerem Bekmez now a second active contributor. Makes moqtail a second non-moq-dev implementation actively converging on the runner’s target. - Relay-resilience / DoS-protection batch (July 21): with the wire format aligned, Zafer Gürel built out the relay’s operational surface from the RL-* task list — the PUBLISH_BLOCKED message (#308, +151/−11), GOAWAY Request ID + Timeout and the REDIRECT structure (#310, +300/−66), EXCESSIVE_LOAD shedding on request streams (#311), graceful SIGTERM drain (send GOAWAY + reject new requests, #312, RL-5), TOO_FAR_BEHIND reset of slow subscribers (#313), and SUBSCRIBE precedence over SUBSCRIBE_TRACKS (#314) — i.e. the graceful-shutdown, load-management, and DoS-protection surface a relay needs beyond interop conformance. A second batch landed July 22 (eight more PRs, all Zafer Gürel): standalone FETCH range validation + End Location clamp (#317), joining-fetch forward-state semantics (RL-7a) (#318), FETCH Stream Count + prior-gap semantics (RL-7b) (#319), rejecting reserved namespaces
.session/.locally (RS-17a) (#324), PUBLISH_BLOCKED on stream exhaustion (RL-2) (#326), forwarding SUBSCRIBE_TRACKS PUBLISH on its own bidi stream (#327), a subgroup-reopen test (RS-17b, #325), and moqtail-rs EndGroup-delta / datagram status+properties / padding (#320). GOAWAY per-request migration / REDIRECT retry (#309) remains open. A third, lifecycle-correctness batch landed July 23 (Zafer Gürel): remove track when the last subscriber leaves (#330, +26/−8) — freeing per-track relay state on the final unsubscribe — plus per-bidi control-message logging (#329) and a comment cleanup (#328); a July-24 follow-up fixed a resubscribe regression the #330 change introduced (#331, fix relay resubscribe after last subscriber). Motivating this: at IETF-126 (July 22) afrind began running his 41-test draft-18 data-plane conformance suite against relays; Zafer Gürel said moqtail is “working on it, a few issues left,” then brought a public draft-18 relay online atrelay18.moqtail.devJuly 23 (public Grafana dashboard) and put it forward for testing — in Jordi Cenzano’smoq-encoder-playermatrix it now carries full video+audio. No new release — relay@0.14.1 stands. - Wire-correctness fixes (interop-relevant): Key-Value-Pair parameters, previously serialized as absolute values, are now delta-encoded as the draft mandates (PR #208); subgroup-header type detection moved to bitmask dispatch (PR #211). Both target cross-version mismatches that surface as interop failures.
- Relay conformance hardening: FETCH_OK is now sent for all non-empty fetch ranges (PR #199), and late subscribers joining a track mid-subgroup receive the in-progress subgroup from its start instead of silently dropping objects (PR #201).
- Upstream FETCH on cache miss: the relay now sends FETCHes upstream to the publisher for groups missing from its local cache — a contributor-led capability landed via sharmafb’s [1/n]–[3/n] series (PR #186 / #187 / #188) and completed in PR #193.
- Per-subscription early-discard:
setEarlyDiscardPolicy(cancel slow subgroup streams after a timeout) can be set per subscription rather than globally (PR #189). - Widening contributor base: beyond maintainers Zafer Gürel and Ali C. Begen, external contributors now land code — sharmafb / Aman Sharma (also a moq-transport editor, contributing FETCH-priority test tooling), davemevans / David Evans (Firefox private-CA test docs), Kerem Bekmez, and thexeos.
Known Issues
- Reported sending AUTHORITY param back in server setup (Feb 2026, noted by sandarsh)
- Empty extensionHeaders bug reported by Daiki Matsui (moqtail#147)
Interop
- Registered in interop-runner matrix
- Successfully tested with moq-rs and moxygen (Feb 2026 Boulder hackathon)
- Published namespace, subscribed to tracks, and received objects with both relays
- FETCH working with moxygen
Related
- interop-runner - Automated test framework
- interop-endpoints - Public relay endpoints
- interop-status - Cross-implementation testing