What Is the Buzz Relay Architecture? A Technical Deep Dive into block/buzz
The Buzz relay architecture is a modular, multi-tenant Nostr relay implementation that supports the NIP-29 protocol over WebSocket while exposing complementary HTTP APIs for media, Git, and webhook services.
The Buzz relay serves as the central server powering the Buzz ecosystem, designed from the ground up to handle isolated community environments (tenants) within a single process. Unlike traditional monolithic relays, the block/buzz codebase separates concerns into distinct crates and modules, enabling independent testing and evolution of each subsystem. This architecture supports both real-time WebSocket messaging and synchronous HTTP operations, making it suitable for diverse client applications ranging from mobile apps to CI pipelines.
Core Components and Module Structure
The relay implementation in crates/buzz-relay follows a layered architecture where each responsibility lives in a dedicated module. This separation ensures that WebSocket routing, state management, and protocol handlers remain isolated and testable.
Entry Point and Runtime Lifecycle
The journey begins in buzz-relay/src/main.rs, which serves as the program entry-point. This file parses the TOML configuration, initializes the asynchronous Tokio runtime, and spawns both the HTTP server and WebSocket listener on port 3000. The main function coordinates the startup sequence, ensuring that database connection pools, Redis clients, and telemetry collectors are initialized before accepting traffic.
WebSocket Routing and Authentication
Incoming WebSocket messages land in buzz-relay/src/router.rs, the nerve center of the relay. The router inspects each message's Nostr kind and dispatches it to the appropriate handler in buzz-relay/src/handlers/. Before dispatch, the router performs NIP-42 authentication validation via src/connection.rs and resolves tenancy based on the host header or explicit community tags. This ensures that every request is associated with a specific TenantId before reaching business logic.
Per-Tenant State Management
The buzz-relay/src/state.rs module maintains runtime state for each active tenant. Rather than sharing global mutable state, Buzz instantiates isolated State structs containing in-memory caches, Postgres connection pools, and Redis pub/sub clients the first time a tenant receives a request. These state objects persist for the process lifetime, providing complete data isolation between communities while maximizing connection reuse.
Protocol Handlers and HTTP API
The buzz-relay/src/handlers/ directory contains specialized handlers for Nostr operations: event.rs handles ingestion, query.rs manages subscription filters, and media.rs processes media uploads. Each handler validates cryptographic signatures, interacts with the database layer (buzz-db), and publishes updates to connected clients.
Complementing the WebSocket interface, buzz-relay/src/api/* exposes equivalent HTTP endpoints. Files like buzz-relay/src/api/media.rs wrap Nostr logic in RESTful interfaces, enabling desktop applications and CI pipelines to interact with the relay without maintaining persistent WebSocket connections.
Mesh Networking and Audio Subsystems
For horizontal scalability, the optional mesh layer in buzz-relay/src/mesh_* allows multiple relay instances to form a cluster. The mesh_boot.rs module handles node discovery and event replication, ensuring eventual consistency across distributed nodes.
The real-time voice chat functionality resides in buzz-relay/src/audio/room.rs, implementing WebRTC-style rooms that leverage the relay's existing pub/sub infrastructure for signaling and session management.
Telemetry and Observability
The buzz-relay/src/telemetry.rs module exposes Prometheus-compatible metrics for monitoring system health, request latency, and per-tenant throughput, enabling operators to track resource utilization across isolated communities.
Multi-Tenant Design and Isolation
Buzz treats every community as a distinct tenant, with isolation enforced at multiple layers. Tenancy resolution occurs in buzz-relay/src/tenant.rs, where the Tenant struct encapsulates community-specific configuration.
Once identified, the TenantId flows through all downstream handlers, ensuring strict separation of:
- Database schemas: Postgres uses schema-per-tenant isolation, while Redis employs key namespacing
- Media storage: MinIO object storage prefixes segregate uploaded content by community
- Event namespaces: Nostr event kinds and ID ranges remain logically separated through filtering
This design allows a single relay process to host thousands of distinct communities without risk of data leakage or resource contention.
Event Flow: From Client to Persistence
Understanding the Buzz relay architecture requires tracing the path of a Nostr event through the system. The implementation follows a four-stage pipeline that supports both WebSocket and HTTP ingress.
1. Connection and Authentication
A client initiates a WebSocket connection to ws://<relay>:3000. The connection handler in src/connection.rs negotiates the WebSocket upgrade and immediately enforces NIP-42 authentication, validating the client's public key and cryptographic signature against the challenge.
2. Event Ingestion and Validation
Upon receiving an EVENT message, buzz-relay/src/handlers/event.rs performs strict validation. The handler verifies the event signature, checks timestamp bounds, and ensures the publishing pubkey has authority within the resolved tenant context. Invalid events are rejected before reaching storage layers.
3. Persistence and Fan-Out
Validated events are written to Postgres via the buzz-db crate, ensuring durable storage. Simultaneously, the handler publishes the event to Redis pub/sub channels managed by buzz-pubsub. This dual-write strategy ensures that all connected WebSocket clients with matching filters receive real-time updates without polling the database.
4. Optional Mesh Replication
If the relay participates in a mesh cluster, buzz-relay/src/mesh_boot.rs asynchronously replicates the event to peer nodes. This gossip protocol guarantees eventual consistency across geographically distributed relay instances while maintaining the same tenant isolation boundaries.
Extensibility and Protocol Evolution
The Buzz relay architecture prioritizes forward compatibility through its modular handler system. New Nostr event kinds are defined in buzz-core/src/kind.rs, with corresponding implementations added to buzz-relay/src/handlers/.
Because buzz-relay/src/router.rs dispatches purely on the kind field, adding features requires no changes to the WebSocket protocol or HTTP routing tables. Developers simply implement a new handler module and register it in the router's dispatch map. This design enables rapid iteration on protocol extensions while maintaining backward compatibility with existing NIP-29 clients.
Practical Deployment Examples
Starting a local relay instance requires minimal configuration:
just relay
This command launches the relay on ws://localhost:3000, ready to accept WebSocket connections and HTTP requests.
Connecting via WebSocket using Node.js:
import WebSocket from 'ws';
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = () => {
// NIP-42 authentication required
ws.send(JSON.stringify(['AUTH', '<pubkey>', '<challenge>', '<sig>']));
};
ws.onmessage = (msg) => console.log('Relay →', msg.data);
Publishing events via HTTP for non-WebSocket clients:
curl -X POST http://localhost:3000/events \
-H 'Content-Type: application/json' \
-d '{
"pubkey":"<your_pubkey>",
"kind":40001,
"content":"Hello Buzz!",
"created_at":1700000000,
"tags":[],
"sig":"<signature>"
}'
Querying events with filters:
curl -X POST http://localhost:3000/query \
-H 'Content-Type: application/json' \
-d '{"kinds":[40001],"limit":10}'
Summary
The Buzz relay architecture delivers a production-ready, multi-tenant Nostr relay with distinct separation of concerns:
- Modular crate structure isolates WebSocket routing, state management, and protocol handlers into testable units
- Multi-tenancy ensures complete data isolation between communities through the
Tenantstruct andTenantIdpropagation - Dual-protocol support serves both persistent WebSocket clients and stateless HTTP consumers through shared handler logic
- Horizontal scalability via optional mesh networking allows clusters to synchronize events while maintaining tenant boundaries
- Extensible design enables new Nostr kinds through pure handler additions in
buzz-relay/src/handlers/without protocol changes
Frequently Asked Questions
How does Buzz handle authentication for WebSocket connections?
Buzz implements NIP-42 authentication in buzz-relay/src/connection.rs, requiring clients to provide a valid public key and cryptographic signature within the initial handshake. The router validates these credentials before dispatching messages to handlers, ensuring that all subsequent operations execute within the authenticated identity's tenant context.
What database systems does the Buzz relay use?
The architecture employs Postgres for durable event storage and Redis for pub/sub fan-out and caching. The buzz-relay/src/state.rs module maintains connection pools for both systems on a per-tenant basis, ensuring that database queries and cache operations remain isolated between communities through schema separation and key namespacing.
Can multiple Buzz relay instances form a cluster?
Yes, the optional mesh networking layer in buzz-relay/src/mesh_* and src/mesh_boot.rs enables multiple relay instances to discover peers and replicate events across nodes. This implementation provides eventual consistency for distributed deployments while preserving the multi-tenant isolation guarantees of the single-node architecture.
How do I add support for a new Nostr event kind to the relay?
Extend the relay by defining the new kind constant in buzz-core/src/kind.rs and implementing the handler logic in buzz-relay/src/handlers/. The WebSocket router in src/router.rs automatically dispatches messages based on the kind field, so no HTTP endpoint or routing table modifications are required to support new protocol features.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →