What Forking Your Platform Costs: Measurements From Three Installs
Forking costs you the ability to fix anything once. We forked our own system twice and measured the result: 60 shared migration numbers of which 29 carry the same number and different content, and 11 tables out of 103 still identical column for column. The intended shared core was 80%. The measured figure was closer to 25%.
What we did
One operating system was built for a real operator and ran their business. It was then forked deliberately for a second market, and later copied again for a third. This is the ordinary path: the second customer needs it slightly different, copying the repository works, it ships, and nobody argues with the decision at the time.
Some months later we read all three databases directly rather than trusting the architecture diagram.
What we found
| What was measured | Result |
|---|---|
| Migration numbers shared across the three | 60 |
| Byte-identical | 31 |
| Same number, different content | 29 |
| Tables across all three systems | 103 |
| Present in all three | 24 |
| Identical column for column | 11 |
| Shared tables that drifted after the copy | 13 |
| Tables unique to one system | 45 · 46 · 23 |
| Intended shared core | ~80% |
| Measured shared core | ~25% |
The line that matters
Twenty-nine migrations carry the same number and different contents. That is the whole finding in one row. It means a fix written against migration 042 in one system cannot be applied to the others, because their 042 is a different change. The version numbers agree and the code does not.
The moment two systems disagree about what migration 042 was, you are maintaining two products that share a name.
The part that was supposed to diverge
The central business object differs by 41 columns between two of the systems. That is not the bug. The main object a business manages — the property, the patient, the job, the policy — should differ per vertical. That is the configurable fifth of the system doing its job.
The bug is that the plumbing forked too. Authentication, tenancy, permissions, migrations, deployment and observability have no business differing between installs, and they did.
Nobody decided to drift
Thirteen tables started identical and changed shape separately afterwards. No meeting was held about it. Each change was small, correct in its own context, and made under delivery pressure by somebody who had no way of seeing the other two systems at that moment.
This is why "we will keep them in sync" is not a plan. Staying in sync is not a decision made once; it is a decision that has to be made again on every commit, by whoever is closest to the deadline.
You cannot merge the past
The uncomfortable half: once installs have drifted this far, they stay the first of their own line. Merging them costs more than leaving them. The compounding starts with the next install, not by rescuing the last three.
That is worth knowing before you promise a customer a date, because the instinct is to promise the clean-up and the arithmetic does not support it.
What to do instead
Extract the plumbing into a shared package and let the next install be its first consumer. Keep it small — our measurement says the genuinely identical part is about a quarter of the system, not four fifths, and a core that claims more than that will be wrong in a way that costs you later. Then read the four questions that decide what belongs in it.
Which rung is your system actually on?
The Platform Readiness Review is seven days and $2,500. A map of what you have built, where the core-versus-configuration boundary really falls, the assumptions that break when a second business signs, and a 90-day plan including what to postpone. If it is not ready to be productized, we say so and you keep the map.