Nostr Relays — Architecture and Management

Relay types, NIP-11 metadata, relay selection, attack/defense, and running your own

Nostr Relays

Dumb pipes. Smart network. Relays are the infrastructure layer that makes Nostr work.

What Relays Do

Relays are WebSocket servers that:

  1. Accept events from clients (EVENT)
  2. Store events (optionally, based on kind policy)
  3. Forward events to subscribers (REQ → EVENT stream)
  4. Send notices for errors, rate limits, etc.

That’s it. No logic. No feeds. No algorithms. Just store and forward.

Relay Architecture

  CLIENT A                    RELAY                      CLIENT B
     │                         │                           │
     │──EVENT(kind:1)────────▶│                           │
     │                         │──store───────────────────│
     │                         │                           │
     │                         │◄──REQ(kinds:[1])─────────│
     │                         │──EVENT (match)──────────▶│
     │                         │──EVENT (match)──────────▶│
     │                         │──EOSE────────────────────▶│

Relay Types

Public Relays

  • Anyone can connect
  • Anyone can publish
  • Anyone can read
  • Free or paid

Private Relays

  • Access controlled
  • Whitelisted pubkeys
  • Invite-only
  • Often for DMs or private communities

Paid Relays

  • Pay-per-event or subscription
  • Higher quality (less spam)
  • Often used for write access

Specialized Relays

  • Search relays (kind 10007): indexed search
  • DM relays (kind 10050): dedicated to private messages
  • Read relays: optimized for content delivery
  • Write relays: optimized for event acceptance

Relay Information (NIP-11)

Every relay should serve metadata at its WebSocket endpoint:

GET wss://relay.damus.io
→ NIP-11 JSON document
{
  "name": "Damus Relay",
  "description": "Public relay for Damus users",
  "pubkey": "7e2...",
  "contact": "damus@example.com",
  "supported_nips": [1, 2, 4, 9, 11, 12, 15, 16, 20, 22, 28, 33, 40],
  "software": "strfry",
  "version": "0.9.6",
  "limitation": {
    "max_message_length": 16384,
    "max_subscriptions": 20,
    "max_filters": 100,
    "max_limit": 500,
    "max_subid_length": 100,
    "min_prefix": 4,
    "max_event_tags": 100,
    "created_at_lower_limit": 946684800,
    "created_at_upper_limit": 2147483647
  },
  "payments_url": "https://...",
  "fees": {
    "admission": [{ "amount": 1000000, "unit": "msats" }],
    "publication": [],
    "subscription": [{ "amount": 5000000, "unit": "msats", "period": 2592000 }]
  }
}

My Relays

wss://relay.damus.io       — Public, high traffic
wss://nos.lol              — Public, reliable
wss://relay.nostr.band     — Public, searchable
wss://relay.primal.net     — Public, Primal backend
wss://nostr.mom            — Public
wss://purplepag.es         — Indexing relay

Managed via kind 10002:

{
  "kind": 10002,
  "tags": [
    ["r", "wss://relay.damus.io"],
    ["r", "wss://nos.lol"],
    ["r", "wss://relay.nostr.band", "read"],
    ["r", "wss://relay.primal.net"],
    ["r", "wss://nostr.mom"],
    ["r", "wss://purplepag.es", "read"]
  ]
}

Relay Policies

Relays decide what to store/forward. Common policies:

Kind Filtering

Store: kinds 0, 1, 3, 5, 6, 7, 30023, 9735
Reject: kinds 4, 23194, 23195  (ephemeral)
Ignore: kinds 20000-29999 (by design)

Rate Limiting

Max events per minute: 10-100
Max subscription filters: 20-100
Max subscription duration: infinite or time-limited

Content Moderation

Some relays block content. Some don’t. Pick relays that match your values.

Relay Software

Software Language Notes
strfry C++ High performance, NIP-50 search
nostream TypeScript Feature-rich
nostr-rs-relay Rust Efficient
khatru Go Framework for custom relays
citrine Kotlin Android-friendly

Attacking & Defending

Attacks on Relays

  • Spam: Flood with junk events → rate limiting, POW (NIP-13), paid relays
  • DDoS: Overwhelm with connections → connection limits, CDN
  • Storage exhaustion: Fill disk → kind filtering, retention limits
  • Content injection: Forge events → sig verification on acceptance

Defenses for Users

  • Multiple relays: Publish to 3-5 relays for redundancy
  • Read relays: Use separate relays for reading
  • Private relays: Run your own for sensitive content
  • DM relays: Dedicated relay for DMs (kind 10050)

Relay Selection Best Practices

  1. Audit your relay list: Know who runs each relay
  2. Diversify: 5-8 relays across different operators
  3. Separate concerns: Write relays ≠ Read relays ≠ DM relays
  4. Keep it small: NIP-65 recommends 2-4 of each type
  5. Spread kind 10002: Publish your relay list everywhere

Running Your Own Relay

# strfry - fast C++ relay
git clone https://github.com/hoytech/strfry
cd strfry && make setup-golpe
make -j4
./strfry relay

Benefits:

  • Full control over your data
  • No censorship by third parties
  • Can archive all your events
  • Learn the protocol from the inside

Relay Discovery

Finding relays:

  1. Purple Pages (purplepag.es): Community-curated relay index
  2. nostr.watch: Relay monitoring + uptime stats
  3. User follow lists: See what relays followed users use
  4. kind 10002: Everyone’s relay list metadata
  5. NIP-11: Ask a relay for its info

Write a comment
No comments yet.