How MeshCore works
Direct messages · Channels
Part 1 · Direct messages (DMs)
The basic idea
A direct message is end-to-end encrypted – only your contact can read it; the repeaters just pass it on without reading along. The interesting question: how does your device know the way to the recipient? Short answer: the first time, it doesn't yet – it has to discover it first.
Step 1 — The first message: "Flood"
When you message a contact for the first time, your device doesn't know a way to them yet. So it sends the message as a flood – meaning roughly: "Everyone in range: please pass it on." Every repeater that hears it forwards it exactly once (not endlessly – duplicates are discarded). It spreads through the network like a wave until it reaches the recipient. The clever part: each repeater stamps its short ID into the packet as it passes. Along the way the message collects the list of stations it travelled through – and that list later becomes the path.
Step 2 — The confirmation (ACK) travels back with the path
When the message reaches the recipient, their device decrypts it, shows it, and sends a delivery confirmation back – the ACK. The ACK is the proof that the message really arrived.
Because your device doesn't know the way yet, the recipient packs the path and the ACK into a single packet (the "path return") and sends it back. Since the return route is also still unknown, this one packet floods just the same through the network. From it your device learns which repeaters reach your contact, remembers the path, and marks the message as delivered. Until the ACK arrives, it stays on "sending".
This flooding of the return trip only happens for the very first message – that is, as long as no path is known yet.
Step 3 — Follow-up messages: "Direct"
From here on it gets efficient – and in both directions. For every further message your device writes the remembered path straight into the packet and sends it direct. Now only the repeaters on the path forward it; all others stay quiet. And the ACK now comes back directly along the known return path too – no longer by flooding. The outbound and return trips don't have to use the same repeaters: each direction has its own path.
First contact = flood once (there and back) to find the way. After that = direct along the path you found, in both directions.
Where it gets tricky — common problems
- First contact is expensive. The first message floods outward – and the path return with the ACK floods back. On a busy network that costs a lot of airtime, and simultaneous transmissions can collide.
- The confirmation can get lost. If the ACK is lost on the way, your message stays on "sending" – even though your contact may have read it long ago.
- Radio doesn't always work equally well both ways. Two devices don't necessarily hear each other equally well: sometimes your message arrives fine, but the return path is too weak for the confirmation. Then your contact reads the message, yet the checkmark never appears – to you it looks like "not delivered", even though it arrived long ago.
- Range / hops. A message travels over at most 64 stations (a technical limit; in practice far fewer). If the recipient is too far away or there is no chain of repeaters, nothing arrives.
- The remembered path goes stale. If a repeater on the path is switched off, relocated, or someone moves out of range, the direct route leads nowhere – and no more ACK comes back.
When flood, when direct — and when back to flood
- No path known (new contact or path forgotten) → flood
- Path known → direct (message and ACK)
- Direct fails (no ACK within the waiting time, even after a few automatic retries) → your device discards the path and sends the next attempt by flood again, to find a fresh route.
That's the self-healing mechanism: a broken path automatically falls back to flooding and is rebuilt. (You can also trigger a path search by hand in the app.) By the way, after sending, your device waits a calculated time for the ACK – longer for flood than for direct.
On your companion you set a default region. It decides which scope a flood uses: every flood message (first DM, channel messages) gets a code derived from the region – and only repeaters of that region forward it. This keeps the regional network manageable instead of every message flooding everywhere. (With no region set you flood "globally" – every repeater forwards.)
The catch: the recipient sends the path return with the ACK using their own default region – not yours. If you and your contact have different default regions, and no repeater bridges both, the message may well arrive but the ACK can't find its way back to you – you see "sending", even though it was read.
Good to know: this only affects the flood phase. Direct messages follow the fixed path and are not region-bound – once a path is established, the region no longer matters for that contact. (More on regions: Why Regions?.)
Part 2 · Channels (group messages)
What is a channel?
A channel is a group that shares a key. Whoever has the key is in – they can read and post. A public channel is simply one whose key everyone knows; a private one has a key only your circle holds. There is no member list and no sign-up: the key is the membership.
Channels always flood
With a DM there is a single recipient you can find a path to. With a channel there isn't one – the message is meant for everyone. So there is no path to find: channel messages always flood (like the very first DM, but permanently). Every repeater forwards each one once, until it has spread across the regional network.
No checkmark – no delivery confirmation
The most important difference from DMs: channels have no ACK. Nobody sends a delivery confirmation back (with many recipients that would just be a confirmation storm). Concretely that means:
- You don't know who received your message.
- Anyone offline or out of range right now misses it – it is not delivered later.
- So there is no "delivered" checkmark like with DMs.
(Delivering missed messages later is something only room servers do – more on those later.)
Who wrote that? – Careful
In a channel message the sender name is just text inside it ("Name: message"). It is not cryptographically verified – unlike DMs, where the sender is pinned down by their key. On a channel anyone with the key can in principle post under any name. Fine for chit-chat; for anything that matters, DMs are the right way.
Region matters here too
Which repeaters carry a channel message depends on its region. You can assign a channel its own region – that one then wins. If you don't, your default region applies; if that isn't set either, the message goes out globally to every repeater. So a local channel stays local – people in another region only hear you if a repeater bridges both. (Repeaters may also cap flood traffic beyond a hop limit, to protect airtime.)
DM vs. channel – at a glance
| Direct message | Channel | |
|---|---|---|
| Recipient | one person | everyone with the key |
| Route | flood first, then direct (path) | always flood |
| Confirmation (ACK) | yes (checkmark) | no |
| Sender verified | yes (key) | no (text only) |
| Missed? | stays "sending" | gone (unless room server) |
Part 3 · Adverts (announcing yourself)
What is an advert?
An advert is your business card on the network: your device calls out "hi, I'm here" and sends your name, your public key and optionally your position. It is signed – so it can't be spoofed: nobody can impersonate you (unlike the freely chosen name on a channel). This is how contacts appear: as soon as someone hears your advert, you show up in their contact list and they can DM you.
Two ranges: zero-hop and flood
- Zero-hop ("zero jumps"): only to everyone in direct radio range – no repeater forwards it. Frugal, ideal for announcing yourself to your neighbours.
- Flood: forwarded by every repeater and spread across the whole (regional) mesh – people far away get to know you too. Long reach, but expensive.
| Zero-hop | Flood | |
|---|---|---|
| Reach | direct neighbours only | whole region (via repeaters) |
| Repeaters forward it? | no | yes |
| Airtime cost | minimal | high (every repeater chimes in) |
| What for | a quick local hello | becoming findable everywhere |
Who sends when?
Your device only sends an advert when you trigger it (advert button). Repeaters can flood-advert automatically on an interval (factory setting: every 47 h) – but that should be set deliberately:
Best to turn the flood advert off (set flood.advert.interval 0) and use zero-hop only – the repeater becomes known to its neighbours anyway and sits in the paths of normal traffic. If you really want flood, set it to the maximum of 168 h.
Set a region. With a region configured, the flood adverts (and all floods) stay within the region. Without a region the repeater floods globally – its adverts then leak into other regions and cost airtime there too.
Why frequent flood adverts are a problem
A flood advert costs just as much as the first flood DM: every repeater in the region rebroadcasts it once. And unlike a message it carries no content – it is pure "I'm still here" overhead. When many devices flood-advert often:
- each of these adverts occupies the shared radio channel many times over;
- that airtime is missing for real messages – and it counts against the repeaters' legal 10% limit (see Why Regions?);
- too much advert traffic can downright clog a dense network.
That's why MeshCore builds in several brakes: repeaters advert rarely by default, adverts are forwarded with lower priority (real messages go first), adverts have a tighter hop limit than normal floods, and the firmware enforces minimum intervals.
A flood advert is expensive and carries no content. Repeater operators: flood off (0) + zero-hop + set a region; 168 h in a pinch. Regular users: only press the flood-advert button when you genuinely want to be findable far away – not out of habit.