Teissier YannisDeveloper · AI & fullstackLyon · Sept. 2026
Back to the indexProject 04 of 06
04Case study — 2026

A modded Minecraft server, in production
a read-only panel, a measurement journal and a four-fix mod

545 mods, a handful of players, and a tick that went from 120 to 45 ms, every change backed by a profile, every fix a twenty-line mixin, and a supervision panel that cannot write to the server by construction.

Role
Ops, measurement, Go collector, Java mod, web panel
Stack
Go · Java · NeoForge · Spark · Fastify · React · PostgreSQL
Status
In production, mod 1.4, panel online, journal published

The problem

A friends' server running All the Mods 10 (545 mods on NeoForge) was crashing on its watchdog, freezing for seconds when someone joined, and stalling at every auto-save. Nobody could see what was happening, and every "optimisation" advice on the internet contradicted the previous one. I wanted three things: to see the server without being able to break it, to measure before touching anything, and to fix only what the measurements pointed at.

What I built

A supervision panel whose collector is read-only as a property of the code, not an intention: three RCON commands as compile-time constants, an AST test that fails if anything else is sent, a lint that refuses every write symbol, and a systemd sandbox with a read-only filesystem and an empty capability set. It samples the process, the logs, the player list and the tick rate, ships them through a WireGuard tunnel to a worker that rolls them up into PostgreSQL, behind an API with hierarchical roles and a React front end. The collector is deliberately outside the deployment pipeline: nothing automatic ships next to the game server.

A measurement journal: five-minute Spark profiles read by a small tool that decodes the undocumented format, a local bench built from a real backup with ten fake players and a warm JVM, one change at a time, negative results written down. Then a NeoForge mod of four mixins for the four bottlenecks the profiles named: a guard on storage controllers, a binary slot search instead of a linear one, a recipe cache, and a save writer that compresses in memory, writes once, syncs once and replaces atomically. Tick median 120 → 45 ms at four players, watchdog crashes 16 in two days → none, player-file writes 700 → 8 ms, join freezes 6.7 s → 0, auto-save stalls 35 → 6 minutes a day.

fig. 1 — no screenshot, a drawing
Fig. 1 — above, the supervision chain and the wall the collector cannot cross; below, five bottlenecks before and after01

What I learned

That the first version of the guard cut every player off their chests for eleven minutes, because another mod read the controller exactly like the one I wanted to block. So before forbidding a capability, enumerate its legitimate uses, and log every refusal. That a fix worth 14 ms on the bench ejected a player in production. That a reconstructed metric can invert four conclusions, and a profile percentage is not a cost. And that lightening the cluster next door changed nothing at all: hosting contention was not the bottleneck, however much it looked like one.

“A benchmark validates a gain; it does not validate a deployment.”
Next — 05Real-time vision on the edge