Design debt is how far the product as built has drifted from its design system and design intent. It builds one small, unfixed difference at a time: a hardcoded color, a padding value set by eye, a new screen copied from one that had already drifted.
It gets paid down the same way, in small pieces. Teams fix it in code on a regular rhythm, and they point every copy at the source (the token or the component) so the next fix happens once. Review rules stop new debt from merging. Most of the list is small enough that the designer who found it fixes it in code. A redesign can reset the balance, but the habits that built it stay.
Key takeaways
- Design debt "accrues interest that compounds on itself over time" (Austin Knight). Every copy of a drifted screen is one more place a fix has to reach.
- Pay it down on a rhythm. At Linear, Quality Wednesdays are a weekly slot for small fixes: "Many of these quality fixes take 30 minutes or less."
- Stop new debt in review. Tailwind theme variables can limit a codebase to the team's own values, and lint rules such as no-arbitrary-value flag one-off ones.
What is design debt?
Definition
Design debt is the accumulated gap between the product as built and the design system and design intent it was meant to follow.
In his essay Design Debt, Austin Knight describes how "the cohesion and consistency of a design deteriorates over time" as teams run experiments and add new elements. He sets it beside its older sibling: "where Technical Debt affects the integrity of the codebase, Design Debt affects the integrity of the user experience."
Design debt examples: UI inconsistencies nobody chose
In a product, design debt shows up as UI inconsistencies that nobody chose:
- Several button styles where the design system defines two.
- Hex values such as
#6B7280where a color token belongs. - Arbitrary Tailwind values such as
top-[117px]where the spacing scale should be. - Near-duplicate components: a card, a "new" card and a settings card that differ by a few pixels of padding.
- States invented per screen, so the error message looks different on every form.
A design QA pass on each pull request catches these before merge. Design debt is what ships unfixed.
How does design debt accumulate?
Martin Fowler separates prudent from reckless technical debt, and notes that "there's also a difference between deliberate and inadvertent debt." Design debt splits along the second line.
Deliberate debt is a decision. GitLab's UX handbook names it: "Deferred UX results from the intentional decision to deviate from the UX vision or MVC." MVC is GitLab's minimal viable change. Written down, deliberate debt stays manageable.
Inadvertent debt is nobody's decision. It arrives in three ways:
- Handoff drift. A design file cannot hold everything the build needs, so the build fills the gaps and small differences ship. The post on why UX breaks after the design handoff covers those gaps.
- Copying. A new screen starts as a copy of an existing one, because that is faster than reading the design system, and the hardcoded values come along.
- Design system changes. A token or a component is updated, and the copies made outside the system do not follow.
The design lead at a Series A startup with five designers and sixteen engineers told us in September that the team had shipped without a design system at first. Speed came first. Drift built up in the core components, and they ended up redoing the navigation, both the UI and the patterns.

AI coding tools add design debt faster
AI coding tools speed up the copying step. Figma's post introducing its MCP server says that when the agent finds no matching component, "it will likely create a new component based on the screenshot." If the codebase already has one the agent missed, that is a near-duplicate on day one.
GitClear's research on AI-assisted code quality found "a spike in the prevalence of duplicate code blocks." Our founder's June sales-call note records the same pattern in AI prototyping tools: "not following existing design system, recreating components that are not 1:1 with the real DS in place". And: "design tokens are not being used, values are hardcoded".
UX debt vs design debt
UX debt and design debt overlap, and the difference is mostly who notices first. Anna Kaley at Nielsen Norman Group defines UX debt this way: "UX debt includes any ongoing problems in the experience due to launching a fast, easy, or careless solution". UX debt is measured by what users run into. Design debt is measured by distance from the design system.
| Design debt | UX debt | |
|---|---|---|
| Who notices first | Designers and design system owners | Users, then support and product teams |
| Measured against | The design system and design intent | What users run into |
| Example | A hex value that matches the color token today | An error state that does not say what to do next |
| Typical fix | A token swap or component fix in one pull request | A design change, often a project |
How do you find and measure design debt?
If you are the designer, or one of two or three, next to a much larger engineering team, you have probably already tried the obvious route. You filed the ticket about the five button styles and watched it age behind feature work. You may have audited the Figma file and found it cleaner than the product. The debt is not in the file. Start with the running product.
Take an interface inventory of the build, which Brad Frost describes as "a comprehensive collection of the bits and pieces that make up your interface". Screenshot every button, input, card and modal in the app, and group them by kind. Five button styles where the system has two are hard to argue with once they sit side by side.
Then check the code. Raw hex values and arbitrary Tailwind values in square brackets are the clearest signs of a value that went around the theme. GitHub's code search finds both on the repository's default branch, without a terminal. Paste /#[0-9a-fA-F]{6}/ for hex values and /-\[[^\]]+\]/ for arbitrary values into the search box, and add NOT path: with your theme file so the token definitions drop out.
Tailwind's docs on custom styles say arbitrary values exist to "break out of those constraints to get things pixel-perfect." A handful are decisions. Hundreds are debt. Run the same two searches once a month. The number of matching files is your measure, and it should fall.
Log each item on its own line, the way you would log a design QA finding: location, expected token, found value. For example, /dashboard ActivityRow: expected gap-4, found gap-[14px]. With the expected value written down, the fix needs no meeting.
How to pay down design debt without a redesign
Design debt is paid down in small fixes on a schedule, made at the source, with review rules that keep new debt out. Austin Knight is clear about the default: paying it down "shouldn't be viewed as a ground-up creation of a new design". The exception is structure that is wrong, navigation that no longer fits the product or flows users cannot finish, which no token swap fixes. When the structure works and the values have drifted, fix the values.
Fix it on a rhythm
Teams that keep up with polish give it a fixed slot. Linear runs Quality Wednesdays, a weekly slot for small fixes tracked with a "quality" label. Tuomas Artman writes, "Many of these quality fixes take 30 minutes or less." And: "Most of these fixes are small on their own, but together they completely change how the product feels." Which rhythm you pick matters less than keeping it.
Point every copy at the source
When the same value is hardcoded on twelve screens, patching it twelve times only resets the problem. Replace each copy with the token once, so the next token change reaches all of them. Fixes like this work when teams store each decision once as a token and use it everywhere.
Stop new debt in review
Fixes hold only when new debt stops merging. In a Tailwind codebase the theme is the first gate. The Tailwind docs on theme variables say "These low-level design decisions are often called design tokens, and in Tailwind projects you store those values in theme variables." A theme that holds only your own values leaves no default palette to reach for.
The theme does not stop an arbitrary value such as gap-[14px], so lint rules catch the rest. The no-arbitrary-value rule in eslint-plugin-tailwindcss "will shout at you if you use any arbitrary value in your classnames." It is off by default, so someone has to turn it on. An engineer sets these checks up once, and from then on a one-off value fails before anyone has to spot it. The design engineer guide covers these guardrails in protecting the design system before the first designer pull request.
UI polish without engineers: small UI changes a designer can make
The common fix is a ticket to engineering. Most of a design debt log does not need one. In Designers' workflow for shipping code, Atlassian's Eduardo Sonnino calls the work "Bump Craftsmanship: turn an 80% implementation into 100% by tuning motion, styles and layouts, directly in code." His advice is "Keep diffs small" and "prefer variable-level changes over rewrites."
Intercom drew the same line years earlier. In Shipping code for designers, not just engineers, Lorcan Coyle wrote: "Changing the value of a CSS block is probably OK, introducing new classes might not." In a Tailwind codebase, swapping one utility class for another is the value change. New components and new CSS are the structure, where an engineer should be involved.
What a designer fixes and what an engineer owns
A designer can fix:
- Token swaps, replacing a hex or arbitrary value with the theme's token
- Spacing, padding and gaps
- Type size, weight and line height
- Color and copy
- A missing state, built with an existing component
An engineer should own:
- Logic, data and new flows
- Shared platform components that other teams depend on
- Performance, security and compliance code
"Without engineers" means without engineering time spent on implementation, not without engineering review. The designer's change goes up as a pull request, and an engineer reviews and merges it like any other. The design engineer guide covers fixing design QA findings on an engineer's pull request and opening your first pull request as a designer.
Take the logged ActivityRow item. In Modeinspect, on a Next.js React codebase that uses Tailwind, the designer selects that row in the running app and picks gap-4 from the team's Tailwind theme. One click on Apply and the coding agent writes the code. One more opens the pull request for an engineer to review. The panel offers the theme's tokens but does not enforce them, so review still catches one-off values.
Larger changes, such as new layouts or new flows, involve design and engineering together. When they go through a handoff from Figma to developers, writing down states and breakpoints keeps new debt out from the start.
Start this week. Run the two searches and put the file count in the ticket, next to a slide with every button style on it. Ask for a weekly slot, not a project. Then take the first token swap on the list and open it as a pull request yourself.
Frequently asked questions
Is design debt the same as technical debt?
No. Austin Knight wrote that technical debt "affects the integrity of the codebase" while design debt "affects the integrity of the user experience". The two often share lines of code, such as a hardcoded hex value that skips the color token.
What are examples of design debt?
Common examples are several button styles where the design system defines two, hex values where color tokens belong, and arbitrary Tailwind values such as top-[117px]. Others are near-duplicate components, states that look different on every screen, and spacing set by eye.
Who is responsible for design debt?
The designer who owns an area is best placed to find and log its design debt, because they hold the design intent. Designers can fix token, spacing, type and color issues as pull requests, while engineers own logic, data and shared components, and review every fix before it merges.