nostrbasedocs
Start building
Guide
.md

Pull missing events

const recovery = await db.sync.table("todos");
console.log(recovery.meta?.sync);

A table pull includes table records, scoped deletion events, and deletion recovery by event/address pointers. This also handles NIP-09 events from clients that omit this SDK’s namespace tag. Private personal records use the same signed ciphertext events; register their wire scope as private:todos for automatic recovery.

You can supply explicit Nostr filters or use registered table scopes:

await db.sync.pull({ kinds: [1], authors: [pubkey] });
await db.sync.pull(); // sync.tables plus tables used through the client.
await db.sync.pull(undefined, { strategy: "query" });

An empty registered scope produces INVALID_QUERY, rather than an unbounded request for every event on every relay. Explicit filters are an escape hatch and can intentionally select data outside the namespace.

For each relay and filter, the SDK:

  1. Gives Applesauce a filtered vector of locally stored event IDs and timestamps.
  2. Uses Negentropy to find remote IDs absent locally.
  3. Fetches missing events in batches of at most 100 IDs.
  4. Verifies each signature and checks the original filter before ingestion.
  5. Uses ordinary event queries if NIP-77 is unsupported, fails, or times out.

The SDK does not publish the local-only IDs reported by reconciliation. Use the explicit signed write queue to send your own events.

meta.sync reports each relay’s strategy (negentropy, query, or mixed), received count, fallback reason, and completion status. Counts include valid received copies; the returned event array is deduplicated by ID. Partial success is reported if some relays fail.

await db.sync.pull(undefined, {
  signal: controller.signal,
  relays: [db.relays[0]!],
});

Only configured relays can be selected. Cancellation and sync.timeout terminate reconciliation. Late responses from a cancelled reconciliation do not enter the cache.

Subscriptions and reconnects

Subscriptions receive new events. Negentropy recovers stored events missed during a disconnect. Use both:

const channel = db
  .channel("tasks")
  .on("nostr_changes", { table: "todos" }, (change) => console.log(change))
  .subscribe();

sync.initial runs a pull after cache hydration. sync.reconnect runs recovery after a previously connected relay disconnects and reconnects. Both are opt-in. Tables registered later through client queries also participate. sync.onError receives background recovery failures. Client close cancels sync and removes its relay connection observers.

Relays can limit ordinary queries or remove event history. Neither subscriptions nor Negentropy guarantee a complete global table, atomic changes, conflict-free writes, or delivery of ephemeral history. Each device still applies Nostr version and author rules.

Search guides, API methods, and protocols.