Get started

Design token deprecation strategy: replace, migrate, and remove without breaking consumers

Don't remove or rename a design token just because its replacement exists. Remove it only after you've mapped its dependencies, regenerated every governed output, migrated named consumers, checked every supported mode, assigned any exceptions, and recorded evidence that the old identifier is no longer required.

Updated July 31, 2026

Deprecation is a state, not proof of removal readiness

Deprecation means a token should move toward retirement. It doesn't mean the token is unused, every consumer has a replacement, or deletion is safe. A token can remain deprecated for several releases while its references, exports, components, and applications move away from it.

Treat lifecycle states as project policy. Don't assume that a metadata field, naming convention, or design-token format enforces the same behavior. The frozen DTCG document in the evidence set is a preview that explicitly says not to implement or cite it as authoritative. This guide therefore doesn't depend on a proposed $deprecated property.

MeaningAllowed actionExit evidence
ActiveSupported for new and existing useConsumers may adopt itA reason and owner exist before deprecation begins
DeprecatedExisting use may remain temporarilyWarn and inventory dependenciesReplacement topology or explicit no-replacement decision is recorded
Blocked for new useNo new references should be introducedEnforce through the project's available checks and review processNew-use observations remain clear for the agreed window
Migration in progressNamed consumers are movingKeep the old token while work and verification continueEvery consumer is migrated or recorded as an owned exception
RemovedThe old source identifier and governed outputs are goneReject reintroductionRemoval gate is complete and the decision record is retained
Project lifecycle states and the evidence each one carries

Do not confuse policy with tool behavior

A documentation badge, temporary alias, lint rule, plugin warning, or format property may help with one part of a migration. None proves that the other layers are complete. Verify each mechanism in the tool and version your project actually uses.

Map the dependency graph from source to surface

Start at the authoritative token definition, then follow every place its name or resolved value can travel. Token references form a graph, so searching for the old identifier is necessary but insufficient. A direct reference may feed another semantic token, which may become a CSS custom property, a Tailwind theme value, a registry payload, and finally a component style.

  1. 1

    Locate the authoritative definition

    Record the exact source file or system, token path, type, mode values, version, and owner. If two artifacts both appear authoritative, resolve that ownership conflict before migration.

  2. 2

    Trace direct and transitive references

    Find tokens that reference the old token directly, then follow their dependants. Record resolved references separately from textual matches so a renamed intermediate token doesn't hide the chain.

  3. 3

    List supported modes and themes

    Record every mode in which the token resolves, such as light and dark. The replacement may be equivalent in one mode and wrong in another.

  4. 4

    Enumerate governed outputs

    List the CSS, Tailwind, DTCG, shadcn registry, platform, or other generated artifacts your project actually produces. For each output, record the expected old and new identifiers.

  5. 5

    Name component and application consumers

    Choose concrete components, templates, routes, and applications. Include representative states such as hover, focus, disabled, error, and data-heavy variants when they consume the token differently.

  6. 6

    Find local overrides and copied values

    Search for local variables, hardcoded resolved values, detached component styles, theme overrides, and stale generated files. A copied value won't appear in an identifier search, so inspect high-risk surfaces as well.

The result should read as a chain: source token, referenced tokens, mode resolutions, generated identifiers, shared components, application consumers, and exceptions. Record any gap between layers. Don't fill it with an assumption.

A compact dependency-map worksheet

What to recordObservation that closes it
Authoritative sourcePath, version, owner, old token, proposed replacementApproved source change is present in the expected version
ReferencesDirect references, chained references, resolved valuesNo unresolved path requires the old token
ModesLight, dark, themes, brands, or platform variants in scopeExpected values resolve in every supported mode
Generated outputsArtifact name, generator version, expected identifiersFresh artifact contains the new identifiers and handles the old ones as planned
ComponentsNamed primitives, variants, and interaction statesReviewed components consume the intended replacement
ApplicationsNamed routes, screens, products, and release versionsRepresentative consumers load the migrated artifact and render as expected
OverridesLocal variables, copied values, detached styles, exceptionsEach override is removed, accepted, or assigned to an owner
Record one row for every governed layer and named consumer

Choose the replacement relationship before changing names

A rename sounds like a one-to-one operation, but the old token may have accumulated several meanings. For example, a broadly named color.action token might control button fills, links, focus rings, and selected navigation. Replacing every use with color.action.primary would preserve the old coupling under a cleaner name.

One-to-oneOne-to-manyMany-to-oneContextual
Use whenThe meaning stays the same and only the public name changesOne old token served several meanings that now need distinct rolesSeveral old names represent one stable semantic roleThe right replacement depends on component, state, mode, or product context
Migration recordOne old path and one new pathOne old path plus a mapping for every consumer classEvery old path mapped to the shared new pathA named rule for each consumer or context
Main riskStale generated identifiers surviveA catch-all replacement recreates the original problemDistinct meanings are erased during consolidationAn unrecorded branch becomes a local override
Removal conditionAll consumers use the new identifierEvery old use has been classified and migratedNo consumer relies on an old distinctionEvery supported context has an owned mapping
Replacement topologies

A fifth option is no replacement. Use it when the capability or visual decision is being removed instead of renamed. The migration then removes the consuming behavior or moves it to a non-token mechanism that has been explicitly approved. Don't invent a replacement merely to make the record look complete.

Keep unresolved mappings visible

If three consumers have clear replacements and a fourth does not, record three mappings and one unresolved case. A visible block is safer than a universal mapping nobody has verified.

Check whether the token name still describes a role

Before you preserve an old coupling under a new identifier, compare the proposed name with the semantic naming test and inspect complete public token systems.

Use one deprecation record for the whole migration

Keep the decision and its evidence together. Splitting the source change, consumer list, exception log, and approval across separate tickets makes it hard to tell whether the migration is complete. The following record is tool-neutral. Add project-specific fields only when they have a named consumer.

deprecationId: token-color-action-to-primary
status: deprecated
source:
  owner: design-systems
  artifact: tokens/source.json
  version: "illustrative-version"
deprecatedToken:
  path: color.action
  type: color
  reason: "Illustrative rename to clarify semantic role"
replacement:
  topology: one-to-one
  mappings:
    - from: color.action
      to: color.action.primary
  unresolved: []
affectedModes:
  - light
  - dark
references:
  direct: []
  transitive: []
generatedOutputs:
  - artifact: tokens.css
    oldIdentifier: --color-action
    expectedNewIdentifier: --color-action-primary
  - artifact: tailwind-theme.json
    oldIdentifier: color-action
    expectedNewIdentifier: color-action-primary
consumers:
  components:
    - name: PrimaryButton
      owner: ui-platform
      states: [default, hover, focus, disabled]
  applications:
    - name: account-settings
      owner: product-team
      surfaces: [profile-save]
localOverrides: []
compatibilityMechanism:
  kind: none-verified
  note: "Do not assume alias support"
observations: []
unchangedSurfaces:
  - secondary-actions
exceptions: []
deadline: "project-owned date"
disposition: migrate
approver: null
decisionEvidence: []
Copyable migration record. All names, values, consumers, versions, and observations shown here are illustrative.

The record separates facts from intentions. expectedNewIdentifier states what regeneration should produce, but it isn't evidence that the artifact was regenerated. consumers names what must move, but it doesn't show that the application loaded the new version. Put observed results in observations. Attach the relevant build, diff, test, screenshot, or release reference under decisionEvidence, following your project's evidence system.

Illustrative fixture: rename one semantic color token

The following fixture demonstrates the sequence without claiming that Identity Forge or any delivery tool manages deprecation, discovers consumers, provides aliases, or performs migration. The token names, values, files, and results are illustrative.

Before the proposed rename

{
  "color": {
    "action": {
      "$type": "color",
      "$value": "#5B5CE2"
    },
    "button": {
      "primary": {
        "$type": "color",
        "$value": "{color.action}"
      }
    }
  }
}
Illustrative source token and direct reference before migration.

After the source decision

{
  "color": {
    "action": {
      "primary": {
        "$type": "color",
        "$value": "#5B5CE2"
      }
    },
    "button": {
      "primary": {
        "$type": "color",
        "$value": "{color.action.primary}"
      }
    }
  }
}
Illustrative replacement after the reference has been updated. This is not a compatibility-alias example.

Equal color values can reduce immediate visual change, but they don't close the migration. The old identifier may remain in generated CSS, a cached registry item, an application theme, or a local override. A text search may find no old identifier even though a copied #5B5CE2 remains in a component. The record must cover both identifier flow and representative rendered behavior.

Why no compatibility alias appears here

Alias and reference behavior varies by tool and delivery path. Use a temporary compatibility mechanism only after verifying that the specific source format, transformer, output, and consumer preserve it as intended. Record its owner and removal condition. Otherwise, leave it out.

Run the migration one layer at a time

  1. 1

    Approve the semantic decision

    Confirm why the old token is changing, who owns the decision, and whether the mapping is one-to-one, split, consolidation, contextual, or no replacement. Block new adoption using only controls your project has verified.

  2. 2

    Update the authoritative source and references

    Add or change the replacement in the source of truth. Resolve direct and chained references there before treating generated files as current.

  3. 3

    Regenerate every governed output

    Run the normal generators for each output in scope. Compare the result with the record: expected new identifiers must appear, and old identifiers must remain or disappear exactly as the migration stage requires.

  4. 4

    Migrate named component consumers

    Update shared components before broad application surfaces where possible. Check the recorded variants and interaction states for each component instead of approving only its default state.

  5. 5

    Migrate named application consumers

    Confirm that each application uses the intended artifact version. Inspect representative routes and realistic content instead of relying solely on a source-code match.

  6. 6

    Check every supported mode

    Exercise light, dark, and any other supported mode listed in the record. Compare semantic behavior, not only whether both modes render without an error.

  7. 7

    Inspect unchanged surfaces

    Choose surfaces that shouldn't change and verify that they didn't drift. This catches replacement maps or generators whose reach is broader than expected.

  8. 8

    Close or assign exceptions

    Every unresolved consumer, override, stale artifact, or unavailable observation needs an owner and a next decision. An exception without an owner blocks removal.

Keep the old token during this sequence unless your project's verified compatibility mechanism makes a different order safe. Removing it early turns missing inventory into breakage. Keeping it forever leaves two apparent choices and invites new use. The lifecycle therefore needs both a new-use block and a removal gate.

Diagnose failures by the layer that owns them

Likely layerNext check
Replacement feels wrong in one componentSource decision or replacement mapConfirm whether the old token carried more than one meaning
Source is correct but output has the old nameGenerator or stale artifactConfirm source version, generator input, output location, and regeneration result
Generated output is correct but the app is notConsumer version or local overrideConfirm the loaded artifact and inspect component or application overrides
Light mode passes and dark mode failsMode mapping or mode-specific overrideTrace the dark value and its complete reference chain
Changed surfaces pass but unrelated surfaces driftReplacement scope or generator reachInspect the unchanged-surface list and generated diff
A temporary alias works in one tool onlyTool-specific compatibility behaviorVerify support independently in every governed output and consumer
No one can approve an unresolved consumerOwnershipAssign an accountable owner or block removal
Common failure signatures and the first owner to consult

This order prevents wasted work: patching an application when the source mapping is wrong, or changing the source repeatedly when one application is loading a stale artifact. Route the failure to the earliest layer whose observation differs from the record.

Apply a falsifiable removal gate

Removal should be a recorded decision, not the absence of objections. Complete the evidence matrix immediately before deleting the old token. Migration evidence can go stale when consumers or generated artifacts change.

Pass evidenceBlocking evidence
Replacement decisionEvery old use has a defined mapping or approved no-replacement outcomeAny consumer still has an unresolved semantic destination
ReferencesDirect and transitive references no longer require the old pathAn unresolved or unclassified reference remains
Generated artifactsFresh governed outputs contain the expected identifiers and treatment of the old identifierAn output is stale, missing, or differs from the recorded expectation
ConsumersNamed components and applications use the intended artifact and replacementA supported consumer still loads or references the old token
ModesRepresentative consumers pass in every supported modeAny supported mode is unchecked or produces the wrong semantic result
Unchanged surfacesNamed control surfaces remain unchanged as expectedUnrelated drift appears without an explained and approved cause
ExceptionsEvery exception is closed or explicitly owned under an approved keep decisionAn exception is unowned, expired, or lacks a next decision
AuthorizationAn accountable approver records the final disposition and evidenceDeletion is proposed without an identified decision owner
Minimum evidence for final removal

Record one of four dispositions

  • Keep: the old token still has a valid, supported meaning. Remove the deprecation state or narrow the proposal.
  • Migrate: the replacement is valid, but named work or observations remain. Keep the old token and continue the recorded migration.
  • Remove: every gate passes, governed outputs and consumers no longer require the old token, and an accountable owner authorizes deletion.
  • Block: a dependency, mapping, mode, artifact, consumer, owner, exception, or evidence field is unresolved. Don't delete the token.

A clean search is not a removal gate

Searching for the old identifier can miss copied values, transformed names, cached outputs, runtime theme mappings, and consumers outside the searched repository. Treat search results as one observation inside the dependency record.

Design token deprecation questions

Should a deprecated token keep resolving?

It often must keep resolving while existing consumers migrate, but that's a project decision rather than a universal rule. Record whether the old token remains available, how new adoption is blocked, and what evidence will permit removal.

Can I use an alias from the old token to the new token?

Only if the exact source format, transformer, generated outputs, and consumers have verified support for that behavior. Treat the alias as a temporary compatibility mechanism with an owner and removal condition, not as proof that migration is complete.

Is a token rename a breaking change?

It can be. Consumers may depend on the source path, a transformed CSS variable, a Tailwind name, a registry payload, or another generated identifier. Classify the change from the consumer boundary, not from whether the resolved value stayed the same.

How long should a token remain deprecated?

Use evidence rather than a generic duration. Keep it while supported consumers or owned exceptions still require it. Remove it when the full gate passes and the accountable owner records that decision.

What if one old token needs several replacements?

Use a one-to-many or contextual mapping. List each consumer class and its destination. Don't choose one catch-all token merely to make automated replacement easier.

Does removing the token prove the interface is accessible?

No. This workflow checks migration integrity across token layers and representative consumers. Accessibility requirements need their own applicable criteria and evidence.

Choose one token currently proposed for retirement and complete the migration record before editing it. If any dependency, replacement, consumer, owner, mode, artifact, exception, or evidence field remains unresolved, set the disposition to block and keep the old token in place.

Sources