Known limitations
This page exists because the fastest way to lose an engineer's trust is to let them discover a boundary the documentation didn't mention. These are the edges of the current release, stated as plainly as the features are — design around them, and when one of them blocks your integration, say so in your access request: this list doubles as a prioritisation signal. Several edges here are decisions rather than limits; the reasons, and what is built on request, are on the engineering site’s design decisions page.
Data path
- The inner tunnel is IPv4-only. IPv6 works on the underlay — links may bind v6 addresses and peers may have v6 endpoints — but IPv6 packets inside the tunnel, and IPv6
allowed_ips, are not supported today. - No protocol version negotiation. Mixed protocol versions between nodes fail loudly rather than interoperating. Treat fleet upgrades as coordinated events; see compatibility rules.
- Redundancy modes spend real bandwidth.
broadcastand the mirror escalations cost N× airtime by design; the receiver deduplicates, but the spectrum is spent. - Two links on one device and address must use distinct ports — otherwise the kernel load-balances inbound datagrams between the sockets and each link loses half its traffic. Config validation enforces it; the architecture page explains why.
Mesh & peers
- Multi-hop mesh forwarding is hop-by-hop encrypted by default. An Atlas node relaying between two others decrypts and re-encrypts, so it can read the traffic it forwards. Trust your relay nodes with the payload, or seal it end to end with
[crypto] e2eon both endpoints, which has its own limits: unicast only, no FEC class, 67 bytes per packet, no replay window or forward secrecy of its own. Trade-offs: Hop-by-hop across relays. (Traversal relay servers forward opaque envelopes and cannot read them; the two kinds of "relay" have opposite properties.) - Runtime-discovered peers expire after
[mesh] expiry_secs(default 60 s) of gossip silence, destroying their sessions and punched endpoints; under the defaultstaticauth provider an expired discovered peer cannot re-add itself. Configured peers are exempt — they are marked unreachable and kept. Size the expiry generously in discovery-driven fleets. - Relay forwarding is capped at 8 hops by default. The cap is a configuration parameter,
[routing] max_hops, and eight is a chosen default rather than a technical ceiling: the field that carries it allows up to 255. The count is Atlas’s own Layer-3 hops. Where a segment of the underlying network is a MANET or 802.11s mesh, the mesh’s own hops are invisible to Atlas and are not part of the count. - A fleet list travels as one datagram and carries about a hundred records; a larger fleet is split into two networks.
- Admission by pairing code or certificate needs a record fleet. A node that cannot sign the fleet list forwards the records it mints to a config author; an author that is not a neighbour is reached only with
[crypto] e2eon the forwarding node. The node it admitted adopts the author's list only when an anchor it trusts signed it, so until then it staysjoining— known to the fleet from the list, reaching its configured peers directly. A refused record stays on the forwarding node. See admission modes. - Position adverts are rate-limited on the advertising node's own links. A relay re-floods every advert at once on every link, so a mover's position adverts cross a relay's narrow bearer at up to the mover's own rate (one per
position_advert_min_interval_secsby default). See position adverts. - An interconnect seam is hop-by-hop and IPv4, and joins only networks with distinct address spaces. The seam daemon opens an end-to-end-sealed payload and seals it again for the far side. In mapped mode, ICMP error messages generated inside one network carry the untranslated header of the packet that caused them. Two networks that share an address space cannot be interconnected, in either mode. Prefix mode routes the other network's members, not a LAN of hosts that do not run Atlas, and member routes are installed on Linux. With two operator hosts bridging the same pair, traffic moves to the second within seconds. See Atlas Interconnect.
- One routing layer at a time: do not run Atlas mesh routing on top of a radio-layer mesh over the same nodes — two control loops re-routing the same failures fight each other.
Traversal
- Hard-NAT pairs stay on the relay. Atlas does not attempt port-prediction punching; a pair of endpoint-dependent NATs relays indefinitely — correct, but some theoretically punchable pairs remain relayed.
- NAT classification requires two observation IPs. A single-address STUN setup cannot classify the NAT behaviors that predict punch success; Atlas relays answer on two addresses for exactly this reason.
- Punched paths report as
directin stats — there is no distinguishing marker yet, and the routes view does not name the relaying next hop. - Relay federation is one hop and needs end-to-end sealing. A federated path crosses exactly two relays, never three; both must run
[federation] enabled, and a node uses one only when[crypto] e2eseals its egress orfederation_allow_plainis set. The relay directory publishes and looks up records for static[[peer]]entries only, and the number of directory slots is fixed when the daemon starts. See relay directory and federation.
Transport classes
- FEC does not pay on two-link bonds. Surviving a link's death forces the parity floor to ~100% overhead there — the price of plain duplication, which is the simpler tool at that price. FEC's fractional-overhead benefit begins at three links. The daemon computes and reports the effective overhead rather than letting a nominal figure under-protect.
- Fragments of one packet ride one link, always. Cross-link distribution is per packet (Aggregate) or per shard (FEC), never per fragment — striping fragments would multiply loss.
- The pacer cannot hold back what it cannot see. Low-band pacing reads the kernel queue below each link; on a device whose queue cannot be read — a
noqueuedevice such as veth or most Wi-Fi drivers, or a netem root that emulates delay — that link's low band is not paced. A native serial link is paced on its serial line and the radio's own reported buffer; a radio still attached through pppd is not.
Serial radios
- The native serial link is Atlas to Atlas. Both ends of the radio run a build with it. Devices that offer only PPP or IP, and radios that must also carry non-Atlas traffic, stay on the SiK adapter and pppd.
- A shared channel carries one copy per peer. Link-state floods and gossip go out as one unicast frame per peer, not one broadcast frame. When a radio's slot ends mid-frame, frames from two senders can interleave at a receiver; the split frame is lost and counted in
framing_errors. - Atlas does not configure the radio. Serial speed, air rate, MAVLink framing, flow control and multipoint settings are set with the radio's own AT commands;
radio_buffer_bytes(default 2048) is the buffer size the pacer assumes.
Operations
- Keyfile removal needs an evict. A key the keyfile admitted is a known peer, and known peers are not checked against the keyfile again, so deleting its line alone does not end its sessions or stop it reconnecting. Run
atlasd peer evict <key>after deleting the line (or restart the daemon). A signed fleet list removes a node everywhere at once. - Removal by area and geofences rest on self-reported positions. A node that misreports, or moved since its last advert, is placed where it said it was; the review shows each fix's age. A geofence is enforced by the node against its own fix, so a device whose GPS is spoofed or whose software is altered does not enforce it — revoke it; a remote zeroize revokes by default for that reason. A node without a fix never fires its action. Last-known positions live in memory, so a restarted node knows only positions advertised since. See removal by area.
- A release gate reads gossip, not reachability. A
requirednode that is up but whose config status does not reach the pushing node is silent, and silence at the release deadline aborts the release. Give every required node a gossip path to the node that pushes, and do not mark a node required that is routinely out of contact;best_effortis for those. - A retire is permanent for the material. A node that returns after retire and after the lifeline window is refused everywhere and re-enrols through admission with a new record; its old key cannot be re-admitted. Scheduled activation needs a disciplined clock — a node without one activates on receipt, before or after the others. The retire gate waits for required nodes and, for a node key, its subject; a best-effort node whose own key is retired while it is away is cut off when the lifeline window closes, while one that missed only a mesh-secret rotation and still holds a valid transport key is let in and catches up over a session. The relay registry learns revocations, not retires: the lifeline rule is the bootstrap peers' alone. A signing key is scheduled, gated and retired on the same schedule, but its subject signs with the next key only once its config carries it as
[interface] signing_key, a config apply. - Quotas are cost controls, not kill switches. An over-budget link still carries traffic when it is the last usable path — deliberately.
- A few knobs need a restart: notably the traversal netcheck cadence and the gossip interval are read at engine construction; the commit-confirmed apply cycle handles the restart safely, but they are not hot knobs.
disable_encryptionis a benchmarking mode. Both peers must set it; it exists for performance measurement and nothing else.
Feed gateway
- A group is readable inside the fleet, with or without a gateway. Multicast is protected hop by hop and read by every relay on its tree; a feed meant for outsiders should carry nothing the fleet would not show them.
- Mode 1 puts the public side on a full member. An existing subscriber publishing out is often an operator or a config author; use a dedicated
sinkhost (mode 2) for anything shared for a season. - Tokens are bearer secrets. Whoever holds a link holds the feeds it names until it expires or is revoked, unless the link also requires a code sent by another channel; a revocation at the server's own issuer cuts at once, one at another trusted issuer within that issuer's poll interval.
- Two parents are for sinks only, and need a neighbour already on the tree.
[multicast] redundant_parents = 2is honoured on a record flaggedsink; an ordinary subscriber gets one parent. The second parent must already carry the stream for someone else — Atlas never pulls a node onto the tree for the gateway. - A sink sends nothing at all. No ping replies, no backfill gap requests, no dashboard reads through the tunnel; manage the gateway host over its own leg.
- A map shares the fleet's positions. A viewer whose link carries the
positionschannel, from a gateway withshare_positions = true, sees the mesh nodes' names and last positions; both switches default off. - The watermark is an overlay. The player draws it; a technically able viewer can strip it from their own screen. Per-viewer burn-in would need a transcode per viewer.
- Nothing travels inward. No channel carries a command toward the fleet, raw MAVLink included; a partner who needs to fly is a member, not a viewer.
Terrain
- Load the same tiles on every node. Routing weighs each edge from the tiles a node holds. Nodes holding different tiles, or none, weigh the same edge differently, which link-state routing cannot keep loop-free; the hop limit bounds any loop that results.
- Routing follows advertised positions. Routing weighs edges from advertised positions so that every node agrees, so it moves a moving node's shadowed path one position advert after the move — within about a second of moving 25 m with the defaults; that node's own scheduler reacts within one pass. Velocity projection covers
rssi_lookahead_secsahead. - One ridge per path. Diffraction is a single knife-edge at the dominant obstruction; several ridges in a row are not combined.
- The ground, not the clutter. There is no separate clutter or building model: a path clears what the tiles hold. A surface model such as Copernicus GLO-30 includes buildings and canopy; SRTM and NASADEM are closer to bare earth.
- One antenna height.
antenna_height_mapplies to every node, a mast and a handheld alike. - One vertical datum. Tiles and positions are taken to share a datum.
clamp_to_groundhandles the common case of a GPS altitude on the ellipsoid that puts a node below the ground; a fix reported too high is used as given. - Unknown outside the tiles. A position or path off the tiles carries no terrain risk at all.
- The 3D view draws the elevation only. No map imagery is draped over it.
- CPU. A full pass of 512 paths costs about 3 ms on a desktop processor;
max_pathsandinterval_msbound it on smaller hardware.
Platform
- Linux is the supported platform. The Android port (same engine inside a
VpnService) is in active development and not yet a published production release. - Verification context: traversal behavior is proven against simulated carrier-NAT topologies and on production relay hardware; degraded-link behavior is validated with injected loss, delay and link-kill emulation on real multi-radio testbeds. Design your acceptance tests to reproduce your failure modes on your bearers — we will help you scope them.