AT Protocol: the Federated Social Protocol Behind Bluesky
Behind the Bluesky app sits a protocol layer designed to stand on its own. The AT Protocol (Authenticated Transfer Protocol) is built around two core commitments, **account portability** and **application-level decentralization**, realized through signed repositories built on Merkle Search Trees, DID-based identity, and a set of infrastructure roles that are deliberately kept separate. Here is how the design works, and the challenges its real-world operation runs into.
What AT Protocol is: account portability and application-level decentralization
The AT Protocol (Authenticated Transfer Protocol) traces its roots to a decentralized-social-networking research project inside Twitter, and has been developed since 2021 by the independent organization Bluesky PBC. The Bluesky app is just one client built on top of this protocol; the protocol itself is designed to be usable by other applications as well. Two ideas sit at the center of its design. Account portability means a user is not technically locked into a single hosting provider and can move to a different server while keeping their followers and post history. Application-level decentralization means multiple independent applications (timeline apps, custom feeds, moderation tools) can coexist and compete on top of the same underlying data. Like federated architectures generally, AT Protocol pursues the goal that no single company can shut down the whole network, and these two ideas are how it tries to get there.
Identity: DIDs and DNS-based handles
Every AT Protocol user has a DID (Decentralized Identifier), a persistent, cryptographically verifiable identifier. Bluesky's default DID method is did:plc, backed by an append-only, auditable directory service (the PLC Directory) run by Bluesky PBC that keeps the update history of each DID document, including the signing key and the current PDS location. Anyone who wants to self-host that directory function can instead use did:web, which places the DID document under their own domain. Since raw DIDs are unwieldy, each one is paired with a human-readable handle (e.g. @alice.example.com). A handle is a domain name or subdomain, and domain ownership (which establishes the handle-to-DID mapping) is proven via a DNS TXT record (_atproto.<domain>) or a .well-known file at the domain root. This separates "which PDS you live on" from "who you are," and reuses the DNS system as an existing, battle-tested root of trust. See DIDs in depth for more.
The repository: a signed Merkle Search Tree
Each user's data (posts, likes, follows, profile) is stored as records in that user's own signed repository. Records are organized into collections named by Lexicon schema (e.g. app.bsky.feed.post), and the whole repository is stored inside a Merkle Search Tree (MST), the structure covered in the MST section of Merkle trees in depth. Every time a user adds, updates, or deletes a record, a new MST root hash is computed, and a commit containing that root is signed with the user's signing key. This lets anyone issue a lightweight proof that a given record really does exist in a user's repository, and lets relays synchronize only the differing subtrees between repository versions, precisely the replica-synchronization problem MSTs were designed to solve. A separate, more privileged rotation key handles updates to the DID document itself: rotating the signing key, or changing which PDS the account points to. This protects the account even if the signing key is compromised or there is a dispute with a PDS provider.
The infrastructure behind the network: PDS, Relay, AppView, Feed Generator, Labeler
Rather than one server doing everything, AT Protocol splits functionality across several components with distinct roles. This split is the technical foundation that makes application-level decentralization possible at all.
- PDS (Personal Data Server)
- The server that actually hosts a user's repository, handling authentication and reads/writes of records. It can be a Bluesky-operated PDS or a self-hosted one.
- Relay (firehose)
- Crawls and subscribes to many PDSs, aggregating repository update events from across the whole network into a single stream (the firehose, via
subscribeRepos) and rebroadcasting it. Bluesky PBC operates a large default relay. - AppView
- Consumes the firehose and aggregates/indexes data for a specific application, building the social graph, generating timelines, and producing notifications.
- Feed Generator
- A small service, independent of the AppView, that implements a custom feed algorithm. It returns only a list of post URIs (a "skeleton"); the AppView hydrates them into full content.
- Labeler
- A service, also independent of the AppView, that attaches moderation labels to content or accounts. Users can subscribe to multiple labelers of their own choosing.
It is easy to misread the fact that repositories get copied out to many Relays and AppViews as meaning the data itself is (in principle) distributed. It is not. The single source of truth remains the user's signed repository on their PDS; what a Relay or AppView holds is only a copy or index received off the firehose. If a PDS deletes a record, that deletion propagates through the firehose, and downstream copies are expected to follow. This "one canonical location" design also does useful work in pinning down legal responsibility for illegal content: most jurisdictions require the hosting party to remove unlawful data, and under AT Protocol that responsibility falls on whoever operates the PDS holding the canonical copy.
Interactions between these components are strictly typed via Lexicon, a schema definition language. Lexicon namespaces each record type and API endpoint using reverse-DNS-style NSIDs (e.g. app.bsky.feed.post), and from those schemas comes XRPC, a simple HTTP-based RPC convention (queries as GET, procedures as POST). As long as independently written PDSs, AppViews, and clients all honor the shared "contract" defined by Lexicon, they can interoperate, which is the point of this separation.
The design philosophy in practice, and what still remains unresolved
This division of roles backs up two philosophical claims. One is algorithmic choice: the protocol itself does not dictate how a timeline is ordered; users can pick and subscribe to whichever Feed Generator they like. The other is stackable moderation: judgments about what counts as inappropriate are not monopolized by a single operator, but instead each user can combine labels from multiple independent Labelers according to their own preferences. Both are only possible because these functions were pulled out of the protocol core.
- Skewed Relay/AppView operating costs: because the firehose carries updates for the entire network, the bandwidth, storage, and compute it demands are substantial. In practice, most traffic ends up flowing through the default Relay and AppView operated by Bluesky PBC, leading to criticism that a protocol billed as "federated" is, in reality, close to centralized. Self-hosting a PDS has gotten relatively easy, but few operators run an independent Relay or AppView.
- Federation in practice is still immature: a world of multiple independent, competing AppViews is discussed as an aspiration, but today the AppView in wide use is essentially the one Bluesky PBC provides.
- No direct interoperability with ActivityPub: because the data model and protocol differ from ActivityPub, Bluesky cannot federate directly with the Mastodon-based Fediverse. Bridging services such as Bridgy Fed translate and relay messages between the two, giving limited cross-network interaction. See ActivityPub in depth for more.
That said, concerns about centralization are not the whole story. In April 2026, Bluesky PBC's servers were knocked offline for over ten hours by a DDoS attack, and the incident made a real-world case that the official app going down and the protocol going down are two different things. While Bluesky's own infrastructure was unreachable, compatible networks running their own Relays and AppViews, such as Blacksky and Eurosky, kept running unaffected and reportedly absorbed a wave of users with nowhere else to go. The episode highlighted an asymmetry in how AT Protocol's decentralization plays out layer by layer: a PDS is light enough that an individual can run one, while a Relay or AppView demands enough operational capacity that it tends to concentrate.
These traits come into sharper focus next to other protocols pursuing similar decentralization goals.
| Aspect | ActivityPub | AT Protocol | Nostr |
|---|---|---|---|
| Identity | A URI tied to an actor name and instance domain (e.g. @user@instance.tld) | A DID (did:plc/did:web) kept separate from a DNS-based handle | A public key (npub) that is itself the identity, with no server binding at all |
| Where data lives | The home instance holds the data and delivers it via inbox/outbox | A signed repository (MST) hosted on a PDS, but decoupled from the DID (the PDS alone is canonical; Relays/AppViews hold indexed copies) | Signed events broadcast redundantly to multiple relays, with no single canonical store |
| Account portability | Moving instances typically means limited carry-over of followers and history | Because the DID and handle are independent of hosting, moving PDS is designed to preserve data and relationships | The keypair itself is the identity, so "moving" is just publishing to a different set of relays |
| Discovery and delivery | Push-based federation via server-to-server inbox delivery | A Relay (firehose) aggregates all updates, and AppViews reassemble them per application | Pull-based: clients connect to and subscribe from multiple relays individually |
| Moderation | Centered on instance-admin blocking and defederation | Stackable moderation via Labelers, individually subscribable per user | Mostly client-side filtering and relay-level blocklists, with little built into the protocol itself |
Related pages
AT Protocol shows up repeatedly as an applied example of the other technologies covered on this site. The Merkle Search Tree that underlies repository integrity is detailed in Merkle trees in depth; the general idea of multiple operators cooperating to run a network is covered in federated architectures; protocols pursuing similar goals via different designs are covered in ActivityPub in depth and Nostr in depth; and the identity technology underneath it all is explored in DIDs in depth.