Long-form notes on the Rust services that run apoptoses, the apoptotic Discord bot, SP-Legends, and Dendrite. New posts roughly monthly. Last updated .
Most of the small-shop guidance online assumes containers, k8s, and a mesh of
sidecars. The apoptoses portfolio runs the opposite shape — one binary, one VM,
one systemd unit per service. Here's why that's worked for me, and the
surprisingly small operational surface it produces.
A pattern I now reach for whenever async Rust meets SQLite: one OS thread owns
the connection, and async code talks to it through a channel. Writes serialize
naturally, the tokio runtime never blocks on disk, and there's no
Mutex<Connection> dance.
SP-Legends polls a small set of Roblox endpoints on a per-endpoint cadence
(20 s fast, 40 s slow) and has held up across multiple upstream API changes.
The cadence isn't arbitrary; the backoff is paranoid; the retry context is
structured and persistent; the alerting is fire-and-forget. A short tour of
how the refresh task is built.
When a Discord bot needs the user's browser to confirm something — like
"two of these accounts share an IP" — you need a handoff between three parties
that don't share a session. HMAC-signed, single-use, time-limited tokens do
that job in about thirty lines.
A walk through the design constraints behind Dendrite — the Windows-specific
scan path, the memory-optimized filesystem tree, and why I deliberately did
not build a cross-platform tool.
The reason Dendrite stays smooth while it's scanning a multi-terabyte volume is
not raw speed; it's that the UI thread does no work. Here's the orchestration
/core/UI split, why nothing in the redraw path is allowed to block, and how
cancellation falls out of the same shape.
Future posts on the queue: a deep dive on the log_store
retention-by-category design, a follow-up on Dendrite's duplicate-detection
pass, and a postmortem on the only Roblox API change that ever broke SP-Legends'
polling. The cadence is roughly one post per month; the
status page is updated more often.