strfry
The most efficient Nostr relay. High-performance C++ implementation using LMDB.
Overview
strfry is designed for large-scale public relays. Written in C++, it offers exceptional performance while maintaining low resource usage — it even runs great on a Raspberry Pi 5.
Key Features
Performance
- LMDB storage — Memory-mapped database for fast reads
- Low memory footprint — Efficient even on constrained hardware
- High throughput — Handles thousands of concurrent connections
Negentropy Sync
strfry's most distinctive feature is set reconciliation using the Negentropy protocol:
┌─────────────┐ ┌─────────────┐
│ Relay A │ │ Relay B │
│ │ │ │
│ Events: │ Negentropy │ Events: │
│ {1,2,3,5} │◄──────────────────►│ {1,2,4,5} │
│ │ Sync Protocol │ │
└─────────────┘ └─────────────┘
│ │
│ Only transfer │
│ missing events │
│ (3 → B, 4 → A) │
└────────────────────┘
Benefits:
- Bandwidth efficient — Only transfers differences
- Works with filters — Sync arbitrary nostr filter results
- Relay-to-relay — Synchronize relays efficiently
- Client sync — Clients can use it too
Event Compression
# Compress events using zstd dictionaries
strfry dict --compress ./events.json
# Events remain efficiently queryable
# Only raw JSON is compressed, not indices
Stream Router
Handle multiple relay streams in one process:
strfry router --config router.conf
Features:
- Pre-filter events with nostr filters
- Plugin support for custom logic
- Efficient multi-stream handling
Installation
From Source
git clone https://github.com/hoytech/strfry.git
cd strfry
git submodule update --init
make setup-golpe
make -j4
./strfry relay
Docker
docker run -p 7777:7777 -v ./strfry-data:/app/strfry-db \
dockurr/strfry
Configuration
# strfry.conf
relay:
bind: 0.0.0.0
port: 7777
info:
name: "My Relay"
description: "A strfry relay"
contact: "admin@example.com"
# Performance tuning
maxWebsocketPayloadSize: 131072
autoPingSeconds: 30
enableTcpKeepalive: true
# Query limits
queryTimesliceBudgetMicroseconds: 5000
maxFilterLimit: 1000
maxSubsPerConnection: 50
# Write policy
writePolicy:
plugin: "" # Optional plugin for custom logic
Plugins
strfry supports plugins for custom event processing:
#!/bin/bash
# write-policy.sh - Accept only kind 1 events
read event
kind=$(echo "$event" | jq -r '.event.kind')
if [ "$kind" = "1" ]; then
echo '{"action":"accept"}'
else
echo '{"action":"reject","msg":"only kind 1 allowed"}'
fi
Configure in strfry.conf:
writePolicy:
plugin: "./write-policy.sh"
Commands
# Start relay
strfry relay
# Export events
strfry export > events.jsonl
# Import events
strfry import < events.jsonl
# Sync with another relay
strfry sync wss://other-relay.example
# Compress events
strfry dict --compress
# Stream router
strfry router --config router.conf
Performance Tuning
For High Traffic
# Increase connection limits
maxSubsPerConnection: 100
maxFilterLimit: 5000
# Tune query budget
queryTimesliceBudgetMicroseconds: 10000
For Low Memory
# Reduce buffer sizes
maxWebsocketPayloadSize: 65536
# Lower connection limits
maxSubsPerConnection: 20
Comparison
| Feature | strfry | nostream | rnostr |
|---|---|---|---|
| Language | C++ | TypeScript | Rust |
| Storage | LMDB | PostgreSQL | Various |
| Negentropy | Yes | No | No |
| Memory | Low | Medium | Low |
| Best for | Large public | Easy setup | Performance |
Links
- GitHub: hoytech/strfry
- Docker: dockurr/strfry
- Negentropy: Protocol docs
See Also
- Nostr Protocol — The protocol
- Production Deployment — Deployment guide
- Nosdav — Storage with Nostr auth