Data Model for a Neo4j Nostr Relay

Background

Nostr: Notes and Other Stuff Transmitted by Relays [1] is an open source protocol for censorship-resistant social media. Users maintain public key - private key pairs and use the Schnorr signature standard for digital signatures and encodings. Content is stored in objects called events (a.k.a. notes) which are signed and broadcast to relays which act as the backend servers for Nostr. Relays transmit events with users, with clients, and with each other via websockets following the protocol specified in NIP-01 (Nostr Implementation Possibility-01: Basic Protocol) [2].

Most Nostr relays store events using relational databases or key-value databases such as LMDB. However, as of Nov 2025, no native graph database nostr relays have been built. This is unfortunate, given the performance advantages of native graph databases in social graph analysis. This prompts us at NosFabrica to construct a fully NIP-01 compliant, native graph database nostr relay based on neo4j. This document provides an overview of a proposed data model [3] for a neo4j nostr relay.

The primary function of this data model is to provide support for NIP-01. However, it also provides support for Follow Lists (NIP-02), Mute Lists (NIP-51), Reports (NIP-56), Replies (NIP-10), Reactions (NIP-25), Reposts (NIP-18), Comments (NIP-22), and Trusted Assertions (NIP-85) [4].

Data Model

Node labels

  • NostrUser, NostrEvent, NostrEventTag, NostrRelay (NIP-01)

  • NostrUserWotMetricsCard (NIP-85: Trusted Assertions))

Relationship types

  • AUTHORS, HAS_TAG, REFERENCES, SUGGESTED_RELAY (NIP-01)

  • FOLLOWS (NIP-02), MUTES (NIP-51), REPORTS (NIP-56)

  • IS_A_REPLY_TO (NIP-10)

  • IS_A_REACTION_TO (NIP-25)

  • IS_A_REPOST_OF (NIP-18)

  • IS_A_COMMENT_ON (NIP-22)

Properties

See graph below.

Graph

Cypher

Cypher code for the above graph.

CREATE (:NostrUser)<-[:FOLLOWS {timestamp: “”}]-(n11:NostrUser {pubkey: “”})-[:AUTHORS]->(:NostrEvent {id: “<id>”, kind: “<kind>”, sig: “<sig>”, content: “<content>”, created_at: “<unix_time>”})-[:HAS_TAG]->(n4:NostrEventTag {tag_name: “<p, e, a, d, …>”, tag_value: “<pubkey, id, naddr, etc>”, relay_url: “<url>”, <other_optional_keys>: “”})-[:REFERENCES]->(:NostrEvent)-[:SUGGESTED_RELAY]->(:NostrRelay {url: “<url>”}), (:NostrUser)<-[:REPORTS {timestamp: “”, report_type: “”}]-(n11)-[:MUTES {timestamp: “”}]->(:NostrUser), (n11)-[:WOT_METRICS_CARD]->(:NostrUserWotMetricsCard {customer_id: “”, hops: “”, influence: “”, average: “”, input: “”, confidence: “”, personalizedPageRank: “”, verifiedFollowerCount: “”, verifiedMuterCount: “”, verifiedReporterCount: “”, followerInput: “”, muterInput: “”, reporterInput: “”}), (:NostrEvent {kind: 1})-[:IS_A_REPLY_TO {marker: “<reply vs root>”}]->(:NostrEvent {kind: 1}), (:NostrEvent {kind: 7})-[:IS_A_REACTION_TO]->(:NostrEvent), (:NostrEvent {kind: 6})-[:IS_A_REPOST_OF]->(:NostrEvent {kind: 1}), (:NostrEvent {kind: 16})-[:IS_A_REPOST_OF]->(:NostrEvent), (:NostrEvent {kind: 1111})-[:IS_A_COMMENT_ON]->(:NostrEvent), (n4)-[:REFERENCES]->(:NostrUser)

Data Volume

Statistics from nostr.band [5] indicate:

  • ~ 15 thousand daily users

  • ~ 1.2 million profiles with a bio and contact list

  • ~ 300 thousand users in the extended Follows network

  • ~ 25 thousand daily updates of contact lists (kind 3 events)

  • ~ 500 thousand new events published per day

  • ~ 600 million total events published as of Nov 2025

References

[1] https://github.com/nostr-protocol/nostr

[2] https://github.com/nostr-protocol/nips/blob/master/01.md

[3]  https://neo4j.com/docs/getting-started/data-modeling/tutorial-data-modeling/

[4] https://nostrhub.io/naddr1qvzqqqrcvypzq3svyhng9ld8sv44950j957j9vchdktj7cxumsep9mvvjthc2pjuqyt8wumn8ghj7un9d3shjtnswf5k6ctv9ehx2aqqzf68yatnw3jkgttpwdek2un5d9hkuuctys9zn

[5] https://stats.nostr.band


No comments yet.