In a design system, how do design files and shipped code drift apart over time, and why does nobody notice until they are compared?
answer
- each side changes alone
- the fix that lands once
- old library versions on each side
- internally consistent, mutually wrong
- nobody owns the pair
basics
~20 sEach side changes alone: designers override, detach or stay on an old library version; engineers hotfix, hardcode or fork components; fixes land on one side only. Each side stays internally consistent, so drift appears only when someone compares them.
solid answer
~40 sDrift is the gap between what the design files say the product looks like and what actually ships. It grows from **one-sided changes**: on the design side, style overrides, detached instances, files left on an old library version and explorations never reconciled after build; on the code side, field hotfixes, hardcoded values, forked lookalike components and undocumented platform adaptations. The commonest source is the **one-sided fix** — a scan button enlarged in the app after gloved users missed it, with the design never updated. Nobody notices because each side is reviewed **against itself**: code review checks the change, design review checks the new design, and old screens are rarely revisited. The cost arrives later, when a designer designs a feature against screens that no longer exist.
go deeper
Recall the common sources of drift on each side — overrides and detachments in design, hotfixes, hardcoded values and forks in code — and that fixes landing on one side are the most common cause.
Explain why each side stays internally consistent and why ordinary code and design reviews never compare across the boundary, so drift accumulates unseen.
Show how you would keep drift small in practice: one-sided fixes opening follow-up tasks, documented deviations, a comparison cadence and leading signals between audits.
Weigh the cost of continuous reconciliation against periodic audits, and who should own the correspondence between design and code when neither discipline naturally does.
## What drift is **Design-to-code drift** is the growing gap between what a product's design files say it looks like and what users actually get. Design and code start in agreement at handoff; drift is everything that happens afterwards on one side and not the other. It is rarely one big decision. It is dozens of small, individually reasonable changes that nobody reconciles. ## Where drift comes from | Side | Source | Example in a warehouse scanner app | |---|---|---| | Design | Style override on an instance | The scan-error color made darker on one screen only | | Design | Detached instance | The pick-list row detached to add a bin-location line | | Design | Stale library version | A file never accepted the library update that enlarged stepper buttons | | Design | Unreconciled exploration | The shipped build simplified a screen; the file still shows the richer version | | Code | One-sided fix | The scan button enlarged on device after gloved users missed it | | Code | Hardcoded value | A color copied from an old screenshot instead of a token | | Code | Forked component | A local copy of the row built because the design showed a lookalike | | Code | Platform adaptation | The native picker used instead of the library's on one platform, undocumented | Two patterns deserve special attention: - **The one-sided fix.** Production pressure means real problems are often fixed where they are found. A field complaint gets fixed in code in a day; the design file is nobody's task. The fix is correct, and the drift it creates is invisible. - **Version skew.** The design file and the app can each be pinned to a different release of the system. Both are faithful to *a* version of the library, just not the same one. ## Why nobody notices Drift survives because every review looks at one side at a time: 1. **Code review** checks that the change works and follows code conventions; it rarely opens the design file for an unrelated screen. 2. **Design review** checks new designs against the library, not against the shipped app. 3. **Old screens are rarely revisited.** Once a flow ships, neither side looks at it again until a feature touches it. 4. **Each side is internally consistent.** The design files agree with each other and the app agrees with itself; only a comparison across the boundary reveals a gap. 5. **Nobody owns the pair.** Designers own files, engineers own code; the correspondence between them is often owned by no one. Small deltas also hide in plain sight: a few units of padding here, one shade of red there, each below the threshold of anyone's attention until a side-by-side comparison lines them up. ## A drift timeline How the scanner app's scan screen drifted over four releases, with every step reasonable on its own: 1. Release one ships matching its design exactly. 2. A hotfix enlarges the scan button in code after gloved workers miss it; the design file is not touched. 3. A designer detaches the result card to add a lot number; an engineer builds that card as a local component. 4. The library darkens its error color to improve contrast. Linked designs and library-based code follow; the local card in code and the detached card in design keep the old color. No single step was a mistake anyone would reject in review, yet after four releases the screen matches neither its design nor the system. ## What drift costs - **Designers design against a product that no longer exists**, so new features collide with the real screens they sit beside. - **Engineers stop trusting design files** and start treating them as suggestions — which creates more drift. - **Library fixes stop landing.** An accessibility or contrast fix to a component reaches linked designs and library-based code, but not forks and detached copies. - **Audits get more expensive**, because every mismatch must be investigated before anyone knows which side is right. ## Keeping drift small - Treat a fix on one side as **opening a task on the other**, so a hotfix is followed by a design update or a library change. - Record **intentional deviations**, such as a platform adaptation, where both designers and engineers will find them. - Compare shipped screens with their designs on a **cadence**, not only when something looks wrong — the purpose of a parity audit. - Watch the leading signals between audits: detachments in design files, raw values and forked components in code.
- Is every difference between design and code drift?No. A documented platform adaptation — using a platform's native picker, for instance — is an intentional difference, and so is a design exploration clearly marked as not yet built. It becomes drift when the difference is undocumented, so nobody can tell whether it is deliberate or a mistake.
- Why are one-sided fixes the hardest drift source to prevent?Because the fix itself is right and urgent. A field problem is fixed where it is found, usually in code, and the team moves on; updating the design file has no deadline and no owner. Preventing the drift means making the second half of the fix a routine task — a follow-up ticket or a checklist item — rather than relying on memory.
Drift is like a building and its floor plans: each renovation done without updating the plans is harmless alone, but after a few years the plans describe a building that no longer exists — and the next architect designs an extension against them.
saying these in an interview costs you the question
- Drift only happens when engineers ignore the design.
- If code review passes, the screen still matches its design.
- Fixing a field problem in code alone is fine; design files will catch up.
- Drift is purely cosmetic and never affects accessibility.
- The design file is automatically the source of truth for the shipped app.