Versioning the schema I didn't have yet
I added a __schemaVersion field to Beacon's config file before there was a v2. Three weeks later, I needed it. The case for stamping a version on every stateful file you ship.
Beacon stores a creator's entire site config in a single file: state.json. The builder reads it, the build pipeline reads it, the UI writes back to it. One file, one source of truth.
The first version of state.json had no version field. There was no v2 to migrate to. There was no v0.5 left over from a previous design. There was just the shape of the data and a builder that read it.
I added __schemaVersion: 1 anyway. Two minutes of work. No real reason to do it that day.
The reason showed up about three weeks later.
The Last.fm tile became the Now Playing tile, with ListenBrainz as a second source. The shape of widgets.lastfm was no longer the shape of widgets.nowPlaying. Existing user configs needed to migrate forward. Without the version field, the migration code would have to detect the old shape from the data itself: heuristics, branching, brittleness. With the version field, the migration was four lines:
if (state.__schemaVersion < 2) {
state.widgets.nowPlaying = migrateLastfm(state.widgets.lastfm);
delete state.widgets.lastfm;
state.__schemaVersion = 2;
}Then the Hardcover tile became the Now Reading tile (Goodreads as a second source). v3. Four more lines.
Then Steam moved to build-time snapshot mode. v4.
Each migration was a handful of lines because the load function knew exactly what version of the data it was reading. A user's state.json last touched four versions ago migrates forward through all four steps the next time they open the builder. They don't have to know a field renamed or a shape moved.
This isn't profound. It's the kind of thing every senior engineer learns the second time they write a migration. I'm writing it down because I've been on the wrong side of this decision before. When you're about to ship a stateful file format, stamp a version on it. Even if you don't need it. Especially if you don't need it.
The day you need it, it's already too late to add it.