How a subscriber to moq-transport catches up on past data when joining an ongoing live Track.
Current mechanism: fill fetch, shipped in draft-20 (2026-08-31).
Superseded mechanism: Joining FETCH — present through draft-19, removed in draft-20 (PR #1673), along with the “standalone” FETCH moniker.
Spec sections (draft-20): §5.1.3 Fill Semantics, §5.1.3.1 Opening and Closing Fill Fetch Streams, §5.1.6 Joining an Ongoing Track, §10.2.15 FILL_PARAMETERS.
Problem
A subscriber joining a live stream needs to “catch up” — typically fetching the latest keyframe and what follows, so it can start rendering immediately rather than waiting for the next Group boundary.
Mechanism (draft-20, as shipped)
A subscription that carries the FILL_PARAMETERS parameter causes the publisher to open a unidirectional fill fetch stream, beginning with a FETCH_HEADER and delivered as a FETCH response. Objects arriving on it are fill-delivered; objects arriving on the subscription’s own subgroups/datagrams are subscription-delivered.
- Fill range: the Locations selected by the Location filter inside
FILL_PARAMETERS, or the subscription’s own Location filter if that is omitted. It is evaluated with the Fetch rules, so the fill range never extends beyond Largest Object. A zero-length or absent Location filter means the whole track up to Largest Object. The subscriber learns Largest Object from theLARGEST_OBJECTparameter inSUBSCRIBE_OK/REQUEST_UPDATE_OK. - Because the fill range is specified independently of the subscription’s filter, a subscriber can pull a range of past Groups while the subscription itself starts at the Next Group. An empty fill range, or one starting after Largest Object, opens no stream.
- Inheritance: the fill fetch stream inherits the subscription’s subscriber priority, range filters and authorization; parameters inside
FILL_PARAMETERSoverride them for the fill.FILL_TIMEOUTapplies as it does to a FETCH — Objects abandoned when it expires are signalled with End of Timed-Out Range (#1822). - Multiple concurrent fills: the
FETCH_HEADERcarries the Request ID of whatever initiated it (theSUBSCRIBEfor the initial fill, aREQUEST_UPDATEfor a later one), so a subscription can have several fill fetch streams open at once. Opening a new one does not implicitly cancel earlier ones. - Forward State interaction:
FILL_PARAMETERScarried while Forward State is 0 opens no stream, and transitioning to Forward State 1 without re-sending it does not open one either. AREQUEST_UPDATEwithoutFILL_PARAMETERSopens no new fill. - Completion and failure: the publisher FINs the stream when the fill range is fully delivered. There is no
REQUEST_ERRORfor a fill fetch stream — failure is signalled by resetting the stream, and the publisher MUST open the stream and reset it right after theFETCH_HEADERif it has to. A subscriber cancels withSTOP_SENDING. Resetting or cancelling the fill never affects the subscription, which keeps delivering. - Duplicates: where the fill range overlaps the subscription’s Location filter, an Object can be both fill- and subscription-delivered. A subscriber wanting exactly-once delivery uses the Next Object subscription Location Filter plus an open-ended fill range, which the publisher ends at Largest Object. Scheduling between fill-delivered and subscription-delivered Objects is defined by #1673.
The four join patterns (§5.1.6)
| Goal | How |
|---|---|
| Join immediately | SUBSCRIBE with a Location Filter starting at Next Object; delivery begins with the next Object and can begin mid-Group |
| Join at the current Group | Location Filter starting at Next Object + FILL_PARAMETERS whose Location filter has StartGroup=1, filling the current Group from its start |
| Join at a past Group | SUBSCRIBE with FILL_PARAMETERS whose Location filter selects the intended Groups (may be relative); the fill range arrives on the fill fetch stream, live Objects on the subscription |
| Join at the next Group | SUBSCRIBE with a Location Filter starting at Next Group |
Dynamically starting new Groups (§5.1.6.1): a joining subscriber may find it cheaper to ask the Original Publisher to start a new Group than to fill the current one. Publishers advertise this with the DYNAMIC_GROUPS Track Property (Property Type 0x30, §12.6).
Relays (§7): a relay receiving a SUBSCRIBE with FILL_PARAMETERS serves the fill from its cache where it can, and otherwise goes upstream with either a SUBSCRIBE carrying FILL_PARAMETERS or a FETCH.
How it got here (April debate → June consensus → draft-20)
Through mid-April 2026 there were five competing proposals for joining a live stream:
- Joining Fetch (then in draft-17) — fetch historical data alongside a live subscription
- Subscribe Rewind (martin-duke) — draft-duke-moq-subscribe-rewind, a Rewind subscription filter
- Join Subscription Filters (alan-frindell) — filter-based join-point selection (“more of an extension to Martin’s”)
- LargestGroup / CurrentGroup / CurrentGroupFill filters (victor-vasiliev PR #1607, afrind’s CurrentGroupFill, luke-curley’s LargestGroup)
- SWITCH (gwendal-simon PR #1378) — framed as a charter ABR deliverable. See switch-abr.
A REWIND consensus call (chair magnus-westerlund, deadline May 1) closed without a chair conclusion — the outcome was a split. REWIND was then de facto parked: draft-duke-moq-subscribe-rewind stayed frozen at -02, its function folded into fill fetch. PRs #1604 (Joining FETCH on the SUBSCRIBE stream) and #1607 (LargestGroup filter) were both closed June 4 — #1604 lost its rationale once Required Request ID was removed in draft-18 (#1615).
At the London interim (June 11–12) the five-way contest collapsed into two workstreams: fill fetch (this page) and SWITCH_FROM for ABR track switching (switch-abr), with Range Filters (#1765, Mo Zanaty) the filter-dimension wire design. Range Filters landed in draft-19; the fill-fetch replacement — afrind’s #1673, revising #1642 and closing #1023 — landed in draft-20, roughly two and a half months after the consensus.
Victor Vasiliev had argued fill fetch removes Joining FETCH’s race and edge-case hazards; Ali Begen pushed for it to reach Groups beyond just the current one — both are reflected in the shipped design’s independent fill range.
Open points against the shipped text
Cullen Jennings argued for keeping Joining FETCH pending operational experience and flagged three concerns; draft-20 addresses two of them explicitly, so what remains is implementation experience rather than open design:
- Error delivery — answered: no
REQUEST_ERRORexists for a fill; failure is a stream reset after theFETCH_HEADER(§5.1.3.1). - Duplicate objects — answered: overlap is legal and named, with a documented exactly-once recipe (Next Object filter + open-ended fill range).
- Nested
FILL_PARAMETERS—FILL_PARAMETERScarries a sequence of Parameters (#1868) that override the subscription’s for the fill; how deeply that nests is still worth watching.
Also live: vasilvv’s issue #1889 asks the draft to document how the several subscription-pausing mechanisms interact — Range/Location filters, FORWARD-based pausing and subscription state — which now includes the Forward-State rules above.
Related
- joining-fetch-dissent — the April five-way debate, proposal by proposal
- switch-abr —
SWITCH_FROM, the sibling ABR-switching workstream - moq-transport — protocol spec
- publish-subscribe — subscription model
- adaptive-bitrate — ABR implications of join-point selection