skip to content

In a design system, how do you rename a widely used design token without breaking consumers, and when can the old name be removed?

level: middleimportance: must knowfreq 50%

answer

  1. both names must work for a while
  2. old name points at new name
  3. reference, not a copy
  4. flag it, ship it as minor
  5. remove only in a major

basics

~20 s

Add the new token, turn the old name into a deprecated alias that references it, and ship that as a minor release. Remove the old name only in a later major release, once consumers have had at least one release to migrate.

solid answer

~40 s

A rename becomes safe when both names work for a while. First **add the new token** with the real value. Then turn the old token into an **alias** — its value becomes a reference to the new token, such as `{availability.open}` — rather than a copy, so the two names can never drift apart. Mark the old one with `$deprecated`, ideally as a string naming the replacement, so generated code and docs can warn consumers. Ship that as a **minor** release: under semantic versioning, marking public API as deprecated requires a minor bump, and the old name still resolves. Track how many consumers still use the old name, then **remove the alias in a major release** with a migration note mapping old to new — after at least one minor release carrying the deprecation.

code

json · 16 lines
json
{
  "availability": {
    "open": {
      "$type": "color",
      "$value": { "colorSpace": "srgb", "components": [0.859, 0.949, 0.89], "hex": "#dbf2e3" },
      "$description": "Background for anything a pet owner can book right now"
    }
  },
  "booking": {
    "slot-free": {
      "$type": "color",
      "$value": "{availability.open}",
      "$deprecated": "Renamed. Use {availability.open}; removed in the next major release."
    }
  }
}

go deeper

for a junior

Recall the order: add the new name, keep the old name working as a deprecated alias, and remove the old name only later in a breaking release.

for a middle

Explain why the old name must reference the new token instead of copying its value, what the $deprecated property carries, and why the alias release is minor while the removal is major.

for a senior

Describe running the migration across many consuming teams: surfacing warnings in code, docs and design files, measuring remaining usage, and choosing the exit condition for the alias.

for a principal

Weigh how long aliases should live against the cost of a growing deprecated set, and how often the system can afford majors that remove names.

## Why a rename needs a migration Consuming apps reference a design token by its **name**, so a rename is really a **removal plus an addition**: every reference to the old name dangles the moment it disappears. In a veterinary clinic booking system, the old name might live in the pet owners' web booking site, the native mobile app, the reception kiosk, the clinic staff dashboard and the design library — each owned by a different team with its own schedule. No single release can update them all at once, so the system has to keep **both names working** for a period. That period is the **alias period**. Suppose the team renames `booking.slot-free` to `availability.open`, because the same green now marks open vaccination drives and grooming sessions, not only appointment slots. ## The alias-period recipe 1. **Add the new token** carrying the real value and a `$description` of its intent. 2. **Turn the old token into an alias.** Its `$value` becomes a reference in braces, `{availability.open}`. In the Design Tokens Community Group format a brace reference resolves to the target token's `$value`, and tools must follow chained aliases until they reach an explicit value. 3. **Mark the old token deprecated** with `$deprecated`. The format accepts `true`, `false`, or a string explanation; a string that names the replacement is far more useful than `true`. 4. **Release as a minor version.** Semantic versioning says the minor version must be incremented when any public API is marked deprecated, and nothing breaks because the old name still resolves. 5. **Surface the warning where consumers work** — a deprecation annotation in generated code, a warning from the token build, a strike-through with the replacement on the documentation site, and a deprecated marker in the design library. 6. **Measure remaining usage** of the old name across every consumer, release by release. 7. **Remove the alias in a major release**, with a migration note that maps old names to new ones and, where the codebases allow it, an automated find-and-replace. The semantic versioning FAQ puts the minimum plainly: before removing functionality in a major release, there should be at least one minor release that contains the deprecation. ## What the consumer sees | Release | Old name | New name | Consumer experience | |---|---|---|---| | 4.3.0 (minor) | Deprecated alias | Added | Everything renders the same; warnings appear | | 4.4.0 to 4.x (minor) | Deprecated alias | Current | Teams migrate on their own schedule | | 5.0.0 (major) | Removed | Current | Any unmigrated reference now fails | ## Why an alias and not a copy - **A copy drifts.** When designers later adjust `availability.open`, the copied value stays behind and the booking calendar shows two slightly different greens depending on which name each screen used. - **An alias is one decision with two names.** The value lives in one place, so removal later is a pure naming change with no visual effect. - **An alias carries its own intent.** Its presence in the token graph shows exactly which name replaces it, which tooling and documentation can render as a link. ## Common mistakes - **Removing the old name in the same release** that adds the new one — that is a breaking change shipped as if it were compatible. - **Deprecating without naming a replacement**, leaving each consumer to guess which token is equivalent. - **Aliases that never die.** Without an exit condition — the next major, or measured usage reaching zero — the deprecated set grows until nobody knows which names are current. - **Renaming only in code** while the design library still offers the old name, so new designs keep specifying it. - **Renaming and changing the value in one step.** Consumers cannot tell whether a visual difference came from the migration or from the new value; do the rename first and change the value separately. How long the alias period lasts across the whole organisation, and who signs off a removal, is a governance policy; the mechanism above is what makes any such policy possible.

  • The team renamed a token once already, so an older name aliases the interim name, which aliases the current one. Is that chain a problem?
    Resolution still works, because the token format requires tools to follow chained aliases until they reach an explicit value. The problem is messaging: the oldest name's deprecation note points to a name that is itself deprecated. Repoint every deprecated alias directly at the current token and update its message, so each warning names the real replacement.
  • What should a consuming team do if it cannot upgrade to the major release that removes the old name?
    Stay pinned to the last minor release, where the alias still resolves, and plan the migration. Nothing forces an upgrade, and the deprecation warnings plus the migration note tell the team exactly which names to change. The cost is that it stops receiving new tokens and fixes until it migrates, which is the incentive the version boundary is meant to create.
  • Why ship the rename and a value change for the same token as two separate releases?
    If both land together, any visual difference a consumer sees could come from either the migration or the new value, and nobody can tell which. Renaming first through an alias is visually neutral, so consumers can migrate names mechanically; the deliberate value change then ships on its own, with its own release note and review.

saying these in an interview costs you the question

  • Just rename it and let each team fix their build errors.
  • Keep the old name as a copy of the new value during migration.
  • A deprecation needs no replacement name; the documentation will explain it.
  • Remove the old name in the next minor release once warnings have shipped.
  • Deprecated aliases are free, so they can be kept forever.