Shopify's checkout.liquid stopped rendering on information, shipping, and payment pages on a single day — August 13, 2024 — and every app built against it broke at once, no overlap, no grace period. Compare that to Polaris, Shopify's own component library, which is currently running two major versions side by side: production apps point at polaris-1.js while teams who want the new web-components architecture can opt into polaris-2.0-rc.js and migrate route by route. Same company, same quarter, two completely different theories of how you retire something people depend on.
That contrast is the whole lesson. Deprecation isn't a changelog entry. It's an operating decision about how much pain you're willing to transfer to the teams who built on top of you, and when.
The Checkout.liquid Lesson: Hard Cutoffs Create Debt, Not Velocity
The instinct to just set a date and force migration feels efficient. It isn't. The Checkout Extensibility rollout shows what a hard cutoff actually costs: a team inheriting that codebase today is still finding code written against surfaces that have been dead for over a year, because the cutoff didn't create urgency so much as it created orphaned code that nobody had time to clean up before the deadline hit (Vercel). Scripts and script tags for Plus stores followed the same pattern — sunset on a fixed date, August 28, 2025, with no transition window for teams who hadn't yet moved to Web Pixels (Vercel).
The failure mode here isn't the deprecation itself — checkout.liquid genuinely needed to go, and the sandboxed extension model is more durable precisely because it doesn't touch markup Shopify can change without notice. The failure mode is treating "we announced it" as equivalent to "teams had a path." A startup design system doing the same thing — killing a <Card> variant with a two-week notice in a Slack channel — gets the same outcome at smaller scale: a pile of components frozen mid-migration, maintained by nobody, breaking in ways nobody expects.
Polaris Shows the Alternative: Overlap, Then Let Teams Choose Their Moment
Polaris 2.0's release-candidate status is doing real work here. Shopify is explicit that 2.x is still release-candidate software and that production apps should keep pointing at polaris-1.js (Shopify Community) — which means teams get to decide, not be told, when they're stable enough to switch. The underlying architecture change is also bigger than a typical deprecation: Shopify rebuilt its Checkout Blocks app on Polaris web components and cut bundle sizes by up to 85% in the process (InfoQ), which is the kind of payoff that makes a migration worth asking teams to do voluntarily rather than forcing it. And the framework question that would normally stall adoption — does moving to web components mean abandoning React? — gets answered directly in the migration guide rather than left as a rumor: React 19 is the recommended path, and AppProvider still supports an embedded={false} mode for teams who don't want App Bridge loaded at all (Shopify Community).
That's the difference between a deprecation that respects velocity and one that taxes it: Polaris gave teams a reason to move (smaller bundles, matching the new admin style) and a safe window to do it in, rather than a cliff.
The Part Most Teams Skip: Make Deprecation a Documented State, Not a Deletion
GitLab's Pajamas system treats deprecation as a formal, visible lifecycle stage rather than a quiet removal. A deprecated component gets moved into a dedicated section, gets (⚠️ DEPRECATED) appended to its name and page, gets a note in its properties about what to use instead, and stays available for at least one milestone before it disappears — with an FYI agenda item on the weekly UX call so nobody is surprised (GitLab Pajamas). Breaking changes themselves get a severity rating — low, medium, high, extreme — so a team can tell at a glance whether a change needs a five-minute review or a coordinated migration (GitLab Pajamas).
That maps onto something I keep coming back to: a design system that's just a folder of components doesn't need this machinery, because there's no contract to honor. The moment other teams start depending on your decisions, deprecation policy becomes part of what you're actually shipping — not an afterthought bolted onto the component work (DEV Community). Versioning policy, a visible "deprecated" state, and a known overlap window aren't bureaucracy for its own sake. They're the difference between a team that trusts your system enough to build on it fast, and one that copies your component source into their own repo because they don't trust you not to pull the rug.
If you're planning a deprecation this quarter, the question worth asking isn't "when do we turn it off" — it's whether the teams depending on it can name their own migration date, or whether you're about to name it for them.
