Does BitChat Have a Server Architecture? Understanding Its Decentralized Design
BitChat does not use a traditional server architecture; instead, it employs a serverless design combining a local Bluetooth Low-Energy (BLE) mesh network with the public Nostr relay network, optionally routed through Tor.
BitChat's architecture represents a deliberate departure from conventional messaging apps that rely on centralized backend infrastructure. The permissionlesstech/bitchat repository implements a dual-transport system where routing, persistence, and message delivery happen across peer-to-peer connections and open-source Nostr relays rather than proprietary servers. This article examines how BitChat functions without a dedicated backend and what components assume server-like responsibilities.
Core Components of the BitChat Server Architecture
BitChat distributes traditional server functions across several client-side components. Each plays a distinct role in message routing, storage, and connectivity.
BLE Mesh Transport
The BLE mesh transport enables infrastructure-free local communication. Each BitChat device operates simultaneously as both a GATT central and peripheral, forwarding packets through a controlled flooding mechanism. This creates an ad-hoc network where messages propagate device-to-device without internet connectivity.
The implementation lives in docs/BLE-ARCHITECTURE-V3.md, which details the packet format and flood control mechanisms that prevent network congestion. Unlike traditional Bluetooth pairing, this mesh allows multi-hop message relay between devices that are not directly paired.
Nostr Relay Transport
When BLE connectivity is unavailable, BitChat bridges to the internet through public Nostr relays. The NostrRelayManager in bitchat/Nostr/NostrRelayManager.swift manages WebSocket connections to a configurable pool of relays, handling:
- Connection lifecycle and reconnection with exponential backoff
- Per-relay statistics and health monitoring
- Tor integration for traffic anonymization
- Built-in and user-added relay management
Messages travel as encrypted private envelopes that relays store temporarily without reading contents. This provides store-and-forward capability for peers that are offline or out of mesh range.
MessageRouter: The Traffic Controller
The MessageRouter in bitchat/Services/MessageRouter.swift serves as the central decision engine. It implements a priority-based routing strategy:
- Active BLE link — preferred for local, low-latency delivery
- Nostr relay path — fallback for internet-wide reachability
- Courier system — invoked when neither transport can deliver promptly
The send(_:completion:) API exposes this routing logic to higher-level components:
router.send(message) { result in
switch result {
case .success: print("Delivered")
case .failure(let err): print("Failed: \(err)")
}
}
ConversationStore: State Management
ConversationStore functions as the single source of truth for all conversation state. It maintains:
- Public channel timelines
- Private conversation contexts
- Transport-specific identifiers that map between BLE and Nostr addressing schemes
This component mirrors how a traditional server would manage session state, but operates entirely on-device with no external database dependency.
AppRuntime: Lifecycle and Service Composition
AppRuntime in ARCHITECTURE_V2.md acts as the composition root, initializing and wiring together:
- BLE service startup
NostrRelayManagerinstantiation- Tor integration
- Background task scheduling
- Screenshot and reconnect observers
How Message Delivery Works Without Servers
BitChat's message flow demonstrates how serverless operation is achieved:
Startup Sequence
During initialization, AppRuntime creates the three core transport components. The ChatViewModelBootstrapper coordinates this boot process, ensuring MessageRouter has active connections before accepting user messages.
Transport Selection Logic
When MessageRouter.receiveSendRequest() is invoked, it evaluates:
- Whether recipient is visible on the local BLE mesh
- Nostr relay connectivity status
- Message urgency and courier eligibility
This decision happens locally with no server consultation.
Store-and-Forward Fallbacks
For undeliverable messages, BitChat implements three mechanisms described in WHITEPAPER.md:
- Sender Outbox — sealed messages persist locally until any transport succeeds
- Couriers — encrypted envelopes delegated to physically proximate peers for delayed delivery
- Nostr Mailboxes — 24-hour encrypted storage on public relays
These systems collectively replace server-side message queues.
Tor Integration for Anonymity
Optional Tor encapsulation, detailed in docs/TOR-INTEGRATION.md, routes Nostr traffic through the anonymity network. This occurs at the NostrRelayManager level without requiring separate Tor-enabled relay infrastructure.
Configuring Nostr Relay Connections
Users can extend BitChat's connectivity by adding custom Nostr relays. The NostrRelayManager supports this through its dependency system:
let dependencies = NostrRelayManagerDependencies.live()
let nostrManager = NostrRelayManager(dependencies: dependencies)
Adding a relay persists to UserDefaults and refreshes the active connection pool:
let customURL = "wss://my.custom.relay"
NostrRelaySettings.addCustomRelay(customURL)
nostrManager.reloadRelays()
The live() factory method in NostrRelayManagerDependencies (lines 84-85) consults NostrRelaySettings.customRelays() when building the relay list.
Key Architecture Files
| File | Purpose |
|---|---|
docs/ARCHITECTURE_V2.md |
Runtime layer, store architecture, and feature-scoped model design |
WHITEPAPER.md |
Complete protocol specification including dual-transport rationale |
bitchat/Nostr/NostrRelayManager.swift |
WebSocket connection management and relay statistics |
bitchat/Services/MessageRouter.swift |
Transport selection and courier invocation |
bitchat/ViewModels/ChatViewModelBootstrapper.swift |
Runtime initialization and component wiring |
docs/TOR-INTEGRATION.md |
Tor anonymization implementation |
docs/BLE-ARCHITECTURE-V3.md |
Mesh networking protocol and packet structure |
Design Rationale: Why No Dedicated Server?
BitChat's serverless architecture directly serves three project goals:
- Decentralization — No single point of control or failure
- Censorship resistance — Communication persists without permission from infrastructure operators
- Offline resilience — BLE mesh functionality in environments without reliable internet
The "server" role is intentionally fragmented: Nostr relays provide public infrastructure storage, while peer devices handle routing, encryption, and local persistence. This eliminates operational costs for backend infrastructure while maximizing user autonomy.
Summary
- BitChat has no dedicated server component; it uses a distributed dual-transport architecture instead
- BLE mesh provides local, infrastructure-free routing through device-to-device forwarding
- Nostr relays offer internet-wide message storage and delivery without proprietary infrastructure
- MessageRouter coordinates transport selection and fallback mechanisms locally
- AppRuntime composes services including optional Tor integration for Nostr traffic
- All state management occurs in ConversationStore on the client device
- Users can extend connectivity by adding custom Nostr relays through
NostrRelaySettings
Frequently Asked Questions
Does BitChat require any server infrastructure to function?
No. BitChat can operate entirely through its BLE mesh transport without internet connectivity. When internet access is available, it uses public Nostr relays that anyone can run—no proprietary backend is required. The app stores messages locally and manages all routing decisions on-device.
How does BitChat handle messages when both sender and receiver are offline?
BitChat employs three store-and-forward mechanisms: the sender's local outbox persists messages until delivery succeeds; couriers (nearby peers) can carry encrypted envelopes; and Nostr relays store encrypted messages for up to 24 hours. These systems operate without centralized message queues.
What are Nostr relays and why does BitChat use them?
Nostr relays are open-source, public servers that store and forward encrypted event envelopes. BitChat uses them as a bridge between separate BLE meshes and for delivery when peers lack local connectivity. The NostrRelayManager handles connections, reconnection logic, and optional Tor routing—treating relays as interchangeable infrastructure rather than trusted authorities.
Can I run my own infrastructure to support BitChat?
Yes. While unnecessary for basic operation, you can operate a private Nostr relay and add it through NostrRelaySettings.addCustomRelay(). The relay must support standard Nostr protocol extensions for encrypted direct messages. This provides additional redundancy without centralizing control.
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 →