Appearance
P2P Real-Time Data
Pulse P2P lets your users collaborate on structured, shared data — kanban boards, whiteboards, counters, diagrams — with changes syncing instantly between browsers.
Why P2P?
Pulse's existing features (comments, cursors, presence) flow through the server via WebSocket. This is perfect for persistent data that needs to be stored and queried.
P2P adds a second data path for high-frequency, collaborative state — data that changes rapidly and needs to sync with minimal latency:
WebSocket (existing): Browser ←→ Server ←→ DB (comments, presence, threads)
P2P (new): Browser ←←← P2P ←→→ Browser (boards, drawings, app state)Both work together in the same room. Your users get comments, cursors, and presence over WebSocket plus shared data structures over peer-to-peer — all from one SDK.
How It Works
Signaling
P2P connections are established through Pulse's existing WebSocket. When two users are in the same room and P2P is enabled:
- User A sends a WebRTC offer through the Pulse server
- Server relays it to User B (no inspection, just forwarding)
- User B responds with an answer
- ICE candidates are exchanged
- A direct peer-to-peer connection is established
After signaling, data flows directly between browsers — the server is not involved.
CRDT Conflict Resolution
P2P data is backed by Yjs CRDTs (Conflict-free Replicated Data Types). This means:
- No conflicts — two users can edit the same data simultaneously
- Automatic merging — changes converge to the same state regardless of order
- Offline support — Yjs buffers updates and syncs when reconnected
You don't need to implement conflict resolution. The SDK handles it.
Transport Fallback
When a room has too many users (above the configurable mesh limit, default 6), new peers automatically fall back to WebSocket relay. The shared data structures work identically over both transports — your code doesn't change.
Auto-Persistence
CRDT state is automatically saved to the server every 5 seconds (configurable). When a user joins a room later, the persisted state is loaded first, then live updates sync on top. Close all browsers, come back tomorrow — everything's there.
What You Get
| Feature | Description |
|---|---|
| SharedMap | Key-value store — like a JS Map that syncs across all peers |
| SharedList | Ordered array — push, insert, delete, move with automatic conflict resolution |
| SharedCounter | Distributed counter — increment/decrement from any peer, always converges |
| Raw Data Channels | Send any message directly to peers — build your own sync protocol |
| Auto-Persistence | State snapshots saved to server, restored on late join |
| WebSocket Fallback | Seamless fallback when P2P can't connect or room is too large |
Architecture
┌─────────────────────────────────────────────────┐
│ Your App │
│ │
│ SharedMap SharedList SharedCounter │
│ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────┐ │
│ │ Pulse P2P Manager │ │
│ │ ┌─────────────┐ ┌──────────────────┐ │ │
│ │ │ PeerManager │ │ SyncEngine │ │ │
│ │ │ (WebRTC) │ │ (Yjs + CRDT) │ │ │
│ │ └──────┬──────┘ └────────┬─────────┘ │ │
│ └─────────┼──────────────────┼─────────────┘ │
│ │ │ │
│ ┌───────┴───────┐ ┌──────┴──────┐ │
│ │ P2P DataChannel│ │ WS Fallback │ │
│ │ (direct) │ │ (via server) │ │
│ └───────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────┘Next Steps
- Quick Start — Enable P2P and create your first shared data
- Shared Data Structures — SharedMap, SharedList, SharedCounter API
- Raw Channels & Connection Info — Custom messaging and peer tracking