# Does BitChat Have a Server Architecture? Understanding Its Decentralized Design

> Explore BitChat's unique serverless architecture. Discover how it uses BLE mesh and Nostr relays for decentralized communication without traditional servers. Learn more today.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: architecture
- Published: 2026-08-01

---

**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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/MessageRouter.swift) serves as the central decision engine. It implements a priority-based routing strategy:

1. **Active BLE link** — preferred for local, low-latency delivery
2. **Nostr relay path** — fallback for internet-wide reachability
3. **Courier system** — invoked when neither transport can deliver promptly

The `send(_:completion:)` API exposes this routing logic to higher-level components:

```swift
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`](https://github.com/permissionlesstech/bitchat/blob/main/ARCHITECTURE_V2.md) acts as the composition root, initializing and wiring together:

- BLE service startup
- `NostrRelayManager` instantiation
- 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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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:

```swift
let dependencies = NostrRelayManagerDependencies.live()
let nostrManager = NostrRelayManager(dependencies: dependencies)

```

Adding a relay persists to `UserDefaults` and refreshes the active connection pool:

```swift
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`](https://github.com/permissionlesstech/bitchat/blob/main/docs/ARCHITECTURE_V2.md) | Runtime layer, store architecture, and feature-scoped model design |
| [`WHITEPAPER.md`](https://github.com/permissionlesstech/bitchat/blob/main/WHITEPAPER.md) | Complete protocol specification including dual-transport rationale |
| [`bitchat/Nostr/NostrRelayManager.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrRelayManager.swift) | WebSocket connection management and relay statistics |
| [`bitchat/Services/MessageRouter.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/MessageRouter.swift) | Transport selection and courier invocation |
| [`bitchat/ViewModels/ChatViewModelBootstrapper.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/ViewModels/ChatViewModelBootstrapper.swift) | Runtime initialization and component wiring |
| [`docs/TOR-INTEGRATION.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/TOR-INTEGRATION.md) | Tor anonymization implementation |
| [`docs/BLE-ARCHITECTURE-V3.md`](https://github.com/permissionlesstech/bitchat/blob/main/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.