Peer-to-peer mesh networking
Offline Protocol's mesh SDK lets phones, desktops and gateways hand messages, files and requests straight to each other, so work on site keeps moving without a cloud round trip for every handoff. Every device relays traffic for the others, so coverage grows with density instead of a tower. DORS, our transport layer, runs this mesh over Bluetooth LE and WiFi Direct on a network that has reached 350,000+ devices.
Diagram: a peer-to-peer mesh network failing over from internet to Bluetooth LE and WiFi Direct, relaying an encrypted message between two phones through a relay node with multi-hop routing, acknowledgment, and deduplication.
The internet path drops, and the message reaches unit-19 over two mesh hops.
What is peer-to-peer mesh networking?
Infrastructure is a single point of failure. In a conventional network every device talks to a tower, an access point, or a server. When that fails or saturates, every device attached to it goes silent, however close they are to each other.
A mesh removes the middle. Devices connect directly to their neighbours and forward traffic for one another, so a message reaches a device that was never in radio range. Coverage is the union of every radio, and it grows with every device that joins.
It heals itself. When a node drops out, traffic reroutes around it. A mesh needs no infrastructure, which makes it the answer where towers cannot exist: in disaster zones, underground, in the air, or under deliberate shutdown.
Which transports does the mesh use, and how does it pick one?
It uses five: Bluetooth LE, Wi-Fi Direct, the internet, Reticulum and Nostr. DORS, the Dynamic Offline Relay Switch, is the transport layer we built for Offline Protocol: it treats the five as one pool and moves every message to the best path available at that moment.
What does each transport do?
The energy-efficient backbone of the local mesh: peer discovery and small messages at very low power, on every device by default.
High throughput for bulk data and chunked file transfer when both ends support it. DORS escalates BLE to WiFi Direct under load.
A WebSocket path to a server, treated as one more transport. Losing it triggers failover, not an outage.
A long-range fallback over an external Reticulum daemon, weighted for reliability and energy when local radios cannot reach.
A fallback over Nostr relays with automatic reconnection, so messages still move when only relay infrastructure is reachable.
How does DORS score each path?
- ObserveEvery enabled transport reports seven live factors: signal strength, proximity, bandwidth, congestion, energy, reliability, and load.
- WeightEach transport weights those factors differently. Bluetooth LE leans on energy, WiFi Direct on bandwidth, Reticulum and Nostr on reliability.
- ScoreThe weighted factors become one score per path, from 0 to 100, recomputed continuously as conditions change.
- SwitchTraffic moves to a rival path only when it clears the thresholds below, so the mesh never flaps between transports.
Illustration: a scoring matrix of five transports against seven factors, each cell a bar for that rating, with the weighted score at the end of each row. WiFi Direct leads at 91 and is active; the internet is down at 0. Hovering a factor highlights its column.
Hover a factor to see what it measures.Signal: rssi on ble and wifi links.Proximity: hop count to the destination.Bandwidth: throughput the transport can carry.Congestion: queue depth and backlog.Energy: battery impact of the transport.Reliability: historical delivery success rate.Load: current processing capacity.
When does DORS switch transports?
Only when a rival path clearly wins or the current link is failing, so traffic does not flap between transports.
// Defaults that keep transport switching stable
const dors = {
switchHysteresis: 15.0, // min score gap to switch
switchCooldownSecs: 20, // spacing between switches
stabilityWindowSecs: 8, // settle before switching
rssiSwitchThreshold: -85, // dBm, switch on poor signal
}; How does a message get from one device to another?
It is forwarded hop by hop through nearby devices, toward the best few paths at once, until the recipient acknowledges it. Devices group into clusters, bridges join the clusters, and the reliability layer confirms each delivery.
How do separate groups of devices reach each other?
Through bridges. A device that can see two clusters connects to both, so separate pockets of devices merge into one routable network.
- Member role
- Connections inside a cluster of nearby peers carry traffic within the group.
- Bridge role
- Connections that link two separate clusters. Bridges stitch isolated pockets of devices into one routable network.
- Connection budget
- Each device holds about four peers, scoring every candidate on RSSI, free slots, uptime, battery, stability, and load.
- Self-rebalancing
- The budget rebalances roughly every 15 seconds, and candidates that would bridge clusters get a scoring bonus, so the mesh actively unifies itself.
- Battery-aware relay
- Well-charged devices take on relay duty and devices low on energy shed it, so the mesh balances its own load across the fleet.
- Gradient routing
- A message forwards toward the few best paths at once, not one pre-computed route, so a link that drops mid-flight never strands it.
- Exactly-once delivery
- An 8-hop TTL, acknowledgment, retry, and deduplication give a message many ways to arrive and exactly one delivery when it does.
Can ordinary phones form a Bluetooth and Wi-Fi mesh?
Yes. iOS and Android phones running the SDK link over Bluetooth LE and a direct Wi-Fi peer link, with no extra hardware.
- No special hardware
- The phones people already carry ship with Bluetooth LE and Wi-Fi radios, WiFi Direct on Android and peer-to-peer Wi-Fi on iPhone, and the SDK turns those radios into mesh links.
- Bluetooth LE
- Handles peer discovery and small messages at very low power.
- WiFi Direct
- Carries bulk data, including chunked file transfer up to 100 MiB, when both ends support it. On Android 10 and later the SDK can form the group itself, with no system dialog. iPhones have no WiFi Direct, so between iPhones the same transport runs over the Network framework, on the local network or AWDL. Since SDK 0.29, an Android phone also finds iPhones and Python hosts on the Wi-Fi network it is on, with no group.
- Coverage is the fleet
- Every device that installs an app built on the platform becomes a relay, so density in a stadium, warehouse, or staging area translates directly into throughput and reach. In production that is 350,000+ devices reached in 140+ countries and 11,500+ local networks active this month, grown on product pull alone.
- No base station
- Nothing to deploy and no gateway to keep powered. The network is the devices.
- One npm install
- A TypeScript API in the React Native SDK over a Rust core, with encryption, retry, and multi-hop routing as the default path.
How does the mesh confirm delivery?
The recipient acknowledges every message, and the sender retries with backoff until the acknowledgment arrives or the retry budget runs out.
- Confirmed, not fire and forget
- A message is done when an acknowledgment comes back from the recipient and
message_deliveredfires with latency and hop count. The ACK timeout is about 10 seconds, with up to 1,000 acknowledgments tracked in flight. - Backoff that respects the link
- Retries start at 1 second and double to a cap of 5 minutes, for up to 10 attempts, so a flapping peer is retried quickly at first and then patiently.
- An outbox with a memory
- A message lives in the persisted outbox for up to 7 days. A peer that walks back into range within that window still gets the message it missed.
- Parked, then re-driven
- A message with no path is parked rather than failed: probed on every carrier with a backoff from 15 seconds to 10 minutes, and re-driven the moment a peer reappears or a link returns.
- Safe to relay
- Each device deduplicates by message id, about 5,000 recent ids kept for 7 days across restarts, and every message carries an 8-hop TTL, so multi-hop forwarding processes a message once and cannot loop the mesh.
- Encrypted by default
- Sessions use MLS (RFC 9420) with Ed25519 identities. Relay nodes forward ciphertext, and keys never leave the device.
- A clean contract
- Your application sees sent, then delivered or failed, with the reason and the retry count attached when the budget is exhausted. Every setting above is tunable through
ReliabilityConfig.
Can the mesh carry files?
Yes. A file of up to 100 MiB moves device to device in acknowledged chunks, encrypted with MLS like a message.
- One call to send
sendFiletakes a recipient, the file's bytes, and a name, and returns a file id.sendFileFromPathtakes a path instead, and the Rust core reads the file itself, so a large file never crosses the React Native bridge as base64. The file moves device to device with no upload endpoint and no intermediary host.- Chunked by default
- Files are split into chunks sized for the carrier and reassembled on arrival: 4 KiB over Bluetooth LE, 32 KiB over the Wi-Fi peer link and 256 KiB over the internet. The engine's limit is 100 MiB per file, and in 0.31.0 it cannot be changed through the SDK interface;
sendFileFromPathrefuses a larger file before reading it. - Survives a dropped link
- Each chunk is tracked and acknowledged on its own, so a link that drops mid-transfer redelivers only the chunks in flight. A transfer stays on the carrier it started on for every chunk and every retry.
- Progress and control
- A
file_progressevent reports the percentage complete,getFileProgressreads status by id,cancelFileTransferstops a transfer, andfile_receivedfires on the recipient when the last chunk lands. - Encrypted like a message
- Chunks travel with the protocol's default MLS end-to-end encryption, so a large payload is protected on the wire the same way a short message is.
Where do teams use a device mesh?
Wherever people, machines and devices on one site have to keep handing work to each other: robot fleets, emergency response, industrial crews, and apps that call services on nearby devices.
- Robotics and autonomy
- Swarm coordination across fleets when links and GPS drop.
- Public sector
- Disaster-resilient communication through outages and shutdowns.
- Industrial sites
- Crews, equipment, and gateways keep coordinating off-grid, with the mesh moving with the work.
- Above the transport
- Service discovery turns the mesh into an invocable network of capabilities.
Mesh networking FAQ
Does mesh networking work without internet?
Yes. Devices connect directly over BLE and WiFi Direct and relay traffic for each other, so messages route peer to peer with no internet, no cell tower, and no router. When internet is present, DORS simply treats it as one more transport alongside Reticulum and Nostr fallbacks.
Can phones form a Bluetooth mesh network?
Yes. Ordinary iOS and Android phones running the SDK discover each other over BLE and connect over BLE or a direct Wi-Fi link (WiFi Direct on Android, Apple’s peer-to-peer Wi-Fi on iPhone), forming a mesh that relays messages up to 8 hops with no extra hardware.
How far can a mesh message travel?
Up to 8 hops in DORS. With WiFi Direct links spanning up to a couple hundred meters each, a single route can cover a venue, a convoy, or a neighborhood without infrastructure.
Does mesh networking drain the battery?
Relay duty is distributed by charge level. BLE advertisement is low-power by design, and devices below an energy threshold stop relaying automatically.
Can relay nodes read the traffic they forward?
No. Relays forward MLS-encrypted ciphertext. Only session members hold keys, and keys never leave their devices.
What happens when the internet is available?
DORS uses it as one transport among several, picking the best path per message. Losing it triggers failover to local transports, not an outage.
Can two devices that have never met talk through a third?
Yes. Since SDK 0.29 the key package and the Welcome that start an encrypted session cross the mesh like any other frame, so a device reachable only through another gets its messages, and the device in between carries frames it cannot read.
Can devices out of radio range still reach each other?
Yes. When no mesh path exists, the hosted relay carries MLS-encrypted messages between devices over the internet, enabled per app in the developer portal. Hosted relay deliveries are metered, 10,000 a month on Free, 100,000 on Pro, and 1 million on Scale, then $0.50 per 1,000, and local mesh traffic never is.
How does the mesh form?
Each device evaluates discovered peers against a connection budget of about four peers and a live score built from signal strength, free slots, uptime, battery, stability, and load. Peers in the same local group connect as members; peers in different groups connect as bridges, which is how separate pockets of devices merge into one routable mesh. The budget is rescored and rebalanced roughly every 15 seconds.
How is delivery confirmed?
Every message carries a unique ID and an 8-hop TTL. Receivers acknowledge, senders retry on timeout, and duplicates are dropped by ID, so the application sees exactly one delivered or one failed outcome per message.
What transports does the mesh run over?
Five: Bluetooth LE for energy-efficient local mesh, WiFi Direct for high-throughput links on Android (the same slot runs over the Network framework on iPhones, and since SDK 0.29 over a shared Wi-Fi network between iPhones, Android phones, and Python hosts), the internet as a WebSocket backhaul, Reticulum for resilient long-range fallback over an external daemon, and Nostr for a fallback over WebSocket relays. DORS scores whichever are enabled and moves traffic to the best one per message.
How does DORS avoid flapping between transports?
Three safeguards. A 15-point hysteresis means a rival transport must score at least 15 points higher before a switch, a 20-second cooldown spaces switches out, and an 8-second stability window requires the current transport to settle first. It escalates BLE to WiFi under load and switches away on poor signal, around -85 dBm.
How does a message get delivered when the recipient is offline?
It is held in the persisted outbox for up to 7 days and retried with exponential backoff, 1 second doubling to a 5 minute cap, for up to 10 attempts. A message with no path at all is parked and probed on every carrier, then re-driven the moment the peer reappears. If the peer comes back within the window, the message is delivered and message_delivered fires.
What stops a message from circulating the mesh forever?
Every message carries an 8-hop time-to-live that is decremented at each relay, and every device deduplicates by message id, tracking 5,000 recent ids for 7 days across restarts, so a message is processed once and dropped when its TTL reaches zero.
How large can a file be?
Up to 100 MiB. The engine splits a file into chunks sized for the carrier the transfer starts on, 4 KiB over Bluetooth LE, 32 KiB over the Wi-Fi peer link and 256 KiB over the internet, and in 0.31.0 the size limit cannot be changed through the SDK interface. Each chunk is acknowledged on its own, so a dropped link costs only the chunks in flight.
Are transferred files encrypted?
Yes. File transfer rides the same machinery as messages, including MLS encryption, DORS transport switching, and the acknowledgment and retry layer.

