Pp2pbuilders
learn › Patterns for P2P apps

9 min read · also at #/learn/pattern-data

Data patterns

The state-shaped patterns we reach for in every app. Steal freely.

1. Single-writer log, many-reader fold

The foundational pattern
(handbook chapter). Each identity appends ops to
its own signed log; every peer folds all followed logs through a pure
reducer into a local view. No shared mutable state, no write conflicts, sync
is length-compare. Use unless the product demands one canonical shared
sequence (then: Autobase).

2. Op schema with version byte

Ops are { v, type, ts, payload }. v first — logs are forever and you
cannot migrate other people's cores
(Storyteller 1). Readers skip unknown types and
versions without erroring: old clients are permanent.

3. Reference, never contain

Ops point at targets by id (vote.target, comment.parent); the fold
stitches the graph. Deterministic ids — author key + sequence number, or a
content hash — cost nothing and never collide.

4. Last-write-wins records (with a real tiebreaker)

For "current value" state (profiles, votes, follows): key the record
(vote!<target>!<voter>), keep the highest (ts, deterministic-tiebreak)
version. The tiebreak (compare hashes, compare authors — anything total)
matters: equal timestamps happen constantly, and peers that break ties
differently never converge.

5. Tombstones — hide, don't delete

Append-only means no erasure; "delete" is an op that conforming indexers
honor by hiding the target (the foundations track is honest about this).
Enforce authorship in the fold — a tombstone only applies if its author
may delete the target (owner, or a role your app defines — p2pbuilders
honors admin tombstones for any target, everyone else's for their own).
Never rely on the writing client being polite.

6. First-writer-wins (sticky) names

Human-readable names in a system with no registry: first
boardcreate / storycreate observed for a name wins; later claims
are ignored by the fold. An established name cannot be hijacked — even by a
claim with a backdated timestamp, which is why "first observed", plus a
deterministic tiebreak for genuine races, beats "earliest claimed". Squatting
on brand-new names remains possible; say so, and let social pressure handle
it.

7. Keyspace design is query design

Views live in ordered stores (Hyperbee); prefixes are
tables, ranges are queries, inverted timestamps give newest-first. Design
keys the way you would design indexes.

« HiveRelay: dumb storage that keeps P2P online Network patterns: topics, gossip, validate-on-ingest »