How Nostr actually works: the protocol, with no jargon
Under the hood, Nostr is 200 lines of spec. Events, signatures, relays, subscriptions. Every moving piece with concrete examples.
Most explanations of Nostr stop at "it is a decentralized social protocol" and leave the interesting part unsaid. The interesting part is that the entire protocol fits in a short document. No clever trick, no buried complexity. Just a few primitives that work together.
This guide walks through those primitives in the order they come up when you actually use Nostr: how an event is built, how it is signed, how it reaches relays, how clients subscribe, and what the flow looks like when you like a post, get a reply, or receive a zap. No blockchain comparisons, no grand narrative. Just the mechanics.
TL;DR. Nostr is pub/sub over WebSockets with cryptographic signatures. Clients publish signed JSON objects (events) to relays (small servers), and other clients subscribe to relays with filters that match the events they want. Signatures prevent forgery; multiple relays prevent single points of failure. That is the whole protocol; everything else is formatting conventions for different kinds of content.
When you are ready, grab your @nostr.blog address
The building block: an event
Everything on Nostr is an event. A post is an event. A reaction is an event. A profile update is an event. A direct message is an event. A zap receipt is an event.
An event is a JSON object with exactly this shape:
{
"id": "abc123...",
"pubkey": "0a4f7b1a3d9a1529a3080c3ae5ee553e0af0a01d86d01677c0bb270592923f88",
"created_at": 1776329035,
"kind": 1,
"tags": [
["t", "nostr"],
["p", "3bf0c63f..."]
],
"content": "hello nostr",
"sig": "def456..."
}
Six fields do meaningful work. id is a hash of the event's own content; it uniquely identifies the event. pubkey is the author (a 64-character hex public key). created_at is a Unix timestamp. kind is an integer describing what the event represents (more on this below). tags is a list of structured annotations such as hashtags (t), mentions (p for pubkey, e for event), and dozens of others. content is the free-form payload, usually text.
sig is the Schnorr signature, made with the author's private key, over the hash in id. This is the field that prevents forgery: anyone can compute the hash, but only the holder of the private key can produce a valid signature on it.
What is a "kind"
The kind field tells clients how to interpret the event. The number is the whole semantic type.
A handful of kinds in active use:
| Kind | Meaning |
|---|---|
| 0 | Profile metadata (name, avatar, bio) |
| 1 | Short text note (the Nostr equivalent of a tweet) |
| 3 | Contact list (who you follow) |
| 4 | Direct message (legacy, being replaced by 1059) |
| 5 | Deletion request |
| 6 | Repost of a short note |
| 7 | Reaction (like, dislike, emoji) |
| 9734 | Zap request |
| 9735 | Zap receipt |
| 30023 | Long-form article |
| 1059 | Gift-wrapped direct message (NIP-44/NIP-17) |
New kinds get proposed and standardized via NIPs (Nostr Implementation Possibilities). Anyone can propose one. The ones that get widely adopted become de facto parts of the protocol; the ones that do not simply remain niche without breaking anything.
How an event gets published
When you tap "post" in a Nostr client, this sequence runs:
- Client assembles the JSON. Fills in
pubkey,created_at,kind,tags,content. - Client computes the id. Runs SHA-256 over a canonical serialization of those fields. This is the hash the signature covers.
- Client signs the id with the private key. Schnorr signature over
secp256k1, the same curve Bitcoin uses. The 64-byte signature becomes thesigfield. - Client opens WebSocket connections to each configured relay. Or reuses existing open ones if they are live.
- Client sends the event as a message. The on-wire format is a JSON array:
["EVENT", {...event...}]. - Each relay validates the signature. Rejects the event if the signature does not verify against the claimed pubkey. Accepts and stores otherwise.
- Each relay pushes the event to subscribers. Any client with an open subscription whose filter matches this event gets the event delivered in real time.
The entire round-trip takes 50 to 300 milliseconds depending on relay locations. If any relay is slow or offline, the other relays still publish the event. You only need one relay to accept it for the event to exist on the network.
How a client fetches posts
Reading is the mirror of publishing.
Your client opens WebSocket connections to a list of relays. For each one, it sends a subscription message:
["REQ", "sub_id_1", { "authors": ["pubkey1", "pubkey2", ...], "kinds": [1, 6], "limit": 50 }]
This asks the relay for up to 50 events from the authors in the list, of kind 1 (short note) or kind 6 (repost). The relay:
- Queries its local database for matching events, sends them (oldest to newest by default, up to the limit) as
EVENTmessages back to the client. - Sends an
EOSE(end of stored events) message so the client knows the historical dump is complete. - Keeps the subscription open. Any new event that matches the filter (published by someone else later) gets pushed to the client in real time.
That is how your feed becomes live. You are not polling; the relay is streaming.
Your client does this in parallel across every configured relay. The union of responses is your timeline. Duplicate events across relays are deduplicated by id.
How signatures actually prevent forgery
This is the part most explanations gloss over.
When a client receives an event, it recomputes the hash over the canonical serialization (same way the publisher did) and runs Schnorr verification: given the pubkey, the id, and the sig, does the signature cryptographically check out?
If yes, the event is authentic. The author of this event was the holder of that pubkey at the moment of signing. Every client runs this check on every event. A relay that ships a forged event with a bad signature just gets the event dropped silently by every client that sees it.
This matters because it means relays are untrusted. A malicious relay cannot put words in your mouth. It can refuse to serve your posts, it can inject someone else's (legitimate) posts into your feed, but it cannot produce a valid post signed by you without your private key, and it cannot modify one of your existing posts without breaking the signature.
The cost of this property is exactly one Schnorr verification per event, which is fast enough that even mobile clients handle it at tens of thousands of events per second.
What relays actually do
A relay is a dumb, fast pipe with three jobs:
- Accept events and validate signatures. Reject anything that does not verify or fails policy checks (spam filters, size limits, blocked pubkeys).
- Store events. Usually in an SQLite or PostgreSQL database indexed by
id,pubkey,kind, and tag values. - Serve subscriptions. Match incoming
REQfilters against the database (for historical) and against live events (for real-time).
That is all. A relay does not rank, recommend, curate, monetize, show ads, apply an algorithm, or do anything a platform would do. It forwards signed bytes.
The absence of those other jobs is why relays can be tiny. A single $5-per-month VPS can run a relay serving hundreds of active users. The same function at Twitter's scale costs billions because Twitter does all the other things.
Relay policies differ. Some are permissionless and serve any signed event. Some require payment (the "paid relay" model), others restrict to a specific community (employees of a company, members of a Discord server), and still others are aggressive about spam filtering. You choose which relays to use; your choice affects which posts you see and which ones reach your followers.
A complete example: someone likes your post
Tying it together, here is what happens end to end when Alice likes a post Bob wrote.
- Bob publishes. Bob's client builds a kind:1 event with content "hello world," signs it, sends it to bob's five configured relays. Each relay accepts and stores.
- Alice subscribes. Alice's client has an open subscription on two of those relays with a filter that includes Bob's pubkey in
authors. The relays push Bob's event down the subscription. Alice's client shows the post in her timeline. - Alice taps like. Alice's client builds a kind:7 event with content "+" (the Nostr "like" convention), tags the post it reacts to (
["e", "bob_post_id"]) and the author (["p", "bob_pubkey"]). Signs and publishes to Alice's five configured relays. - The reaction propagates. Any relay that has an active subscription matching the filter
{ "#e": ["bob_post_id"], "kinds": [7] }(which is what Bob's client uses to watch for reactions to his own posts) pushes the reaction to Bob. Bob's client aggregates the likes and shows the count under the post.
Notice what did not happen. No centralized "like button" service got pinged. No backend decided whether the like counts. The like is just a signed event, announced on the same channels as the post itself.
What Nostr explicitly does not do
Five things left out of the core protocol on purpose, because they belong in the client or the relay, not the shared wire format.
- Identity verification. Nostr only proves "this pubkey signed this post." Whether the pubkey belongs to a specific human being is a separate question answered by NIP-05 and off-chain context.
- Content moderation. The protocol does not decide what is visible. Clients filter, relays filter, users filter. Each layer independently.
- Search. There is no global search endpoint. Some relays support text search over their local event pool; there is no protocol guarantee that any relay can find any post.
- Algorithmic ranking. No "for you" feed in the protocol. Ranking happens in the client if at all.
- Account recovery. No email reset, no phone reset, no central dispute system. Lose the private key, lose the identity. This is a tradeoff, not a bug.
Those absences are what make the protocol small. They are also what makes building a polished user experience on top harder than building one on a centralized platform, which is the honest cost.
Why the design works at all
The design relies on one simple property: signatures are cheap to verify, forgery is impossible without the private key, and relays are free to replace.
Those three facts compound. Cheap verification means every client can check every event. Impossible forgery means relays do not need to be trusted. Free replacement means no single relay has power over anyone.
Put together, you get a social network where the platform layer is interchangeable and the identity layer is owned by the user. Which is what "decentralized" actually means in practice, as opposed to how marketing usually uses the word.
If you want to see the whole flow from the user side (a key pair, a NIP-05 identity, a relay list, a wallet, ready to post), nostr.blog's signup collapses those steps into one page. The mechanics described here are what is actually running underneath that flow.
Frequently asked questions
Is Nostr a blockchain?
How does Nostr prevent fake posts from being attributed to me?
What happens if a relay goes offline?
How do clients find my posts?
Can relays see my direct messages?
Related reading
What is Nostr? A plain-English guide for 2026
Nostr is a simple, open protocol for social media and identity. No company runs it, no account can be deleted by anyone but you. Plain English.
6 min readGetting startedHow to use Nostr: a step-by-step guide for beginners
Open an app, get a pair of keys, follow some people, post. What starting Nostr looks like in 2026, with the details nobody warns you about.
9 min readIdentity and NIP-05What is NIP-05? The Nostr address, explained
NIP-05 is the email-shaped identifier you use on Nostr: alice@nostr.blog. What it actually does, what it does not, and how to get one.
7 min readAdvanced and technicalAre Nostr DMs really private? The honest answer
Nostr DMs use encryption but the privacy model has gaps. What NIP-04, NIP-44, and NIP-17 gift wraps protect, and when to use Signal instead.
7 min readAdvanced and technicalHow to run your own Nostr relay in 2026
A practical guide to running a Nostr relay on a cheap VPS. Which software, how to configure it, what it costs, and why you might want to.
7 min read