Community

NIPs

NIP-67: EOSE Completeness Hint

NIP-67 adds optional finish and more hints to EOSE so clients can know whether a relay sent all stored events for a subscription or whether pagination needs to continue.

NIP-67: EOSE Completeness Hint visual
NIPs Under the hood Events, NIPs, relay behavior and the shared formats apps can trust.
Back to Nostr
NIPs Open NIP map Deep guidesConcepts, NIP pages and source checks BrowseClose
Core protocoldraftoptionalpagination

NIP-67: EOSE Completeness Hint

NIP67Statusdraft / optionalExtended messageEOSEHintsfinish, moreScopestored events onlyAddedJune 2026

EOSE used to say boundary, not completeness

In NIP-01, EOSE marks the end of stored events for a subscription before real-time events continue. It does not tell a client whether the relay sent every stored match or stopped because of an internal cap. That ambiguity is a real pagination problem.

Clients have historically guessed. If fewer events than the requested limit arrive, assume complete. If the limit is filled, paginate with until and ask again. That breaks when a relay's internal cap is lower than the client's requested limit, and it wastes requests when the result count exactly hits the cap.

NIP-67 adds a small hint array to EOSE. It is a tiny protocol change with large practical value for clients that sync history.

finish, more and safe fallback

A relay may send ["EOSE", subscription_id, [hints...]]. The current defined hints are finish and more. finish means the relay has sent every stored event matching the filters and the client must not paginate further. more means the relay holds more matching stored events than it has sent and the client needs to paginate.

Unknown hints must be ignored. Absence of hints is not definitive, so clients fall back to legacy pagination. The hint applies only to stored events. It does not stop real-time delivery.

The NIP also discusses created_at ties. If several events share the oldest timestamp in a page, naive pagination can skip events. Relays needs to include boundary-timestamp events where possible and emit finish only when no older events remain.

A fresh pagination NIP from June 2026

NIP-67 is extremely recent. mattn added the visible EOSE Completeness Hint in June 2026 through PR #2317. There is no long adoption history yet, which needs to be stated plainly.

Its freshness does not make it unimportant. Sync correctness is a core client problem. If a client silently misses older events because it guessed wrong, users see incomplete profiles, broken threads and unreliable archives.

The right reading is practical: implement it where possible, advertise support in NIP-11 and keep fallback behavior for relays that still send old two-element EOSE messages.

First visible addition2026-06-06 by mattnPull requestPR #2317Open Git history

The client gets to stop guessing

A relay implementing NIP-67 appends the hint array and advertises 67 in NIP-11 supported_nips. It needs to send finish only when it knows the stored result set is complete, and more when it knows more stored events remain.

A client implementing it needs to trust explicit finish, paginate on explicit more, ignore unknown hints and use its old pagination heuristic when hints are absent. This keeps compatibility with older relays and clients.

The UI effect is mostly invisible when it works. History loads completely with fewer wasted requests. That is exactly the kind of infrastructure NIP you may never notice but will feel when it is missing.

finishStored result set is complete; stop paginating.
moreMore stored results exist; paginate.
No hintFall back to legacy heuristic.
ScopeStored events only; real-time delivery continues.

A wrong hint is worse than no hint

If a relay sends finish incorrectly, a client can miss data with confidence. That is worse than old uncertainty. Relays needs to be conservative.

There is also boundary-timestamp risk. Pagination around equal created_at values needs care, or clients can lose events even while following the hint model.

Read NIP-67 in the wild

NIP-67 gives clients a completeness hint at End Of Stored Events. That helps an interface know whether a relay likely finished responding or whether more history may still arrive.

The detail matters because empty states lie. A client can tell you 'no more from this relay' instead of implying 'nothing exists anywhere.' That distinction keeps discovery honest.

What changes when you actually use it

For you, NIP-67: EOSE Completeness Hint is felt when an app either behaves predictably or suddenly loses context. The visible symptom may be a missing reply, a broken link, a strange reaction count, an empty result or a relay error that looks like the whole network failed. The official terms draft, EOSE, limit, REQ, until, created_at are where that visible behavior begins, so the source is not background material; it is the place where the product promise gets its limits.

What changes for builders and operators

For builders, NIP-67: EOSE Completeness Hint is compatibility discipline. Implement draft, EOSE, limit, REQ, until, created_at against more than one relay and more than one library, then test malformed, missing and duplicated data. Core standards fail most painfully when the happy path looks fine and the second client exposes the shortcut.

What the official file makes concrete

The official file is organized around Motivation, Specification, Semantics around createdat ties, Relay advertisement, Examples. Inspect draft, EOSE, limit, REQ, until, created_at, until = oldest received event's created_at, CLOSE because these are the pieces most likely to surface as product behavior. Read it beside NIP-01, NIP-11 before treating it as isolated.

NIP-67: EOSE Completeness Hint is a shared contract between independent software. The smallest field can become user-visible when two clients disagree about it.

Where it breaks

The failure mode in NIP-67: EOSE Completeness Hint is often indirect. Nobody complains about draft, EOSE, limit, REQ, until, created_at; they complain that the feed is wrong, the reply vanished or the relay behaved strangely. Use the official file to diagnose the hidden cause instead of patching only the visual symptom.

Where this appears outside the markdown

In the ecosystem, NIP-67: EOSE Completeness Hint is not something most people choose directly. It is the invisible grammar behind clients, relays, crawlers, search tools and archives. When a product team treats draft, EOSE, limit, REQ, until, created_at as implementation detail only, the mistake eventually reaches the surface as missing history, bad threading or state that cannot be reconstructed after a client switch.

The nearby-standard trap

The nearby-standard trap in NIP-67: EOSE Completeness Hint is assuming the base layer solves the higher-level feature. This NIP may define the common grammar, but publishing, wallets, moderation, media or groups still need their own constraints. Read NIP-01, NIP-11 to see where the base contract ends and the product-specific promise begins.

Language that keeps the feature honest

Good product copy for NIP-67: EOSE Completeness Hint does not say "the protocol handles it" and move on. It explains the visible consequence: what was sent, what was accepted, what was rejected, what is still loading and what another relay or client may show differently.

What this page does not promise

NIP-67: EOSE Completeness Hint does not promise a finished social product. It gives software a shared grammar. Feed design, moderation, ranking, notifications, storage duration and recovery remain separate product decisions. That distinction matters because a client can be technically compatible and still give you a weak experience if it hides relay errors, drops context or treats optional fields as if every app understood them.

Read it as a field test

Start NIP-67: EOSE Completeness Hint with the visible product symptom, then trace it back to draft, EOSE, limit, REQ, until, created_at. That order keeps the article grounded: you see why the field exists, which relay or client behavior depends on it, and where adjacent standards change the story. A core NIP is strong only when it explains both the normal path and the awkward edge case.

Where the standard earns trust

The source links give you places to test the interpretation in public: PR #2317, NIP-01 Basic Protocol, NIP-11 Relay Information. Use those links to move from the spec to live libraries, mirrors, pull requests, guides or products.

Official NIP-67 source is the anchor for exact wording, and NIP-67 commit history shows how that wording moved over time. The strongest secondary clues here are PR #2317, NIP-01 Basic Protocol, NIP-11 Relay Information. Treat this evidence chain as part of the article, not as footnotes. A NIP page becomes useful when you can move from claim to source to working behavior without guessing.

Keep the chain visible for NIP-67: EOSE Completeness Hint: first the human promise, then draft, EOSE, limit, REQ, until, created_at, then the implementation record, then the real-world failure case. That order keeps NIP-67 useful without turning it into marketing copy or protocol trivia.

Three questions to carry forward

  • Can two independent clients read the same draft, EOSE, limit, REQ without a hidden compatibility rule?
  • Does the UI explain relay rejection, missing context or state replacement without blaming the whole network?
  • Which adjacent standard, especially NIP-01, NIP-11, changes the behavior once the base event leaves the happy path?

What to verify before you rely on it

  • Find draft, EOSE, limit, REQ, until in the official file and check where the UI exposes the same concept.
  • Read NIP-01, NIP-11 as context before treating NIP-67 as a complete product story.
  • Open at least one implementation, mirror, pull request or library source from the source links before trusting that the idea is mature.
  • Test the unhappy path: missing relays, stale metadata, invalid signatures, blocked events, expired state, revoked permissions or unavailable media.
  • Write the user-facing copy in plain language. If a standard changes authority, privacy, money, moderation or recovery, say that before the click.

Direct sources

Use these sources for NIP-67: EOSE Completeness Hint in that order: Official NIP-67 source for the current wording; NIP-67 commit history for the change record; PR #2317, NIP-01 Basic Protocol, NIP-11 Relay Information for public context. The article gives you the consequence in plain language, but the source trail is where exact fields, status notes, unresolved debates and implementation proof stay checkable.

Back to the NIP hub
NIPs route visual cue 1
NIPs route visual cue 2
NIPs route visual cue 3
NIPs route visual cue 4
NIPs route visual cue 5