What is a design token, and what breaks when you change one?
A design token is a named design decision - color, spacing, radius or motion - that products reference by name instead of raw value. Changing one token can silently alter contrast, layout and brand consistency across every pinned consumer.
What the interviewer is scoring
- Whether you describe tokens as an indirection layer rather than as a variables file
- Does the candidate separate primitive values from semantic roles, and justify the middle layer
- That they recognise a value change is a breaking change for consumers even though nothing fails to compile
- Whether version pinning and lagging consumers come up without prompting
- Can they name a concrete case where a single token change violates a contrast requirement
Answer
Short answer
A design token is a named design decision, such as a color role, spacing step, radius or animation duration, that products consume by name instead of by hard-coded value. Changing a token is risky because it can silently change contrast, layout and brand behavior across every product version that depends on it.
The indirection is the whole point
A token is a name bound to a design decision. color.background.danger rather than #B3261E, space.4 rather than 16px, duration.short rather than 150ms. The value matters less than the fact that nothing downstream refers to the value directly. Every button, banner and form field in every product reaches for the name, so the value has exactly one definition and one place it can be edited.
That indirection buys you three things that are hard to get any other way. A retheme becomes a data change rather than a code change, because dark mode and a white-label brand are both just a different binding of the same names. A design decision becomes reviewable, because a pull request that changes one line of JSON is legible in a way that a hundred CSS diffs are not. And a token file can be compiled into whatever each platform wants — CSS custom properties, a Swift enum, an Android resource file, a Figma variable collection — so the same decision reaches the web and native codebases without anyone retyping it.
Primitive, semantic, component
The layer that candidates skip is the middle one, and it is the one that makes the system survive contact with a redesign.
{
"color": {
"red": { "60": { "$value": "#b3261e", "$type": "color" } },
"background": {
"danger": { "$value": "{color.red.60}", "$type": "color" }
}
},
"button": {
"destructive": {
"bg": { "$value": "{color.background.danger}", "$type": "color" }
}
}
}
The primitive tier is a palette: raw values, named after what they are. The semantic tier names what a value is for — danger, surface, muted text — and is the only tier a product engineer should ever reference. The component tier exists so a single component can be retargeted without touching the semantic names shared with everything else. The $value and $type keys and the {curly.reference} syntax come from the Design Tokens Community Group format, which most token pipelines now read or emit.
Skip the semantic tier and you get an application full of color.red.60, which reads fine until the brand decides danger is now orange. Then you cannot tell which of four hundred usages meant "danger" and which meant "our red". You are back to grepping hex codes, which is the problem tokens existed to solve.
A value change is a breaking change with no compiler to tell you
Nothing throws when you darken color.background.danger by two steps. Every consumer keeps building. What actually changes is pixels in products you do not own, and the failure modes are specific.
Contrast is the sharpest one. A background token and a foreground token together determine a ratio, and AA wants 4.5:1 for normal text and 3:1 for large text. Those two tokens are usually owned by different concerns and changed at different times, so a purely cosmetic tweak to one can drop a pairing below the line in a component you never looked at. The pairings, not the individual values, are what you have to test.
The rest follow the same shape. A spacing token that grows by 4px reflows a layout that was fitting exactly, and someone's table now scrolls. A radius token that a product had been relying on to look like a pill becomes a rounded rectangle. A duration token that lengthens breaks a visual regression suite in a different repository, at 3am, in someone else's CI.
Drift, pinning and the reskin that cannot land
Because tokens ship as a package, consumers pin them, and pinning is how the indirection quietly stops working.
flowchart TD
A["Token source of truth"] --> B["Build pipeline"]
B --> C["CSS variables package"]
B --> D["iOS + Android resources"]
C --> E["Product A on v4"]
C --> F["Product B on v2"]
D --> G["Mobile app on v3"]
E --> H["Same brand, three appearances"]
F --> H
G --> HLook at where the arrows converge: three consumers on three versions produce one visible brand, and nobody looking at a single repository can see the divergence. The reskin you promised marketing lands in the design system on day one and reaches the products over the following two quarters, one dependency bump at a time.
The mitigations are unglamorous and they work. Version the token package semantically and treat a changed value as a minor-or-worse release with the visual delta in the changelog, screenshots included. Publish contrast-pair assertions as tests inside the token repository so a bad pairing fails there rather than in a product. Keep an inventory of which consumer is on which version, because a reskin you cannot forecast is a reskin you cannot commit to. And for renames, ship the old name as an alias pointing at the new one for a release or two rather than deleting it, since a rename is the one breaking change a build can catch, and that makes it far safer than a silent value edit.
The dangerous token change is not the one that breaks the build. It is the one that compiles everywhere and looks slightly wrong in six products on four different versions.
© 2026 Preptima. Originally published at preptima.com.
Likely follow-ups
- When would you deliberately hard-code a hex value instead of adding a token for it?
- How would you detect that a token has been changed in a way that breaks contrast, before release?
- What do you do about a product still on a two-year-old token package that you need to reskin?
- How would you model a token whose value differs between web and native platforms?
Related questions
- The business wants to change a rating factor next Monday. Walk me through what actually has to happen.hardAlso on versioning5 min
- How would you build a rating engine, and how do you reproduce a quote you gave someone eighteen months ago?hardAlso on versioning5 min
- Design the contract for a public API. How do you handle pagination, idempotency and versioning?hardAlso on versioning7 min
- How do you write prompts that survive a model upgrade?mediumAlso on versioning4 min