0

Ship a breaking API change to a library community

by · about 3 hours ago· ⑂ 0 remixes

Question: Ship a breaking API change to a library community

Companies: Hugging Face

Problem statement

Describe planning a breaking public API migration for a widely used library: how the rollout was staged and how users were carried along. Reported on 1point3acres' Hugging Face bank; reconstructed in our own words.

What the question probes

Hugging Face maintains libraries that millions of people import. A breaking change there is not an internal migration with a deadline; it lands on users you can't see, can't message directly, and can't force to upgrade. The question tests whether you understand that:

  1. Empathy for downstream users. Do you think about the person whose notebook breaks, the company pinned to an old version, the tutorial that's now wrong?
  2. A staged plan. Deprecation, warnings, migration tooling, a long overlap, then removal, with dates and criteria.
  3. Measurement. How do you know how many people use the old API, and when it's safe to remove?
  4. Communication in public. Release notes, a migration guide, issues and forum threads, and how you respond to angry users.
  5. Judgment on whether to break it at all. The best answers question the break first.

If you haven't done exactly this, use the closest story: an internal API used by many teams, a public SDK, a database schema change with many readers. Then say how it would differ in open source.

First: should you break it?

Start your answer by showing you considered not breaking it. Options, cheapest first:

  • Add, don't change. New parameter or new function next to the old one; keep the old one working indefinitely.
  • Shim. Keep the old signature as a thin wrapper over the new implementation.
  • Break behind a flag. Opt in now, flip the default in the next major version.
  • Break. Only when keeping the old behavior blocks something important (correctness, security, performance, a design that can't evolve).

Be specific about the cost of keeping it: "Maintaining both code paths meant every new model had to be implemented twice, about 20% of contributor time on new architectures."

The staged plan

A typical plan for a widely used library, with rough timing:

Stage When What happens
1. Proposal Week 0 Public issue or RFC: what changes, why, the migration path; invite objections from major downstream projects
2. New API ships Release N New API available; old API works unchanged; docs show the new way
3. Deprecation warnings Release N+1 Old API emits a FutureWarning naming the removal version and linking the guide; warn once per process, not per call
4. Migration tooling With N+1 A codemod or script that rewrites common uses; a migration guide with before/after for each case
5. Downstream help N+1 to N+3 Pull requests to the 10–20 biggest dependent projects; office hours or a pinned forum thread
6. Removal Next major, ≥ 6 months later Remove only if usage has dropped below an agreed threshold; otherwise extend

Two details that separate senior answers:

  • Warnings must be actionable. "X is deprecated" is not enough. Say what to use instead, when it will be removed, and link to the guide.
  • Removal has a criterion, not just a date. For example: "remove when fewer than 5% of the top 1,000 dependent repositories still call the old API", checked by searching public code.

Measuring usage

You can't see your users' code, but you can estimate:

  • Public code search across dependent repositories on GitHub. Count calls to the old API in the top N dependents by stars or downloads.
  • Hub metadata. For model or config format changes, scan public model repositories' config files: how many use the old field?
  • Download stats by version to see how fast users upgrade. If 40% of downloads are still for a release from a year ago, a removal in the next release will hit them when they eventually upgrade.
  • Issues and forum mentions after warnings ship: a spike tells you which use cases your guide missed.

Worked numbers: say 12,000 public repositories import the library and a code search finds the old API in 3,000 of them (25%). After six months of warnings plus pull requests to the top 50 dependents, it's in 900 (7.5%). If the agreed threshold was 5%, you extend by one release and target the next 100 dependents, rather than removing on schedule.

Worked example (L5)

"I maintained the data-loading module of an open-source training library with about 2 million monthly downloads. Our load_dataset(path, split_ratio=...) silently shuffled before splitting, so the same call gave different train/test splits across versions. That's a correctness bug for anyone comparing results.

Fixing it meant changing default behavior, which breaks reproducibility for everyone who relied on the old splits, ironically the same people the fix was for. So I proposed a new seed parameter, with the old behavior kept when it's absent but emitting a warning that explained the reproducibility problem and showed the one-line fix. I opened an issue first; two maintainers of large downstream projects asked for a way to reproduce old splits exactly, so I added legacy_split=True.

After two releases, code search showed seed in about 60% of calls in the top 500 dependents. We made seed required in the next major version, with legacy_split kept for one more major. We got about 30 issues in the month after the major release; most were from people who'd suppressed warnings, so I added the migration snippet to the error message itself. Issues dropped to a handful."

Worked example (L6)

"I led the move from our library's original configuration format to a new one that could describe multi-modal models. Thousands of public models used the old format, and other libraries parsed it too, so a break would ripple beyond our users.

I spent the first month on the ecosystem, not the code: I scanned about 200,000 public model configs and found 14 distinct patterns, 3 of which covered 95% of them. I wrote a converter for those 3 and ran it on every public config to find failures before anyone else did. I contacted maintainers of the four other libraries that parsed our format and agreed a shared schema with them before release.

We shipped a reader that accepted both formats indefinitely and a writer that only wrote the new one. That was the key decision: reading old files forever cost us about 300 lines, but meant no model on the Hub ever stopped loading. Over a year, new uploads in the old format went from 100% to under 3%. We never removed the old reader, and I'd make that call again: the cost was tiny and the trust it bought was large."

Red flags

  • "We announced it and removed it in the next release." No overlap, no tooling.
  • No thought about whether to break it at all.
  • Removal on a date regardless of usage.
  • Dismissing angry users. In open source, some will be loud; the response should be patient and specific.
  • Only thinking about direct users, not the libraries and tutorials built on top.

Follow-ups

  • "A large company says the change will cost them weeks and asks you to delay. What do you do?"
  • "How do you handle users who pinned an old version and never upgrade?"
  • "What if a security fix requires breaking the API immediately?" (Ship the fix, provide the narrowest compatibility shim you safely can, and communicate loudly; the staged plan compresses but its parts stay.)
  • "How do you write a deprecation warning that people actually read?"
  • "How do you decide between semantic versioning's major bump and a long deprecation within a major?"

Interviewer expectations

Mid-level (L4)

  • Describes deprecation warnings, a migration guide and an overlap period.
  • Thinks about users who are affected and how to tell them.
  • Has a real or adjacent story with a result.

Senior (L5)

  • Questions whether to break at all and considers shims and opt-in flags.
  • Plans stages with versions and dates, actionable warnings, migration tooling, and help for major downstream projects.
  • Measures usage of the old API and ties removal to a threshold.

Staff (L6+)

  • Treats the ecosystem as the system: coordinates with other libraries, scans public artifacts to find breakage before users do.
  • Makes asymmetric choices like reading old formats forever, explaining the cost and the trust it buys.
  • Has thought about governance: who decides breaking changes, how the community is consulted, how to handle a security-driven break.

Sign in to comment, vote or remix.