10 design system mistakes that wreck consistency at scale
Buttons multiply, tokens drift, components fork. The 10 design system mistakes that quietly turn a product into a parts bin, and the fixes.
A team ships its tenth feature of the quarter. Eight contain new buttons. Three of those buttons look almost like the design system primary button, but each carries a slightly different padding, radius, or shadow. Nobody made the call to fork. Everyone just shipped. This is what design system inconsistency looks like at scale: not one bad decision, but a thousand small ones nobody had to defend.
The mistakes below are the ten we keep finding when we run a design system audit on a product that grew faster than its system. None of them are exotic. All of them compound. The good news: each has a fix that is mechanical once you decide to pay for it.
1. Treating the design system as a side project
The mistake: nobody owns the system. A senior designer keeps it alive in 20% time. Engineering treats fixes as "we will get to it". There is no roadmap, no on-call, no release notes.
What it costs: every contributor reinvents what is missing. The library accumulates near-duplicates because nobody has the authority to decline a pull request that adds a 41st button variant.
The fix: assign a real owner with a percentage of their time formally allocated, a public roadmap, and a single Slack or Linear queue. A defined component lifecycle (propose, review, build, document, release, measure, deprecate) turns a parts bin into a product.
2. Adding a component for every new design
The mistake: every new feature adds two or three components to the library. Six months in, the team cannot tell whether to reach for Card, CardCompact, CardWithHeader, or CardLegacy.
What it costs: trust. Sprawl undermines the very benefits design systems are supposed to create. Teams stop reaching for the library because they cannot navigate it.
The fix: a strict criterion for promotion to the shared library. We use three: the pattern appears in at least two unrelated features, it has been stable for at least one release, and a designer plus an engineer have signed off on the API. Everything else stays local until it earns the upgrade.
3. Skipping the semantic token layer
The mistake: components reference primitive tokens directly. Button uses color-blue-500 instead of color-action-primary. The semantic layer never gets built because "we will add it later".
What it costs: every theme change becomes a global find-and-replace. Most systems define generic primitive tokens that are aliased to purposeful uses of space and color. Without that aliasing, you cannot ship dark mode without rewriting every component.
The fix: three layers. Primitives hold values (color-blue-500 = #3B82F6). Semantic tokens hold intent (color-action-primary points to color-blue-500). Component tokens hold local decisions (button-bg-default points to color-action-primary). Components reference the semantic or component layer, never the primitive. We covered the tradeoffs in tokens vs CSS variables vs Tailwind.
4. Letting local overrides become normal
The mistake: every product team forks a component "just for this view" and changes one prop. Six months later, half the surfaces use the override and half use the base. The system has two truths and no way to pick one.
What it costs: design drift. Local overrides to spacing, color, typography, or component props become normal, slowly fragmenting the system until "what is truly standard" is a question nobody can answer.
The fix: track the override rate as a first-class metric. If a component is overridden in more than 10% of its instances, the system is missing a variant and the override is the signal. Either fold the override back in as a supported variant, or kill it and the use case it served.
5. No variant budget
The mistake: a button started with three variants. By the second year it has 22, including primary-with-icon-on-right-disabled-loading.
What it costs: the team that should be building features is now spending Tuesday afternoons arguing over which existing variant to use. Storybook becomes a maze.
The fix: cap variants per component. We use a budget: a component over five variants triggers a review. Adding a new variant requires deprecating an old one or proving the new one cannot be expressed by composing existing primitives. The cap is artificial. The discipline is real.
6. No deprecation path
The mistake: components only get added, never removed. ButtonV1 stays alive next to ButtonV2 because removing it would break six pages nobody on the current team owns.
What it costs: confusion at the import layer ("which Button do I use"), bundle bloat, and an audit cost that grows linearly with library age.
The fix: a quality tier system. Experimental, Beta, Stable, Deprecated, Removed. A component lives in Deprecated for two release cycles with a codemod available, then it is removed. We commit to that calendar publicly, in the changelog, on the day we deprecate.
7. Naming tokens by value instead of intent
The mistake: color-red-600, spacing-16, shadow-large. The names describe the visual output. The day the brand changes red to magenta, every name lies.
What it costs: a name like color-text-red describes a visual value, which means the name breaks as soon as the color changes. A name like color-text-error describes intent and stays stable.
The fix: name by why. color-feedback-error, spacing-stack-md, elevation-overlay. The first time a designer pushes back ("but it is red"), explain that the system serves the next five years, not today's mockup.
8. Treating Figma as the source of truth
The mistake: the design library lives in Figma. Engineers translate it to code by hand. The two diverge within weeks.
What it costs: a handoff problem dressed up as a design system. Every release, design ships components engineering has not implemented, and engineering ships fixes design has not absorbed. The audit gap widens until somebody runs a manual reconciliation nobody wants to repeat.
The fix: code is the source of truth. Tokens live in a single repository as JSON or a typed export, and Figma reads from it via Variables and a sync tool. Components have one canonical implementation; design provides annotated specs, not parallel sources. The Figma library mirrors the code library, not the other way around.
9. No measured adoption metric
The mistake: nobody can answer "what percentage of UI uses the design system". The team estimates 80%. The audit finds 38%.
What it costs: it is hard to say what constitutes a healthy count without a goal. Without measurement, every conversation about the system is anecdote against anecdote.
The fix: instrument coverage. Static analysis on the codebase reports the ratio of design system component instances to bespoke ones, broken down by surface. Mews built theirs from production data, scanning the React tree at runtime. We run a similar scan in our own ops, weekly, and treat any drop as an incident.
10. Designing the system around designers only
The mistake: the system is gorgeous in Figma and painful in code. Component APIs are inconsistent, props are named for visual concepts engineering does not use, accessibility primitives are missing. Engineers route around the system rather than fight it.
What it costs: adoption stalls. Engineering writes its own primitives, design audits them and finds drift, the cycle repeats.
The fix: bring engineering into the system from day one. Component APIs are designed alongside the visual specification, not after. Accessibility is a hard requirement on every component (focus management, keyboard handlers, ARIA roles). The system ships as a package an engineer can install and import in one line, not as a Figma library plus a wiki page. A custom system that engineers refuse to use is the worst of both worlds.
The pattern under all ten
The common thread: a design system is governed or it sprawls. The mistakes above are not failures of taste or talent. They are failures of governance. A roadmap, a budget, a tier system, a measurement, an owner. None of them are exotic and none of them require a new tool. They require somebody to decide that the system is a product and to treat its evolution like one.
The systems that hold up at scale share a quiet rule: every new component, variant, token, or override has to justify itself against the cost it adds. The default answer is no.
Sources
- UXPin: Design System Governance, A Guide to Prevent Drift
- UXPin: Prevent Design Drift, Design System Governance Guide
- Path to Project: How to Govern Component Sprawl in a Design System
- Nathan Curtis (EightShapes): Naming Tokens in Design Systems
- Smashing Magazine: Best Practices For Naming Design Tokens, Components and Variables
- Brad Frost: Atomic Design, Chapter 5, Maintaining Design Systems
- Figma: Design Systems 104, Making Metrics Matter
- Mews: Building a design system adoption metric from production data
Studio
Start a project.
One partner for companies, public sector, startups and SaaS. Faster delivery, modern tech, lower costs. One team, one invoice.