Validate at the boundary
Parse once, at load, into typed objects. Clamp numbers into the range the code can actually survive — negative cooldowns, zero move-speed, a 99999999 spawner count are all edits a player will make within a week of launch. Unknown keys get a warning, not a crash. A malformed file keeps every default and logs loudly at boot.
A server that boots with defaults beats a server that doesn't boot. That sentence is the whole policy.
Defaults are documentation
Ship a defaults.yml next to the real config, every key present and commented. Add a version key and migrate on load — v1 to v2 adds the new keys, renames the old ones, keeps values where they still make sense. Players copy configs between servers constantly; versioned migration is the only thing that makes that survivable.
Reload without a restart
A reload command and a file watch, both building the entire new config object first, then swapping the reference atomically. Tasks already running keep their old snapshot until they finish their current cycle. Never apply half a config — a half-applied reload is just a slower crash with extra steps.
Test with hostile input for five minutes
Before every release, five minutes of malice against your own parser: negative numbers, zero, absurd maximums, empty strings, unicode names, a file that's one brace short, a YAML alias bomb if you parse YAML. Most "config crashes" are found in those five minutes by the author — or found at 3am by the owner.
RnK is a Minecraft developer with six years in the game — plugins, server setups and performance work across Paper, Spigot and Folia backends. Three networks run day to day; the rest of the time is client work. The bench is open on Discord.