2025-12-21 · retrospective · ~5 min read

2025 year-end retrospective

Eleven releases this year (0.1.5 through 0.2.5), about 14,000 lines of net Rust added, 4,000 deleted. One full architectural rewrite of the merge engine that didn't ship in 2025 but is queued for 0.3 in March. A small but real number of users — about 80 by my last count of unique IPs hitting frostvex.icu/install.sh.

This post is the obligatory year-end "what worked, what didn't" — partly for me, partly so the next person hacking on a small dev tool doesn't have to learn the same things.

What worked

Releasing on a fixed cadence. I committed to a release every 4–5 weeks, regardless of how much was queued up. That meant 0.1.7 went out with one tiny fix and a mildly improved error message — boring, but it shipped. The discipline of "ship something, even if small" beat the urge to wait for the perfect feature set.

Refusing to add a config option. Twice this year I caught myself adding a config option to please a hypothetical user. Both times I deleted the option and picked a default. The codebase is ~6% smaller for it, and nobody has complained. Most config options aren't features; they're abdications.

Writing a benchmark before optimizing. The merge engine rewrite (which will land in 0.3) only became tractable once I had a reproducible bench that showed exactly where the bottleneck was. Before that, I'd been "guessing" and the guesses were uniformly wrong.

What didn't

The pre-allocation experiment in 0.2.0. I shipped a feature that pre-allocated the chunk store on init. It made first-sync 8% faster on spinning disks. It also broke for two users because their VPS had thin-provisioned disks and the pre-allocation showed up as the disk being "full" to the hypervisor. Reverted in 0.2.1.

The 0.1.9 release with the off-by-one in parity blocks. Three users lost data; nobody noticed for a week because the bug only triggered when reconstructing from a single missing parity shard. Caught by a strict verify that I'd written but wasn't running on every release. Lesson: write the verify test, then run it on every release.

Trying to support FreeBSD. Spent two weekends on it. Hit a tokio-quinn issue that needed upstream changes I didn't have bandwidth for. Dropped it from the supported-platform list. Maybe 2026.

Three bugs that ate sleep

One: the 0.1.9 parity off-by-one. Mentioned above. Cost three users actual data and me about ten hours of writing forensics tools to recover what was recoverable.

Two: a deadlock in the peer discovery code that only triggered on machines with exactly two NICs of opposite endianness in their MAC addresses. Took four days to figure out the trigger condition. The fix was a one-line change to a comparison.

Three: a Windows-specific bug where symlinks to long paths (\\?\ prefixed) caused a panic. I have no Windows machine; I had to bisect this remotely with a user over email. They were patient. We figured it out. Shipped in 0.2.5.

What's queued for 2026

The big one is the merge engine rewrite. After that:

If you used frostvex this year — thanks for trying it, thanks for reporting bugs, thanks for not giving up the first time something broke. See you on the other side of the new year.


Wishing you a less interrupted 2026.