The timing problem in design systems
How perfectionism kills component adoption faster than bad code
There’s a point you hit when you’re restoring a car – and it shows up in most kinds of craft – where you stop and ask yourself a quietly embarrassing question: Did I make this better, or did I just keep myself busy?
A few weekends ago, I caught myself right at that point.
Same wheel well. Same sheet of 400-grit. I’d already taken the steel from “rough” to “done”, and then to “actually done”. But there I was, chasing tiny imperfections that only appear at one angle, under one awkward light, if you’re already looking for them. Meanwhile the rest of the to-do list on my whiteboard – suspension, wiring, and forty other jobs that actually mattered – was burning holes in the back of my head.
I see that same moment inside design systems more often than people admit.
The point where momentum dies
System work attracts perfectionism. Components sit at the centre of everything, so the stakes feel higher than they really are – one bad decision feels like it could echo across every product team for years. And that’s usually where momentum disappears.
You open a component to fix something small. Then you tidy something else. Then you adjust a variant you’re not sure anyone needs yet. And before long, you’re polishing a decision that doesn’t change anything for anyone.
Meanwhile, teams aren’t waiting. They never do.
While you’re making a component “just a bit cleaner”, they’re shipping their own versions – a button that’s close but not quite right, a card that solves their immediate need but doesn’t match the system. By the time your version is ready, there are already half a dozen homegrown alternatives in production.
The quality was fine. The timing wasn’t.
The short list of things that can’t be compromised
After enough of these cycles, you learn there’s a small number of things that really can’t be compromised:
Accessibility
Semantic structure
Consistent token usage
A stable API
Sensible defaults that help more than they hurt
Everything else is a judgment call.
I’ve watched teams bypass components because a variant was missing – not because the component was bad, but because waiting wasn’t an option. A slightly inelegant internal abstraction has never stopped a product shipping. But slow delivery absolutely will. A team stuck waiting will drift away from the system faster than you can tidy a prop name.
When you’ve spent enough time working on systems across different organisations, you start to notice the difference between structural work and ornamental work. One impacts everything upstream. The other just feels satisfying in the moment.
Production teaches you things the bench can’t
Back in the garage, when I finally stopped sanding and bolted the suspension into place, a few things I thought were perfect didn’t fit at all. Clearances changed. Angles shifted. A bracket I’d shaped carefully was suddenly wrong once the car had its weight back.
None of that showed up when the part was sitting on my bench.
Design systems behave the same way.
You only learn how a component holds up once a team tries to use it under pressure – with real data, imperfect constraints, and a deadline that isn’t theoretical.
That’s where the missing loading state surfaces. That’s where the rigid prop shows its cracks. That’s where the component you thought covered 90% of cases suddenly covers 60%, if that.
Figma won’t show you any of this. Production will.
What actually gets adopted
The components I’ve seen get the most adoption aren’t the ones with the cleanest code or the most elegant API. They’re the ones that showed up when teams needed them.
They shipped with 80% of the variants teams would eventually need, not 100%. They had a few rough edges that got smoothed out later. They got better through use, not through endless pre-planning.
I think about encouraging design system adoption differently now. It’s less about building the perfect thing, and more about building the right thing at the right time. Teams need something they can actually use today, not something pristine they can’t touch for another three months.
So how do you know when to stop?
I use a simple test now, both in the garage and in Figma: if the next hour of work won’t change how anyone uses this thing, it’s done.
If accessibility is solid, if it works with the tokens, if teams can implement it without breaking things – ship it. The rest can come later, informed by actual use rather than imagined scenarios.
Because while you’re perfecting variant 16, someone’s building their own solution. And once they’ve done that, they’re not coming back.
The best system components aren’t the ones that tried to solve every problem upfront. They’re the ones that solved the immediate problem well enough that teams chose to use them, then evolved based on real feedback from real implementation.
Ship it when it’s good enough. Learn what you missed. Fix it based on what actually matters.
The suspension is waiting.
Thanks for reading! Subscribe for free to receive new posts directly in your inbox.
This article is also available on Medium, where I share more posts like this. If you’re active there, feel free to follow me for updates.
I’d love to stay connected – join the conversation on X and Bluesky, or connect with me on LinkedIn to talk design systems, digital products, and everything in between. If you found this useful, sharing it with your team or network would mean a lot.



