Media Over QUIC S. Nandakumar
Internet-Draft Cisco
Intended status: Standards Track C. Jennings
Expires: 1 September 2026 Cisco Systems
28 February 2026
ATOM: AT Protocol Over MoQ Transport
draft-nandakumar-atproto-atom-00
Abstract
This document specifies how the Authenticated Transfer (AT) Protocol
can leverage Media over QUIC Transport (MOQT) for efficient data
synchronization across decentralized social networks. The AT
Protocol's firehose event stream and repository synchronization
mechanisms map naturally to MOQT's publish/subscribe model, enabling
scalable relay infrastructure, priority-based delivery, and improved
resilience for large-scale social data distribution.
This specification addresses the challenges of the current WebSocket-
based transport and demonstrates how MOQT's relay architecture,
group-based caching, and multiplexed streams provide significant
benefits for AT Protocol deployments at scale.
About This Document
This note is to be removed before publishing as an RFC.
The latest revision of this draft can be found at
https://snandaku.github.io/draft-nandakumar-atproto-atom/draft-
nandakumar-atproto-atom.html. Status information for this document
may be found at https://datatracker.ietf.org/doc/draft-nandakumar-
atproto-atom/.
Discussion of this document takes place on the Media Over QUIC
Working Group mailing list (mailto:moq@ietf.org), which is archived
at https://mailarchive.ietf.org/arch/browse/moq/. Subscribe at
https://www.ietf.org/mailman/listinfo/moq/.
Source for this draft and an issue tracker can be found at
https://github.com/snandaku/draft-nandakumar-atproto-atom.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 1 September 2026.
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents
1. Introduction
1.1. Current AT Protocol Architecture
1.2. Requirements Language
2. Challenges with Current Transport
2.1. Scalability Limitations
2.1.1. Connection Overhead
2.1.2. Message Size Constraints
2.1.3. Single-Stream Bottleneck
2.2. Reliability Challenges
2.2.1. Cursor-Based Replay Limitations
2.2.2. No Native Late-Join Support
2.2.3. Connection Fragility
2.3. Operational Challenges
2.3.1. Relay Infrastructure Complexity
2.3.2. Limited Quality of Service
3. MOQT Transport Benefits
3.1. Native Publish/Subscribe Model
3.2. Priority-Based Delivery
3.3. Relay Infrastructure
3.4. Group-Based Organization and Caching
3.4.1. Late-Join via SUBSCRIBE
3.4.2. FETCH for On-Demand Retrieval
3.4.3. Caching Benefits Summary
3.5. QUIC Transport Advantages
4. MOQT Mapping
4.1. Connection Establishment
4.2. Track Types
4.2.1. Firehose Tracks
4.2.2. Repository Sync Tracks
4.2.3. Blob Store Track
4.3. Object Structure
4.4. Subscription and Filtering
4.4.1. Firehose Subscription
4.4.2. Repository Sync
4.4.3. Late-Join and Catch-Up
4.5. Priority and Parallelism
4.6. Relay Aggregation
5. Reliability and Recovery
5.1. Cursor Mapping
5.2. Gap Detection and Recovery
5.2.1. Detecting Missing Objects
5.2.2. Recovery: Fetch Missing Objects
5.2.3. Recovery: Fetch Full Group
5.2.4. Recovery: Full Repository Sync
5.3. Disconnection Handling
5.3.1. Brief Disconnections: 0-RTT Resumption
5.3.2. Extended Disconnections: Cursor-Based Reconnection
5.3.3. Network Transitions: Connection Migration
6. Authentication and Authorization
7. Security Considerations
8. IANA Considerations
9. References
9.1. Normative References
9.2. Informative References
Authors' Addresses
1. Introduction
The Authenticated Transfer (AT) Protocol [AT-ARCH] provides a
framework for decentralized social web applications using self-
certifying data repositories. The protocol enables users to maintain
control over their data while participating in a federated network of
Personal Data Servers (PDS), relays, and application views
(AppViews).
Currently, AT Protocol relies on two primary transport mechanisms for
data synchronization:
* *HTTP*: Used for batch repository exports via CAR (Content
Addressable Archive) files
* *WebSocket*: Used for real-time event streams (firehose) with
CBOR-encoded messages
While functional, these transport mechanisms face significant
challenges at scale, particularly for the firehose event stream that
must distribute updates across a network with millions of users
generating billions of records.
This document defines how Media over QUIC Transport (MOQT)
[MoQ-TRANSPORT] can serve as an enhanced transport for AT Protocol.
MOQT enables low-latency delivery while relay caching supports
multiple latency spectrums from real-time to eventual consistency.
The protocol's native publish/subscribe model, relay infrastructure,
and priority-based delivery address current scalability and
resilience challenges.
1.1. Current AT Protocol Architecture
AT Protocol Network Architecture:
┌─────────────────┐
│ AppView │
│ (Indexer) │
│ │
└────────▲────────┘
│
Firehose (WS)
│
┌────────┴────────┐
│ Relay │
│ (Aggregator) │
└────────▲────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ PDS A │ │ PDS B │ │ PDS C │
│ (Hosts) │ │ (Hosts) │ │ (Hosts) │
│ - User 1 │ │ - User 2 │ │ - User 3 │
│ - User 2 │ │ - User 5 │ │ - User 6 │
└─────────────┘ └─────────────┘ └─────────────┘
The current architecture comprises:
Personal Data Server (PDS): Hosts user accounts and their data
repositories. Each PDS provides a firehose endpoint for real-time
updates and HTTP endpoints for repository exports.
Relay: Aggregates firehose streams from multiple PDS instances into
a unified event stream. Full-network relays attempt to include
all PDS instances in the network.
AppView: Application-specific indexing services that consume the
firehose to build aggregated views (e.g., feeds, search,
analytics).
1.2. Requirements Language
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
2. Challenges with Current Transport
The current WebSocket-based transport for AT Protocol faces several
challenges that impact scalability, reliability, and operational
efficiency.
2.1. Scalability Limitations
2.1.1. Connection Overhead
Each subscriber to a PDS or relay firehose requires a dedicated
WebSocket connection. At network scale, this creates:
* Connection state overhead on servers hosting popular content
* TCP head-of-line blocking affecting all events on a connection
* Limited ability to prioritize critical events during congestion
2.1.2. Message Size Constraints
The current protocol specifies a hard maximum of 5 MBytes per
WebSocket frame. While this accommodates most operations, it creates
challenges for:
* Large repository commits (limited to 2MB blocks, 200 operations)
* Efficient batching of small updates
* Variable-size content distribution
2.1.3. Single-Stream Bottleneck
Current Firehose: Single Stream for All Event Types
WebSocket Connection
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ #commit │ #commit │ #identity │ #commit │ #account │ #commit │
│ (big) │ (small) │ (urgent) │ (med) │ (urgent) │ (big) │
└─────────────────────────────────────────────────────────────────┘
│
▼
Head-of-line blocking:
Urgent #identity event must wait
for large #commit to complete
All event types flow through a single WebSocket stream without
differentiation, meaning:
* High-priority identity changes wait behind large commit events
* Account status updates cannot preempt in-progress transfers
* No mechanism for subscribers to filter by event type at transport
layer
2.2. Reliability Challenges
2.2.1. Cursor-Based Replay Limitations
The current firehose relies on monotonic cursor values for replay
after disconnection. This approach requires consumers to track
cursor state externally, since the protocol provides no mechanism for
server-side cursor persistence. Gap detection depends entirely on
commit chain validation, which is computationally expensive and
requires maintaining local state. When gaps are detected, recovery
requires fetching the complete repository, creating a thundering herd
risk when many consumers reconnect simultaneously after an outage.
2.2.2. No Native Late-Join Support
When a new consumer connects to a firehose, it must either start from
the current position and miss all prior events, or replay from a
cursor to catch up. There is no concept of "recent state" that would
allow quick synchronization to a meaningful starting point.
Consumers cannot receive cached recent events without initiating a
full replay sequence, which increases latency for new subscribers and
places additional load on the server.
2.2.3. Connection Fragility
WebSocket connections over TCP are susceptible to network path
changes that cause connection drops. The protocol provides no
mechanism for connection migration when a client's IP address
changes, such as when moving between networks on a mobile device.
Any network transition requires establishing a completely new
connection and resuming from the last known cursor position.
2.3. Operational Challenges
2.3.1. Relay Infrastructure Complexity
Current relays face significant operational burden in maintaining the
firehose infrastructure. Each relay must establish and maintain
persistent WebSocket connections to all upstream PDS instances it
aggregates, scaling linearly with the number of sources. When
connections fail, relays must handle reconnection logic and cursor
tracking independently for each upstream source. Custom caching and
replay logic must be implemented at the application layer, as the
transport provides no native support for these operations.
Additionally, relays must build proprietary distribution mechanisms
to serve their own downstream subscribers, duplicating effort across
the ecosystem.
2.3.2. Limited Quality of Service
The current transport provides no native mechanism for quality of
service differentiation. All event types receive equal treatment
regardless of their operational importance, so critical account
status changes compete with routine content updates for bandwidth.
Rate limiting based on consumer capacity must be implemented entirely
at the application layer, with no transport-level flow control.
Graceful degradation during overload conditions is difficult to
achieve, often resulting in connection failures rather than
controlled service reduction.
3. MOQT Transport Benefits
MOQT addresses the challenges identified above through its native
architecture designed for large-scale media distribution.
3.1. Native Publish/Subscribe Model
MOQT's publish/subscribe model aligns naturally with AT Protocol's
firehose semantics. Subscribers select specific event tracks of
interest while publishers announce available tracks via
PUBLISH_NAMESPACE. Since relays handle distribution, no dedicated
connection is required per subscriber, and track-level subscription
granularity reduces unnecessary traffic.
PUBLISH_NAMESPACE enables dynamic discovery of available content.
When a PDS comes online, it announces its namespaces to connected
relays, advertising firehose tracks, repository sync tracks, and blob
stores. Relays learn about new PDS instances automatically without
static configuration, enabling the network to scale organically as
new servers join.
SUBSCRIBE_NAMESPACE allows subscribers to discover available tracks
using prefix-based queries. A full-network relay can subscribe to
at/firehose/ to discover all PDS instances publishing firehose
events, then selectively subscribe to each. An AppView can query a
relay's namespace to enumerate available event types before
subscribing to specific tracks of interest. This discovery mechanism
eliminates the need for out-of-band coordination when adding new
publishers or subscribers to the network.
A PDS advertises its available namespaces via PUBLISH_NAMESPACE:
+=============================+===============================+
| Namespace | Description |
+=============================+===============================+
| at/firehose/pds.example.com | Firehose events from this PDS |
+-----------------------------+-------------------------------+
| at/repo/pds.example.com | Repository sync tracks |
+-----------------------------+-------------------------------+
| at/blobs/pds.example.com | Blob storage |
+-----------------------------+-------------------------------+
Table 1
A relay discovering PDS instances issues SUBSCRIBE_NAMESPACE with at/
firehose/ and receives a NAMESPACE response listing all matching
hosts (potentially thousands of PDS instances).
3.2. Priority-Based Delivery
MOQT's 0-255 priority scale enables differentiated event delivery,
ensuring that critical account takedowns (priority 0-15) and urgent
identity changes such as key rotations (priority 16-31) are delivered
ahead of routine commit events (priority 96-191). This prevents
large content transfers from blocking time-sensitive operations.
+=====================+===============+========================+
| AT Event Type | MOQT Priority | Rationale |
+=====================+===============+========================+
| #account (takedown) | 0-15 | Critical - affects |
| | | content availability |
+---------------------+---------------+------------------------+
| #identity | 16-31 | Urgent - key rotation, |
| | | handle changes |
+---------------------+---------------+------------------------+
| #account (status) | 32-63 | Important - account |
| | | state changes |
+---------------------+---------------+------------------------+
| #sync | 64-95 | Moderate - state reset |
| | | events |
+---------------------+---------------+------------------------+
| #commit (small) | 96-127 | Normal - typical |
| | | record operations |
+---------------------+---------------+------------------------+
| #commit (large) | 128-191 | Background - bulk |
| | | content updates |
+---------------------+---------------+------------------------+
| Repository export | 192-255 | Bulk - full sync |
| | | operations |
+---------------------+---------------+------------------------+
Table 2
3.3. Relay Infrastructure
MOQT relays provide purpose-built infrastructure for AT Protocol
distribution. Hierarchical relay topologies reduce origin load by
distributing cached content from regional nodes, while geographic
placement optimizes latency for subscribers. Because the relay
protocol is standardized, operators need not implement custom
distribution logic.
MOQT Relay Network for AT Protocol:
┌─────────────────┐
│ Global Relay │
│ (Federation) │◄─── Cross-region aggregation
└────────┬────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Regional │ │ Regional │ │ Regional │
│ Relay A │ │ Relay B │ │ Relay C │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │ │ │
PDS 1 PDS 2 PDS 3 PDS 4 PDS 5 PDS 6
▲ ▲ ▲ ▲ ▲ ▲
│ │ │ │ │ │
Users Users Users Users Users Users
3.4. Group-Based Organization and Caching
MOQT groups enable efficient caching and late-join support. Late-
joining subscribers receive the most recent group immediately rather
than replaying from the beginning, and relay caches at each tier
reduce upstream load. Group boundaries serve as natural replay
points, with cursor semantics mapping directly to Group ID and Object
ID.
Group Hierarchy: [G0: events 0-99] [G1: events 100-199] ... [GN: live]
↓ ↓ ↓
Relay Cache: cached cached caching
3.4.1. Late-Join via SUBSCRIBE
MOQT's SUBSCRIBE message includes filter parameters that control the
starting position for delivery. As defined in [MoQ-TRANSPORT], these
filters include LatestGroup (start from the newest available group),
LatestObject (start from the most recent object), AbsoluteStart
(begin at a specific group/object position), and AbsoluteRange
(request a bounded range). These filters allow subscribers to join
at any point and then continue receiving live and future content.
SUBSCRIBE delivers content from the specified starting position
forward, keeping subscribers at the live edge as new content arrives.
For historical content retrieval, subscribers use FETCH operations
instead (see Section 3.4.2).
This capability supports several AT Protocol scenarios. A new
subscriber joining a track uses LatestGroup to begin with current
activity.
3.4.2. FETCH for On-Demand Retrieval
MOQT's FETCH operation complements SUBSCRIBE by enabling selective
retrieval of specific objects. While SUBSCRIBE keeps clients at the
live edge, FETCH retrieves historical content regardless of how far
back it exists. FETCH specifies exact group and object ranges,
retrieving precisely the needed data without establishing a
continuous subscription.
When a subscriber detects a gap in received events, it can FETCH the
missing objects directly rather than replaying an entire group. When
verifying a specific record, a client can FETCH just the MST path
blocks needed for cryptographic validation. For deep historical
queries, an analytics service can FETCH specific commit ranges from
months prior.
Relay caching amplifies the benefit of FETCH operations. Popular
content such as viral images, high-profile account commits, and
frequently accessed MST nodes remain in relay cache. Subsequent
FETCH requests for this content are served locally, reducing latency
and eliminating load on origin servers. For a viral post with an
embedded image, thousands of FETCH requests for the image blob
resolve to a single origin fetch followed by cache hits at the relay
tier.
3.4.3. Caching Benefits Summary
The combination of SUBSCRIBE late-join and FETCH with relay caching
provides several benefits for AT Protocol deployments:
* Fan-out efficiency: Origin publishes once, relay serves many
subscribers
* Late-join speed: New subscribers receive cached history
immediately
* Gap recovery: Missing events fetched from relay cache, not origin
* Popular content: High-demand blobs and commits served from cache
* Reduced origin load: Relay tier absorbs read amplification
3.5. QUIC Transport Advantages
Leveraging QUIC [RFC9000] provides connection migration so that
firehose subscriptions survive network changes such as IP address
transitions or WiFi-to-cellular handoffs. Multiplexed streams
eliminate head-of-line blocking between logical channels, while
mandatory TLS 1.3 [RFC8446] ensures built-in encryption. Per-stream
and connection-level flow control prevents subscriber overload, and
0-RTT resumption enables fast reconnection after brief
disconnections.
4. MOQT Mapping
This section defines how AT Protocol data maps to MOQT primitives.
4.1. Connection Establishment
AT Protocol endpoints using MOQT establish connections following the
standard MOQT setup procedure:
AT-over-MOQT Connection Establishment:
PDS/Relay Subscriber
│ │
│◄─── QUIC Connection (ALPN: "moqt") ─────────────────│
│──── QUIC Connection Established ───────────────────▶│
│ │
│◄─── MOQT CLIENT_SETUP ──────────────────────────────│
│ (at-version: 1, supported-events: 0x0F) │
│ │
│──── MOQT SERVER_SETUP ─────────────────────────────▶│
│ (at-version: 1, relay-capabilities: 0x07) │
│ │
│──── PUBLISH_NAMESPACE ─────────────────────────────▶│
│ (at/{pds-host}/firehose) │
│ │
│◄─── SUBSCRIBE_NAMESPACE ────────────────────────────│
│ (at/{pds-host}/firehose) │
│ │
│──── NAMESPACE (tracks available) ──────────────────▶│
│ (commits, identity, account, sync) │
│ │
│◄─── SUBSCRIBE (commits) ────────────────────────────│
│ │
│──── SUBSCRIBE_OK ──────────────────────────────────▶│
│ │
│═════ Firehose Event Stream ════════════════════════▶│
Setup parameters for AT Protocol:
+=====================+============+========+======================+
| Parameter | ID | Type | Description |
+=====================+============+========+======================+
| at-version | 0x41540001 | varint | AT Protocol version |
+---------------------+------------+--------+----------------------+
| at-supported-events | 0x41540002 | varint | Bitmask of supported |
| | | | event types |
+---------------------+------------+--------+----------------------+
| at-relay-caps | 0x41540003 | varint | Relay capability |
| | | | flags |
+---------------------+------------+--------+----------------------+
Table 3
Event type bitmask values: 0x01 (#commit), 0x02 (#identity), 0x04
(#account), 0x08 (#sync).
4.2. Track Types
ATOM defines three track types for different use cases:
4.2.1. Firehose Tracks
Firehose tracks carry real-time event streams from PDS hosts.
Namespace structure: at/firehose/{host}/{event-type} -- {did|all}
+==========+============================+============+==========+
| Track | Namespace | Content | Priority |
+==========+============================+============+==========+
| Commits | at/firehose/{host}/commits | Repository | 96-191 |
| | | updates | |
+----------+----------------------------+------------+----------+
| Identity | at/ | DID/handle | 16-31 |
| | firehose/{host}/identity | changes | |
+----------+----------------------------+------------+----------+
| Account | at/firehose/{host}/account | Hosting | 0-63 |
| | | status | |
+----------+----------------------------+------------+----------+
| Sync | at/firehose/{host}/sync | State | 64-95 |
| | | assertions | |
+----------+----------------------------+------------+----------+
Table 4
Groups organize events by sequence number (e.g., 1000 events per
group). Track name is either a specific DID or "all" for aggregated
streams.
4.2.2. Repository Sync Tracks
Repository sync tracks provide full block-level repository data.
Namespace: at/repo/{host}/{did}/sync
The MOQT hierarchy maps to AT Protocol repository concepts:
+============+=======================+=========================+
| MOQT Level | AT Protocol Concept | Purpose |
+============+=======================+=========================+
| Track | Repository (DID) | Subscription unit |
+------------+-----------------------+-------------------------+
| Group | Commit/Revision | Temporal progression |
+------------+-----------------------+-------------------------+
| Subgroup | Collection + MST path | Structural organization |
+------------+-----------------------+-------------------------+
| Object | Record/Block | Individual data items |
+------------+-----------------------+-------------------------+
Table 5
Each group represents a commit. Subgroup 0 contains the signed
commit and MST structure; subsequent subgroups contain collections
with MST proof paths for independent verification.
+==========+===============================================+
| Subgroup | Contents |
+==========+===============================================+
| 0 | Commit block + full MST (verification anchor) |
+----------+-----------------------------------------------+
| 1+ | Collection records + MST proof path |
+----------+-----------------------------------------------+
Table 6
Objects within a group are ordered: signed commit (ObjectID 0), MST
root, MST intermediate nodes, then records. The at-block-cid
extension header carries the CID for integrity verification.
MST Structure and MOQT Mapping:
Repository (DID: did:plc:abc123)
│
├── Commit (rev: 3kf7x2...) ──────────────▶ Group N
│ │
│ ├── Signed Commit Block ──────────────▶ Subgroup 0, Object 0
│ │
│ └── MST (Merkle Search Tree)
│ │
│ ├── Root Node (CID: bafyr...)──────────────▶ Subgroup 0, Object 1
│ │ ├── key: "app.bsky.feed.post/3k..."
│ │ └── children: [L, R]
│ │
│ ├── Left Node ───────────────▶ Subgroup 0, Object 2
│ │ └── key: "app.bsky.actor.profile/self"
│ │
│ └── Right Node ───────────────▶ Subgroup 0, Object 3
│ └── key: "app.bsky.graph.follow/3k..."
│
├── Collection: app.bsky.feed.post ──────────────▶ Subgroup 1
│ ├── Record 3k7abc... + MST proof ──────────────▶ Object 0
│ └── Record 3k7def... + MST proof ──────────────▶ Object 1
│
├── Collection: app.bsky.actor.profile ────────────▶ Subgroup 2
│ └── Record self + MST proof ──────────────▶ Object 0
│
└── Collection: app.bsky.graph.follow ─────────────▶ Subgroup 3
└── Record 3k9xyz... + MST proof ──────────────▶ Object 0
The MST proof path included with each record contains the minimal set
of tree nodes required to verify that record's inclusion in the
commit. This enables independent verification of individual records
without downloading the entire repository.
4.2.3. Blob Store Track
Blob store tracks enable cross-repository deduplication of large
media.
Namespace: at/blobs/{host}
The Group ID is derived from the CID (first 8 bytes of multihash as
uint64), Object ID is always 0. This deterministic mapping ensures
identical blobs from different repositories resolve to the same MOQT
location.
4.3. Object Structure
AT Protocol events are encapsulated in MOQT objects:
MOQT Object Structure:
┌─────────────────────────────────────────────────────────────┐
│ Extension Headers: │
│ at-event-type (0x41544501): varint │
│ at-repo-did (0x41544502): string │
│ at-repo-rev (0x41544503): string (TID) │
│ at-seq (0x41544504): varint (cursor equivalent) │
│ at-block-cid (0x41544505): bytes (for repo sync blocks) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Payload: CBOR-encoded event (compatible with AT-REPO) │
└─────────────────────────────────────────────────────────────┘
4.4. Subscription and Filtering
4.4.1. Firehose Subscription
Subscribers specify start position and filtering:
* StartGroup=Latest: Begin with live events (default)
* StartGroup=N: Resume from specific cursor position
* Track name all or specific DID for filtering
4.4.2. Repository Sync
Subgroup filtering enables selective synchronization:
Selective Sync Examples:
Full repository: SubgroupFilter: [0, 1, 2, 3, ...]
Posts only: SubgroupFilter: [0, 1] (~15% bandwidth)
Verification only: SubgroupFilter: [0] (~2% bandwidth)
Temporal navigation with groups:
* Subscribe StartGroup=LATEST: Current state + live updates
* Fetch StartGroup=N, EndGroup=M: Historical range retrieval
4.4.3. Late-Join and Catch-Up
New subscribers request StartGroup=LATEST to receive current state
immediately. After disconnection, subscribers use Fetch with their
last known group to retrieve missed commits before resuming live
subscription.
4.5. Priority and Parallelism
MOQT priority enables efficient delivery ordering:
+==================+==========+=============================+
| Block Type | Priority | Rationale |
+==================+==========+=============================+
| Account takedown | 0-15 | Safety-critical |
+------------------+----------+-----------------------------+
| Identity changes | 16-31 | Affects routing |
+------------------+----------+-----------------------------+
| Signed Commit | 0-15 | Required for verification |
+------------------+----------+-----------------------------+
| MST Root | 16-31 | Unlocks tree traversal |
+------------------+----------+-----------------------------+
| MST Nodes | 32-63 | Enables record verification |
+------------------+----------+-----------------------------+
| Small Records | 64-127 | Core content |
+------------------+----------+-----------------------------+
| Large Records | 128-191 | Less urgent |
+------------------+----------+-----------------------------+
| Blobs | 192-255 | Media, lazy-loadable |
+------------------+----------+-----------------------------+
Table 7
Content-addressable blocks enable parallel fetching across QUIC
streams, with total transfer time bounded by the slowest stream
rather than the sum of all transfers.
4.6. Relay Aggregation
MOQT relays aggregate firehose streams from multiple upstream
sources:
Relay Aggregation:
Full-Network Relay
┌────────────────────┐
│ at/firehose/ │
│ relay.network/* │
└─────────▲──────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ Regional │ │ Regional │ │ Regional │
│ Relay │ │ Relay │ │ Relay │
└──────▲──────┘ └──────▲──────┘ └──────▲──────┘
│ │ │
PDS hosts PDS hosts PDS hosts
Relays perform subscription aggregation, namespace republishing,
event caching for late-join, and deduplication.
5. Reliability and Recovery
ATOM leverages MOQT's group-based delivery model and QUIC's transport
features to provide robust reliability mechanisms for AT Protocol
data synchronization. The key capabilities include cursor mapping
that translates AT Protocol sequence numbers to MOQT group/object
positions, gap detection that identifies missing events through
sequential object tracking, and multiple recovery strategies ranging
from targeted object fetches to full repository synchronization.
QUIC's connection migration further ensures that subscribers maintain
continuous delivery even when network conditions change.
5.1. Cursor Mapping
AT Protocol cursors map to MOQT group and object identifiers,
enabling seamless translation between the existing cursor-based
replay mechanism and MOQT's hierarchical addressing. Each firehose
track maintains a mapping table that records the sequence number base
for each group, allowing bidirectional conversion between AT Protocol
cursors and MOQT positions.
When a subscriber needs to resume from a specific cursor position, it
converts the cursor value to the corresponding group and object
identifiers. The conversion uses integer division to determine the
group number and the modulo operation to determine the object offset
within that group. This deterministic mapping ensures that any
cursor value can be precisely located within the MOQT track
structure.
Cursor Translation:
AT Cursor (seq: 12345678)
│
▼
┌────────────────────────────────────────┐
│ Cursor Mapping Table (per track) │
│ │
│ seq_base: 12340000 │
│ group_size: 1000 │
│ │
│ seq 12345678 │
│ = seq_base + (group * group_size) │
│ + object │
│ = 12340000 + (5 * 1000) + 678 │
│ │
│ MOQT: Group 5, Object 678 │
└────────────────────────────────────────┘
Publishers MUST include the at-seq extension header in each object to
enable accurate cursor reconstruction.
5.2. Gap Detection and Recovery
MOQT's group-based delivery model simplifies gap detection compared
to the current cursor-only approach. This section describes how gaps
are detected and the recovery strategies available to subscribers.
5.2.1. Detecting Missing Objects
Because objects within a group are sequentially numbered and groups
themselves are ordered, subscribers can immediately identify when
expected objects are missing by comparing received object identifiers
against their expected sequence.
Gap Detection:
Subscriber State:
Last received: Group 5, Object 999
Expected next: Group 6, Object 0
Incoming object: Group 6, Object 5
Expected Received
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ G6, O0 │ ← Missing! → │ G6, O5 │
└─────────┘ └─────────┘
│
▼
Gap detected: Objects 0-4 missing from Group 6
5.2.2. Recovery: Fetch Missing Objects
The preferred recovery approach is to fetch only the specific missing
objects using MOQT's FETCH operation with precise group and object
boundaries. If relay caches contain the missing data, recovery
completes without any load on the origin server.
Fetch Missing Objects:
Subscriber Relay Origin
│ │ │
│── FETCH ────────────────────────▶│ │
│ StartGroup=6, StartObject=0 │ │
│ EndGroup=6, EndObject=4 │ │
│ │ │
│ [Cache hit?] │
│ │ Yes │
│◄── Objects 0-4 ──────────────┘ │
│ (from cache) │
│ │
│ Gap filled, resume live stream │
5.2.3. Recovery: Fetch Full Group
For larger gaps spanning multiple groups, subscribers may request
entire groups rather than specifying individual object ranges. This
approach is simpler but may retrieve more data than strictly
necessary.
Fetch Full Group:
Subscriber Relay Origin
│ │ │
│ [Gap spans Groups 6-8] │ │
│ │ │
│── FETCH ────────────────────────▶│ │
│ StartGroup=6, EndGroup=8 │ │
│ │ │
│ [Partial cache] │
│◄── Group 6 (cached) ─────────────┤ │
│◄── Group 7 (cached) ─────────────┤ │
│ │── FETCH ──────────────▶│
│ │ (Group 8) │
│ │◄── Group 8 ────────────│
│◄── Group 8 ──────────────────────┤ │
│ │
│ All groups received, resume live stream │
5.2.4. Recovery: Full Repository Sync
As a fallback when cached data is unavailable or gaps are too
extensive, subscribers can perform a full repository synchronization
using either HTTP CAR exports or the MOQT repository sync track.
This approach validates the entire repository state against a #sync
event.
Full Repository Sync:
Subscriber PDS/Relay
│ │
│ [Gap too large or cache miss] │
│ │
│── GET /xrpc/com.atproto.sync. ──▶│
│ getRepo?did=... │
│ │
│◄── CAR file ─────────────────────│
│ (complete repository export) │
│ │
│ [Validate against #sync event] │
│ │
│ 1. Parse CAR blocks │
│ 2. Verify MST root matches │
│ 3. Update local state │
│ 4. Resume live subscription │
5.3. Disconnection Handling
MOQT over QUIC provides superior disconnection handling through three
complementary mechanisms: 0-RTT session resumption, cursor-based
reconnection, and transparent connection migration.
5.3.1. Brief Disconnections: 0-RTT Resumption
For brief disconnections (typically under 30 seconds), QUIC's 0-RTT
resumption allows subscribers to restore their session with minimal
latency. The subscriber presents a session ticket from the previous
connection, and the relay resumes delivery from where it left off if
the cached session state remains valid. This typically completes in
a single round trip.
QUIC 0-RTT Resumption:
Subscriber Relay
│ │
│ [Connection lost briefly] │
│ │
│ [Reconnecting with session ticket] │
│ │
│── QUIC 0-RTT ────────────────────────▶│
│ ClientHello + session ticket │
│ + early data (SUBSCRIBE) │
│ │
│◄── ServerHello + Finished ────────────│
│ │
│◄── Continue from last position ───────│
│ (relay cached subscriber state) │
│ │
│══ Resume live stream (minimal gap) ══▶│
5.3.2. Extended Disconnections: Cursor-Based Reconnection
For extended disconnections where session state has expired,
subscribers perform a full reconnection using their saved cursor
position. The subscriber first uses FETCH to retrieve any missed
events from their last known position, then establishes a new
SUBSCRIBE starting from the latest group to receive live updates.
Relay caches serve the historical data when available, minimizing
load on upstream servers.
Full Reconnection with Cursor:
Subscriber Relay
│ │
│ [Disconnected for extended period] │
│ [Saved state: at-seq = 12345678] │
│ │
│── QUIC Handshake (full) ─────────────▶│
│◄── Connection Established ────────────│
│ │
│── CLIENT_SETUP ──────────────────────▶│
│◄── SERVER_SETUP ──────────────────────│
│ │
│ [Convert cursor to Group/Object] │
│ seq 12345678 → Group 5, Object 678 │
│ │
│── FETCH ─────────────────────────────▶│
│ StartGroup=5, StartObject=678 │
│ EndGroup=LATEST │
│ │
│◄── Historical objects (cached) ───────│
│ │
│── SUBSCRIBE ─────────────────────────▶│
│ StartGroup=LATEST │
│◄── SUBSCRIBE_OK ──────────────────────│
│ │
│══ Live stream resumes ═══════════════▶│
5.3.3. Network Transitions: Connection Migration
For network transitions such as WiFi-to-cellular handoffs, QUIC's
connection migration enables seamless continuation without any
application-layer intervention. The subscriber's IP address changes
transparently while the MOQT session continues uninterrupted,
ensuring no gaps in the event stream during mobile network
transitions.
QUIC Connection Migration:
Subscriber (mobile) Relay
│ │
│══ Streaming on WiFi ═════════════════▶│
│ (IP: 192.168.1.50) │
│ │
│ [User moves, WiFi signal lost] │
│ [Device switches to cellular] │
│ [New IP: 10.0.0.75] │
│ │
│── QUIC PATH_CHALLENGE ───────────────▶│
│ (from new IP address) │
│ │
│◄── QUIC PATH_RESPONSE ────────────────│
│ (path validated) │
│ │
│══ Continue streaming on cellular ════▶│
│ (no gap, no reconnection needed) │
│ │
│ [Application layer unaware of │
│ network transition] │
6. Authentication and Authorization
TODO
7. Security Considerations
TODO
8. IANA Considerations
TODO
9. References
9.1. Normative References
[AT-ARCH] Newbold, B. and D. Holmgren, "Authenticated Transfer (AT)
Protocol Architecture", Work in Progress, Internet-Draft,
draft-newbold-at-architecture, 2025,
.
[AT-REPO] Holmgren, D. and B. Newbold, "Authenticated Transfer (AT)
Repository and Synchronization", Work in Progress,
Internet-Draft, draft-holmgren-at-repository, 2025,
.
[MoQ-TRANSPORT]
Curley, L., Pugin, K., Nandakumar, S., Vasiliev, V., and
I. Swett, "Media over QUIC Transport", Work in Progress,
Internet-Draft, draft-ietf-moq-transport-16, January 2026,
.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, .
[RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
.
[RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based
Multiplexed and Secure Transport", RFC 9000,
DOI 10.17487/RFC9000, May 2021,
.
9.2. Informative References
[MoQ-C4M] Jennings, S., "Common Access Token for Media over QUIC",
Work in Progress, Internet-Draft, draft-ietf-moq-c4m,
2025,
.
[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext
Transfer Protocol Version 2 (HTTP/2)", RFC 7540,
DOI 10.17487/RFC7540, May 2015,
.
[RFC8949] Bormann, C. and P. Hoffman, "Concise Binary Object
Representation (CBOR)", STD 94, RFC 8949,
DOI 10.17487/RFC8949, December 2020,
.
[WebTransport]
Vasiliev, V., "The WebTransport Protocol Framework",
RFC 9297, August 2023,
.
Authors' Addresses
Suhas Nandakumar
Cisco
Email: snandaku@cisco.com
Cullen Jennings
Cisco Systems
Email: fluffy@cisco.com