What We Got Wrong (And Fixed)
Building a platform means making hundreds of decisions under uncertainty. Some turn out to be right. Some turn out to be wrong. The useful ones to write about are the wrong ones.
Here are a few things we got wrong, and what we did about them.
We Overbuilt the Abstraction Layer
Early in the platform's development, we invested heavily in a very general abstraction for resolving definitions — the configuration objects that define how the platform behaves for each tenant. The abstraction was flexible and elegant, but it was also complex.
The complexity showed up as: hard to debug when something went wrong, hard to optimize for performance, and hard to explain to new contributors. The flexibility it provided was largely hypothetical — we never actually used most of the generality we'd built.
We simplified it. The replacement is less general but faster, easier to reason about, and easier to test. The specific capabilities we actually needed are all there. The theoretical ones we never used are gone.
Lesson: Don't abstract for possibilities. Abstract for the cases you actually have.
We Underestimated the Importance of Inline Editing
In the first version of the platform, all editing happened in forms. Detail pages were read-only; you clicked Edit to open the form, made changes, saved. We thought this was clear and safe — editing is a distinct mode, separate from viewing.
Users hated it. The overhead of switching to edit mode for a single field update was felt constantly, especially for frequent operations like changing a status or updating an assigned user.
We shipped inline editing, and the feedback was immediate and positive. In retrospect, this should have been obvious — users want to work with data, not navigate to a mode that allows working with data.
Lesson: Friction that seems acceptable in the abstract is intolerable in daily use. Watch how users actually work.
We Made Permissions Too Coarse Initially
The first permission system was simple: roles with broad access levels. It worked for simple team structures and didn't work at all for teams with nuanced process requirements. "Can edit invoices" isn't the policy any real business wants — they want "can edit draft invoices, can't edit approved invoices."
Dynamic access rules, shipped later, address this properly. But we shipped a simplified version first and then had to retrofit the more nuanced system.
Lesson: Model the actual access requirements before building the permission system. Simple systems often don't generalize.
Getting things wrong is not the failure. Not noticing, not admitting, not fixing — those are the failures. We're watching for the next set of things we're getting wrong right now.