One build flag, 20× faster
The morning after the first mesh came alive, it was pushing a 61.9 GB photo library across the room at 1.2 MB/s. Fourteen hours to finish. By breakfast it was doing 23.8 MB/s — and the fix that mattered was embarrassingly boring.

The suspects
The obvious theories were all about the protocol. Every shard was written strictly one at a time — send, wait for the peer's acknowledgement, send the next — so throughput was capped by round-trip latency rather than bandwidth. With ~19,000 photos, nearly every file is a single chunk whose shards each pay that full round trip. Both true, both worth fixing. Neither was the story.
Then came the question that cracked it: "wait — are these two Macs even talking over the LAN, or are they going out through the VPN?" Checking meant measuring the raw link, so: pipe 100 MB over SSH between the same two machines. 20 MB/s. The network was fine. Recilic was using six percent of a road it already had.
The unglamorous answer
The dev builds were Debug builds. So I benchmarked the hot path in both configurations, 8 MB through each stage:
erasure-encode (our Swift): 3.2 MB/s → 142.9 MB/s (44×)
ChaChaPoly seal (CryptoKit): 958.8 → 958.5 MB/s (1.0×)
SHA-256 (CryptoKit): 3260 → 3156 MB/s (1.0×)
chunk split (our Swift): 1965 → 2080 MB/s (1.1×)
The entire deficit lives in one place: the GF(256) erasure coder. The crypto was never slow — CryptoKit ships pre-optimized inside the system, so your build settings can't hurt it. But the coder is our Swift, multiplying every single byte through a lookup table. With optimizations on, gfMul inlines into a tight loop, the Data retain/release traffic disappears, and whole-module optimization inlines the tables across files. With -Onone, every byte pays a real function call plus reference counting.
Why a build flag can be worth 44×
Imagine you have to stamp 66 billion envelopes. That's roughly what the coder faces: 61.9 GB is 66 billion bytes, and it multiplies every one of them four times over — a few hundred billion tiny operations. Each operation itself is trivial: look up two numbers in a table, combine them. It's the paperwork around each operation that decides your afternoon.
Debug mode is doing it like this: for every single envelope, walk to the supply room, fetch the stamp, walk back, stamp it, return the stamp, then write a line in a logbook. The stamping is instant. The walking is everything.
Release mode keeps the stamp in your hand and throws the logbook away.
Translated back: the walk to the supply room is the function call, which the optimizer inlines straight into the loop; the logbook is automatic reference counting, which the optimizer proves unnecessary and deletes. Neither changes what the program computes — only how much ceremony surrounds each byte.
And that's why Apple's crypto is immune: it shipped sealed, already in stamp-in-hand mode. Your build settings can't reach inside it. Only the code you write yourself pays the debug tax — and it pays it once per byte.
And the numbers line up exactly: a 3.2 MB/s coder, minus I/O and framing overhead, is the 1.2–2 MB/s we were seeing. A 142.9 MB/s coder is far above the 20 MB/s network — so the bottleneck moved to the wire, which is where it belongs.
Rebuilt with optimizations: 1.2 → 23.8 MB/s, which is above the 20 MB/s we measured over SSH. The backup that needed fourteen hours now needs about forty-five minutes. The bottleneck is the Wi-Fi link, exactly where it should be.
The fixes that were still worth making
The protocol theories weren't wrong, just outranked — and they shipped anyway, because at line rate the remaining latency actually matters:
Concurrent shard writes. A chunk's six shards are now written in parallel instead of serially. If one fails, the whole group is still drained so every shard that landed gets registered for cleanup — a partially-written backup must never leave orphans behind.
A connection pool. Four channels per peer, so concurrent writes overlap their round trips instead of queueing behind one pipe.
Two papercuts from real use. A laptop that slept mid-transfer used to hang the backup forever on a dead socket — now TCP keepalives plus per-request deadlines surface it as "peer unavailable" within a minute, and the next backup reconnects. And the first connection after launch could fail once while macOS rebuilt its local-network permission cache; it now retries itself, so nobody sees it.
One bug fixed for good measure: pressing "Back Up Now" while a prerequisite was missing did nothing at all — silently. A button that looks clickable and answers with silence is worse than an error message. It now says exactly what's missing.
The lesson, written down
Recilic 0.1.0 is on the Mac App Store at a founding price of $9.99. The mesh ships as a free update — and yes, at line rate.