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.
| Meaning | Allowed action | Exit evidence | |
|---|---|---|---|
| Active | Supported for new and existing use | Consumers may adopt it | A reason and owner exist before deprecation begins |
| Deprecated | Existing use may remain temporarily | Warn and inventory dependencies | Replacement topology or explicit no-replacement decision is recorded |
| Blocked for new use | No new references should be introduced | Enforce through the project's available checks and review process | New-use observations remain clear for the agreed window |
| Migration in progress | Named consumers are moving | Keep the old token while work and verification continue | Every consumer is migrated or recorded as an owned exception |
| Removed | The old source identifier and governed outputs are gone | Reject reintroduction | Removal gate is complete and the decision record is retained |
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
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
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
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
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
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
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 record | Observation that closes it | |
|---|---|---|
| Authoritative source | Path, version, owner, old token, proposed replacement | Approved source change is present in the expected version |
| References | Direct references, chained references, resolved values | No unresolved path requires the old token |
| Modes | Light, dark, themes, brands, or platform variants in scope | Expected values resolve in every supported mode |
| Generated outputs | Artifact name, generator version, expected identifiers | Fresh artifact contains the new identifiers and handles the old ones as planned |
| Components | Named primitives, variants, and interaction states | Reviewed components consume the intended replacement |
| Applications | Named routes, screens, products, and release versions | Representative consumers load the migrated artifact and render as expected |
| Overrides | Local variables, copied values, detached styles, exceptions | Each override is removed, accepted, or assigned to an owner |
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-one | One-to-many | Many-to-one | Contextual | |
|---|---|---|---|---|
| Use when | The meaning stays the same and only the public name changes | One old token served several meanings that now need distinct roles | Several old names represent one stable semantic role | The right replacement depends on component, state, mode, or product context |
| Migration record | One old path and one new path | One old path plus a mapping for every consumer class | Every old path mapped to the shared new path | A named rule for each consumer or context |
| Main risk | Stale generated identifiers survive | A catch-all replacement recreates the original problem | Distinct meanings are erased during consolidation | An unrecorded branch becomes a local override |
| Removal condition | All consumers use the new identifier | Every old use has been classified and migrated | No consumer relies on an old distinction | Every supported context has an owned mapping |
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: []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}"
}
}
}
}After the source decision
{
"color": {
"action": {
"primary": {
"$type": "color",
"$value": "#5B5CE2"
}
},
"button": {
"primary": {
"$type": "color",
"$value": "{color.action.primary}"
}
}
}
}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
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
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
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
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
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
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
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
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 layer | Next check | |
|---|---|---|
| Replacement feels wrong in one component | Source decision or replacement map | Confirm whether the old token carried more than one meaning |
| Source is correct but output has the old name | Generator or stale artifact | Confirm source version, generator input, output location, and regeneration result |
| Generated output is correct but the app is not | Consumer version or local override | Confirm the loaded artifact and inspect component or application overrides |
| Light mode passes and dark mode fails | Mode mapping or mode-specific override | Trace the dark value and its complete reference chain |
| Changed surfaces pass but unrelated surfaces drift | Replacement scope or generator reach | Inspect the unchanged-surface list and generated diff |
| A temporary alias works in one tool only | Tool-specific compatibility behavior | Verify support independently in every governed output and consumer |
| No one can approve an unresolved consumer | Ownership | Assign an accountable owner or block removal |
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 evidence | Blocking evidence | |
|---|---|---|
| Replacement decision | Every old use has a defined mapping or approved no-replacement outcome | Any consumer still has an unresolved semantic destination |
| References | Direct and transitive references no longer require the old path | An unresolved or unclassified reference remains |
| Generated artifacts | Fresh governed outputs contain the expected identifiers and treatment of the old identifier | An output is stale, missing, or differs from the recorded expectation |
| Consumers | Named components and applications use the intended artifact and replacement | A supported consumer still loads or references the old token |
| Modes | Representative consumers pass in every supported mode | Any supported mode is unchecked or produces the wrong semantic result |
| Unchanged surfaces | Named control surfaces remain unchanged as expected | Unrelated drift appears without an explained and approved cause |
| Exceptions | Every exception is closed or explicitly owned under an approved keep decision | An exception is unowned, expired, or lacks a next decision |
| Authorization | An accountable approver records the final disposition and evidence | Deletion is proposed without an identified decision owner |
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
- Deprecating in design systems: When it's time to say goodbye: The guide treats deprecation as a sequenced dependency, replacement, communication, risk, migration, and deletion problem, including references from tokens, templates, and complex components.
- Design Tokens: The Foundation of Your UI Arch: The article describes token references as a dependency graph and treats tokens as governed interfaces delivered to downstream consumers.
- Design Tokens in Webstudio: A Practical Implementation Guide: The guide covers layered token architecture, maintenance, exports, custom code, and integrations, showing why a source change can affect several downstream layers.
- Design Tokens Format Module 2025.10: The captured document identifies itself as a preview draft and explicitly says not to implement it or cite it as authoritative.
- Token Values with References - Tokens Studio for Figma: The documentation explains reference behavior inside Tokens Studio and provides an example of product-specific deprecation behavior that should not be generalized to every token tool.