> **Nostr Agent Onboarding** · [start here](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/start.md) · [index](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/llms.txt) · source: `Nostr-exp/core/02-how-it-should-work.md` · snapshot 2026-10-10

# How Nostr should work

> Part 2 of the core synthesis: the *intended* network architecture — what
> keeps Nostr decentralized when it is used correctly, and what quietly
> re-centralizes it when it isn't. Sources: *Building Nostr* ch. 4, NIP-65,
> fiatjaf's "A vision for content discovery" ([`../sources/fiatjaf-vision.md`](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/docs/sources/fiatjaf-vision.md)),
> the Outbox literature ([`../sources/outbox-model.md`](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/docs/sources/outbox-model.md)), OpenSats client report
> ([`../sources/opensats-advancements.md`](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/docs/sources/opensats-advancements.md)).

## The routing problem is the real problem

Signatures make events valid anywhere; they do not make events *findable*
anywhere. Decentralization therefore stands or falls on the **routing
problem**:

1. Where should a given event be **sent**?
2. Where should a given query be **asked**?

Get this wrong in either of the two obvious ways and the network degrades:

- **Naïve replication** ("blast everything to every relay"): every relay must
  store everything, small relays become impossible, and the network collapses
  into a few mega-relays. That is redundant vertical scaling, not
  decentralization.
- **Fixed relay lists** ("just use these 5 popular relays"): the popular
  relays become de facto platforms. If they drop you, your followers cannot
  find you, and the censorship-resistance story is over.

This is not hypothetical. fiatjaf's 2024 experiment ("Nostr is not
decentralized nor censorship-resistant") published two identical notes — one
to three popular relays, one only to his own relay, announced exactly where
clients are supposed to look (his NIP-05 and NIP-65 lists). Engagement on the
second was a fraction of the first, which "shouldn't have happened at all" if
clients followed *people* rather than relays. His verdict: "Nostr today is
indeed centralized" — and the failure lives in clients that hardcode relay
sets, not in the protocol. Censorship-resistance is an **emergent property of
clients doing discovery properly**, or it does not exist. The same essay's
flip side ("Nostr is pro-censorship"): every relay is private property, free
to reject anything for any reason; the network resists censorship precisely
because censorship is everywhere permitted and nowhere decisive — *provided*
readers can look elsewhere, which is the client's job to make real.

The correct answer is **intelligent, per-event relay selection** — routing
*heuristics*, agreed on by convention so that writers and readers can predict
each other. Think of each heuristic as a database index: it connects a query
someone will plausibly run with the place matching events are stored.
Heuristics are additive — publish to every location a legitimate reader would
look, and *only* those (access control is precisely the deliberate omission of
a heuristic).

## The outbox model — the paradigm heuristic

NIP-65: each user publishes a **kind 10002 relay list** declaring where they
write. The two flags:

| Flag | Name | Meaning |
|---|---|---|
| `write` | **OUTBOX** | where this user publishes their public content |
| `read` | **INBOX** | where this user expects to receive mentions and DMs |

The rules that fall out:

- To read someone's posts → query 2–3 of their **outbox** relays.
- To publish your own post → your **outbox** + the **inbox** of everyone you
  `p`-tagged.
- To send a DM → recipient's **inbox** (NIP-17 uses a dedicated kind 10050
  DM inbox), plus your own for the record.
- Cold start / unknown user → indexer + general relays, then upgrade to their
  outbox once you've seen their 10002.

With outbox, each author is sovereign over their own distribution: routing is
declared by the *author*, not chosen by the platform. This is why the
literature is unanimous that **outbox is no longer optional for a serious
general-purpose client** (OpenSats report; Amethyst talks to ~1,000 relays
from a phone; the point is a flat traffic profile across many small relays
instead of ten hubs).

**Gossip** (Mike Dilger) is the superset in practice: outbox plus every other
discoverable hint — relay hints in `e`/`p`/`a` tags, `nprofile`/`nevent`
URIs, NIP-05 metadata, observed author presence. Use every signal you can get.
fiatjaf is emphatic that reducing discovery to NIP-65 alone is "too
restrictive," and that dropping per-event relay hints (as Coracle once
proposed) is "a catastrophic idea": hints are what keep community-relay
posts, conference relays, topical relays, archive relays, and even a
fully-banned "Alex Jones" — whose kind 10002 no indexer will carry —
reachable via nothing but an nprofile on a business card. Resilience comes
from *deliberately mixing many mechanisms*, manual user action included.

## Outbox is one heuristic, not the routing model

The most common architectural mistake after "ignore routing entirely" is
"pretend NIP-65 covers everything." It covers exactly one case:
author-addressed public social content. Other cases have their own
heuristics, and a NIP that defines a new kind **without defining its relay
selection is an incomplete spec**:

| Content | Route by | Mechanism |
|---|---|---|
| Public notes, articles, profiles | author | outbox (kind 10002) |
| Mentions, replies | mentioned users | inbox (kind 10002 / 10050) |
| DMs (NIP-17/44/59) | recipient | DM inbox only — *never* outbox |
| Community / group content (NIP-29, NIP-72) | the community | the group's declared relay(s) only; leaking to outbox violates the access model |
| Topical / curated feeds | topic | topic relays, relay-advertised interest (NIP-66 kind 30166 recommendations) |
| Search / aggregate | nobody | indexer relays, an explicit trade of centralization for capability |
| Zap receipts | zap *request* author | their outbox (the wallet acts on the sender's behalf) |
| Git / repo events (NIP-34) | the repo | repo's declared GRASP relays, then author outbox |
| Service RPC (NIP-46/47/90) | the service | the relay(s) the service advertises |

Publishing means applying **all** applicable heuristics for the readers you
intend, and none for the readers you don't.

## Bootstrapping, hints, and healing

**Bootstrapping.** Kind 10002 tells you where a user's content lives — but
where do the 10002s live? You have to start somewhere: hard-coded
indexer/default relays in the client (swappable, and honest about being a
compromise), purpose-built profile indexes, and eventually perhaps a DHT.
Bootstrapping is a *trust* problem as much as a network problem: relay
recommendations (NIP-66) are only as good as the web of trust you filter them
through.

**Relay hints.** Tags that reference events carry optional relay URLs (and
pubkey hints, which are more durable — a pubkey leads to an outbox even after
relays rot). Hints are the fallback when heuristics fail — and they have a
second, adversarial function: a hint baked into a signed event cannot be
stripped without breaking the signature, so even censorious relays end up
advertising where the censored content lives. Hints force federation and let
clients route around damage.

**Migration.** Relay selections change; signed data makes the fix trivial in
principle — copy the events — but somebody has to do it, and the rule for who
is: **the person who wants the event findable in a place is responsible for
putting it there.** Change your outbox → re-publish your content to the new
relay, or your 10002 becomes a lie ("Alice said her notes are on relay B;
they weren't"). Group moves relay → the admin syncs. New indexer →
its operator scrapes. Negentropy (NIP-77 set reconciliation) makes this cheap.
Most clients still don't do it; a complete client must.

**Proxies and the super-peer curse.** Read/write proxies that do relay
selection *for* the client break at the edges: NIP-42 AUTH deliberately
cannot be proxied, and the client-side context that drives selection (group
membership, user intent) never reaches the proxy. Multiplexers that carry
explicit client-side selections in a wrapper protocol are fine; opaque
"smart" proxies re-create the platform. fiatjaf generalizes this into the
**super-peer curse**: any trusted machine that hands clients "massaged,
sorted, filtered, ordered data" — Bluesky's app views, Farcaster hubs,
p2panda's Aquadoggo, and the aggregator/proxy experiments inside Nostr itself
— means the users behind it "will be controlled, censored, mislead and
tricked." If that architecture came to dominate Nostr he "would immediately
declare Nostr a failed experiment." The legitimate home for that power is the
relay layer itself — curation relays, WoT relays, search relays, AI-feed
relays — chosen by the user, never interposed between follower and followed.

## Relays are services, not infrastructure

The healthy end-state is not ten thousand identical relays; it is a market of
*differentiated* relays: community homes, paid indexes, curated topic feeds,
DM mailboxes, archives, algorithm relays that answer a query with a
recommendation feed. NIP-43/86 (membership lists, management API — the
Coracle line of work) formalize this: a relay may state who it serves and
what its policy is, and clients should honor that.

Constant's framing sharpens the point: "The point of Nostr was never to get
rid of servers; the point of Nostr is to be free again to leverage them for
what they are good for… It frees servers, just as much as it did the users."
Use relays for what servers are good at — **curation and ordering**: relay
feeds as a first-class client feature (fiatjaf pushes the same thing —
favorite a curated relay *as a feed*, don't add it to your read list),
NIP-29 rooms, curated topic relays. "Dumb relay" refers only to the
standardized query interface; within accept/store/serve, a relay is in full
control and free to be as smart as it likes.

Two corollaries:

- **Expose relays to users.** Per-note relay selection, visible relay
  provenance, user-editable selections. A client that hides relays "for UX"
  is quietly re-centralizing; making relays *legible* is what makes the user
  sovereign. (Coracle's per-note relay selection is the reference.)
- **Relays need business models.** A relay that is indistinguishable from its
  neighbors can only be a subsidized commodity, and subsidized commodity
  infrastructure is how we got the old internet. Distinct services can charge —
  and users choosing whom they do business with is the alignment mechanism.

## Spam is a routing problem too

fiatjaf's mature position ("The only solution to Nostr spam," 2025): spam is
solved at the **relay layer**, by construction, not by client-side cleverness.

- Main feeds have no spam problem: you read people you follow, from relays
  you chose.
- Inbox spam: query `#p` mentions **only from the user's declared read
  relays** — and choose read relays that actually filter (WoT-gated,
  NIP-05-gated, PoW, paid). Filtered public inbox relays should be client
  defaults so newcomers never see spam.
- Other people's threads: replies are fetched from *the author's* read
  relays; a spam-flooded thread "is their fault for not picking 'read'
  relays correctly" — hygiene is per-user, socially correctable, and the
  incentive lands on the right person.
- Why not client-side WoT/mutes as the primary defense: content must be
  downloaded before it can be filtered (at scale that's the bandwidth of all
  spam, and a 500-reply flood starves naive queries); mutes can't beat
  infinite fresh keys; and purely local filtering is a tragedy of the
  commons. Client-side trust scoring remains useful as a *secondary* layer —
  ranking, impersonation warnings, zap-feed dampening — not as the wall.

## No global view — and that's the design

There is no "the network." Nostr is partition-tolerant to its core: you can
fetch any subset of events from any subset of relays, and you will never know
whether you have "all" of anything. Every alternative that promises a global
view (Bluesky's firehose being the clearest case) pays for it with a
centralized chokepoint.

*Building Nostr* names the positive version of this **digital localism**: the
network topology is allowed to align with the social graph. Clusters overlap
relays; relays serve clusters; not all parts of the network need to be
connected for each part to be whole. Discovery bootstraps from "many
different hackish attempts" (fiatjaf) — replies you happen to see, hints,
NIP-05 addresses, invite links — and that friction is not a bug to engineer
away with a global index; it is what a captureless network feels like.

The No Solutions podcast crew states the same law from the builder's side:
global view counts, global usernames, guaranteed deletion, consistent group
state — "everything else is a lie… if you want a global view you need to
rebuild Bitcoin" (Gigi). Their predicted eternal-September failure mode:
newcomers "building REST APIs that give you global feeds." Don't be the
REST API.

## The local relay: partition tolerance as a feature

The strongest positive expression of no-global (No Solutions eps. 02/09/13):
**a relay is not an external dependency** — "a server truly is an external
dependency: one source of truth, power over you. A relay is not, because it
can literally be internal — on my phone, at home — completely exchangeable."
So put one on the device:

- **The flight-mode test**: an app backed by a local relay reads and writes
  offline, rebroadcasts in the background when connectivity returns, and its
  optimistic UI is *free* — the data is already signed; whether it has
  reached other relays yet is secondary.
- The local event cache doubles as the honest personalization layer: "what's
  been trending on my WoT relay in the last 48 hours" beats any global
  algorithm, computed from data the user already chose to hold.
- Marketing translation, for people who flinch at "censorship resistance":
  it's **100% uptime**.
- Missing-but-needed tooling around this: rebroadcast daemons that keep your
  events on your *current* relay set, and Blossom link-healing from the
  user's server list — signed data makes both trivial in principle; almost
  nobody ships them yet.

## The failure model you must build for

Concrete engineering consequences, non-negotiable for anything serious:

- Events arrive **duplicated** → dedup by id; ingest must be idempotent.
- Events arrive **late and out of order** → `created_at` is a claim, not an
  ordering; render defensively, use threads/references for causality.
- Events **don't arrive** → absence of evidence is nothing: "I asked 3 relays
  and got no result" never proves nonexistence.
- Relays **lie, throttle, vanish, and reject** → treat every relay response
  as best-effort; retry elsewhere; never let one relay's answer be final.
- Replaceable events **race** → last-write-wins per relay can differ across
  relays; fetch from several, take newest, and preserve fields you don't
  understand when re-publishing (see [`03-how-to-develop.md`](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/docs/core/03-how-to-develop.md) §fault tolerance).
- Any event may be **malformed or adversarial** → validate signatures always,
  sanitize content always, treat relay hints and media URLs as untrusted
  input.

Design for eventual, partial, best-effort consistency and Nostr is pleasant.
Design against it and every layer of your app fights you.

## The one-page summary

1. Routing heuristics, not replication, are what scale Nostr.
2. Outbox/inbox for social broadcast; every other kind needs its own declared
   heuristic; specs without routing are incomplete.
3. Whoever wants data findable somewhere is responsible for it being there —
   including after relay changes.
4. Relays are differentiated services with intent; make them visible to
   users and let them charge.
5. There is no global view. Build local-first, partition-tolerant, and
   paranoid about relay honesty.
