On Shipping Things That Are Good Enough
There's a project I've had half-built for about fourteen months. I keep opening it, adding something, convincing myself it needs one more thing before it's ready to show anyone, and then closing the laptop.
I know exactly what's happening. The version of it in my head is coherent and complete. The version on my hard drive is a mess of reasonable decisions made at different times by a person who was figuring things out as they went. Shipping it means accepting the gap.
The Gap Is the Work
I used to think the gap between what I imagined and what I built was a sign that I wasn't good enough yet. That with more skill or experience, the gap would close.
It doesn't close. You get better and the imagined version gets more ambitious at roughly the same rate. The gap is just a permanent feature of doing creative work. The question isn't how to eliminate it — it's whether you ship anyway.
What "Good Enough" Actually Means
Good enough isn't a compromise. It means:
- The thing does what it says it does
- It doesn't embarrass you
- Someone can actually use it
That's it. Good enough is not a ceiling — it's a floor. You're allowed to make it better after you ship it. In fact, you'll make it better faster once it's out, because real use surfaces problems that months of thinking about it never will.
The Accumulation Problem
The longer you sit on something, the more it accumulates. More features. More edge cases to handle. More imagined user scenarios to account for. More things that feel like they need to be solved before it's "ready".
This is why things that take three weeks of focused work somehow take eight months of intermittent work. The code isn't the bottleneck. The accumulation is.
I've started deliberately picking an arbitrary ship date before I'm ready. Not a deadline — more of a forcing function. Something like: "I'm going to show this to five people on Friday, whether or not the settings page exists."
Readability Over Cleverness
One thing I've noticed: the projects I ship fast tend to be the ones with the most boring code. No clever abstractions, no optimised architectures, no framework I was excited to try. Just straightforward, readable, slightly repetitive code that does the thing.
The projects that drag on forever tend to be the ones where I got interested in the implementation. I stop building the product and start building the infrastructure for the product. The infrastructure never ships.
None of This Is Advice
I'm still sitting on that half-built project. Writing this down is mostly a way of making myself feel like I've done something about it without actually doing anything about it.
But I think the real thing I'm avoiding isn't the imperfection of the shipped version — it's the loss of the imagined one. Once you ship, the thing in your head is replaced by the thing in the world, and the thing in the world is always smaller.
Maybe that's fine. Maybe that's just the deal.
I'm going to open the laptop now and try to ship something.