Nine Versions Later — What the Star Taught Me
From an inverted foundation to the version I'd deploy, KC Star evolved through ten explicit releases in the open. The retrospective on all of it - what versioning a schema publicly taught me about drift, variants, bugs as motivations, and simplicity as the real destination.
I started KC Star to answer one itch — what if dimensions and measures were rows instead of columns — and ended up with ten explicit versions, three parallel stars, a permission system I built twice, and a folder of engines I never built at all. This is the last post, and it is not about any single version. It is about what evolving a schema in the open, keeping every boundary on the record, actually taught me. Nine versions later, here is the retrospective on the whole star.
The road, in one paragraph
V1 inverted the star: dimensions and measures as rows, SCD2, SHA-256 fingerprints, time travel. V2 computed every measure and shipped an aggregate-expiry bug. V3 gave aggregates their own table to kill that bug. V4 added a conscience — quality, lineage, calculation context. V5 grew an org chart and, accidentally, two implementations. V6 added permissions and a changelog describing a system that never existed. V7 went ultra-scale with batch processing and two-pass fix scripts. V8 made recalculation intelligent, mostly. V9 fused permissions with intelligence and got complex enough to need simplifying. And V9 Simplified deleted the cleverness and became the version I would deploy. Ten releases, one idea, evolved in public.
Lesson one: bugs are the best version motivations
The version boundaries I am proudest of were driven by defects, not features. V3 exists because V2's expiry clause leaked per-SaleType aggregates — a real bug I can point at line by line, and the fix (a dedicated table) was structural, not a patch. Keeping the bug on the record made the fix legible: you can read V2, see the leak, read V3, see why the table shape changed. A schema that hides its bugs hides the reasons for its own structure.
The generalisable version: a bug you preserve becomes documentation for the fix that follows it. Delete the bug from history and the fix looks arbitrary. Keep it, and the evolution explains itself. Every version-to-version boundary in KC Star is a small argument, and the strongest arguments start with “here is what broke.”
Lesson two: documentation drifts, and only code doesn't
The most repeated failure across the whole project was documentation drifting from code. The V6 changelog documents SecurityAuditLog, RolePermission, password columns — none of which were built. The V7 feature-flag docs describe a flat table; the code ships six normalized ones. The CHANGELOG count tables match neither the folder nor the root build. Over and over, the prose described a system that the SQL did not implement.
The rule I extracted and applied everywhere: the folder split files are ground truth; everything else is a claim to be checked. When a document and the code disagree, the code is the system, and the way you find out they disagree is grep, not trust. I learned to read the SQL first and the docs second, and to treat every changelog as intent rather than inventory. If I built KC Star again, the single biggest process change would be an integration test that stands the schema up from scratch and runs one sale through — the thing whose absence produced V7's two-pass repair and let the docs drift unchecked.
Lesson three: variants are fine; silence about them is not
V5 shipped two implementations of the same version — a folder build and a root overlay that do not contain the same objects. V9 shipped two permission models in one folder. V4 had two lineage designs. Divergent variants are not inherently a problem — running two live explorations of the same problem taught me more than picking one on a whiteboard would have. V5's push-versus-pull fork is why V7 chose batch with its eyes open.
What hurt was not the drift but the silence about it — no README saying “these are two builds, here is how they differ, here is which one the tests run.” V9 got this right by keeping its naive and optimised paths deliberately and labelling them. The lesson: keep the variants if they earn their keep, but declare them. Undeclared drift is indistinguishable from inconsistency.
Lesson four: the hash is the version's self-image
A small technical delight. The version hash grew at almost every boundary — SaleType in V2, quality in V4, employee and permissions in V9 — and watching what each version folded into its fingerprint turned out to be the most compact way to read what that version believed a sale's identity was. The hash is the schema's self-image, and its evolution is the project's evolution in miniature. If you want to understand what changed at a boundary, look at what the hash started hashing.
Lesson five: simplicity is a destination, not a starting point
The ending is the real lesson. V9 Simplified is the version I would deploy, and it is the version that removes features — the only such release in the project. It deletes permission groups, the group cache, the dual implementation, and keeps only what was correct: the inverted schema, SCD2, selective recalculation, and the NULL-means-redacted discipline.
I could not have started there. V9 Simplified is only possible because V9 built the complex thing first and I got to see, in operation, which parts earned their weight and which were cleverness for its own sake. Simplicity that comes before understanding is just naivety; simplicity that comes after is wisdom, and it looks identical from outside. The whole nine-version arc was the cost of earning the right to build the simple version and know it was enough. You cannot skip to the end — you have to build the complicated thing to learn what to delete.
What the star taught me
Versioning a schema in the open is uncomfortable. Every bug, every drifted doc, every variant I couldn't reconcile, every zero I shipped where I meant a value — it is all on the record, and this series has been me pointing at each one on purpose. But that discomfort is exactly the value. A schema that only shows its polished final form teaches you nothing about how it got polished. KC Star's ten versions are a legible argument, boundary by boundary, for why it is shaped the way it is — bugs and fixes and forks and simplifications, kept rather than airbrushed.
The itch I started with — dimensions as rows — turned out to be the least interesting thing I learned. The interesting thing was the meta-lesson: evolve in the open, keep the boundaries, let the bugs motivate the fixes, distrust the docs, declare your variants, and earn your way to simplicity by first building the complicated version and watching what it costs. That is what nine versions of a star schema taught me, and it is the part that transfers to every system I will build next.
The code stops at V9 Simplified. The wishlist is where it goes if it goes further — four engines designed and unbuilt, honestly labelled, waiting. But the version I would deploy already exists, and it is the simple one. That feels like the right place for a project about turning a star on its side to come to rest.