In Angular, how do developer preview and experimental APIs differ from stable ones, and would you ship them to production?
answer
- outside semver guarantees
- polished vs may never stabilise
- can change in a patch
- JSDoc stability tags in source
basics
~20 sDeveloper preview APIs in Angular are complete and polished but not yet stabilised; experimental APIs may change heavily or never stabilise. Neither is covered by semver or the deprecation policy, so either can change even in a patch release.
solid answer
~40 sStable Angular APIs follow semantic versioning and the deprecation policy. **Developer preview** APIs are fully functional and polished, but the team is not ready to stabilise them, usually to gather feedback or because docs or migration tooling are incomplete. **Experimental** APIs might change significantly or never become stable. For both, the versioning and deprecation policies **do not apply**: they can change at any time, even in a patch. In the source they carry tags such as `@developerPreview 20.0` or `@experimental 22.0`, while stable ones carry `@publicApi`. Using them in production is a team decision: developer preview is often reasonable if you wrap it, pin versions with a lockfile and read every changelog; experimental needs a stronger reason and an exit plan.
go deeper
Remember that Angular labels some APIs developer preview or experimental, and that those labels mean the usual upgrade guarantees do not apply.
Explain the difference: developer preview is polished but not yet stabilised, experimental may change heavily or never stabilise, and both can change in a patch.
Describe the guard rails you would put around a developer preview API in production: wrappers, lockfile discipline, changelog reading and tests on its behaviour.
Set a team rule for which stability levels may enter shared libraries versus leaf applications, and who approves exceptions.
Angular marks every public API with a stability level. The level decides which promises from the versioning policy you actually get when you depend on it. ## The three levels | Level | Source tag | What it promises | | :-- | :-- | :-- | | **Stable** | `@publicApi` (often with a version, e.g. `@publicApi 20.0`) | Semver and the deprecation policy: no breaking change outside a major, at least one major of deprecation before removal | | **Developer preview** | `@developerPreview` (e.g. `@developerPreview 20.0`) | Fully functional and polished, but not yet stabilised; may change at any time, even in a patch | | **Experimental** | `@experimental` (e.g. `@experimental 22.0`) | May change significantly before stabilising, or never stabilise at all | The docs give the reasons an API sits in **developer preview**: the team wants feedback from real applications before committing to it, or the documentation or migration tooling is not complete yet. Feedback goes through GitHub issues. **Experimental** is the earlier and riskier stage: the design itself may still move. ## Examples in v22.2 - The `@boundary` / `@error` template blocks for error boundaries are in **developer preview**, and the `ErrorDetails` interface they report is tagged `@developerPreview 22.2`. - `provideCheckNoChangesConfig()` is tagged `@developerPreview 20.0`. - Stability can be set **per member**: the `PendingTasks` class is `@publicApi 20.0`, while its `run()` method is still `@developerPreview 19.0`. - **Signal Forms** (`@angular/forms/signals`) were graduated to public API in 22.0, yet individual members there are still tagged `@experimental`. ## What "the policy does not apply" meant in practice The best-known cases are the signal APIs. **`effect()` changed its timing in v19 while it was in developer preview**: effects triggered outside change detection began running as part of change detection instead of as a microtask, and effects triggered during change detection began running before the component's template. Tests needed adjusting. Teams using it had accepted that risk. **`toSignal()`** only became stable API in v20 (it is tagged `@publicApi 20.0`), after several majors in which its behaviour could still change. The pattern is the usual path: 1. an API lands as **experimental** or **developer preview**; 2. real applications use it and report problems; 3. it is **stabilised** (the changelog says "mark ... as stable" or "graduate ... to public API"), and from then on semver and the deprecation policy protect it. ## Stabilisation is itself an upgrade event When an API graduates, its stable shape is not always its preview shape. The 20.0.0 changelog shows both outcomes: - `linkedSignal` was **stabilised** as it was; - `afterRender` was **renamed to `afterEveryRender` and stabilised** in the same change, so code using the preview name had to move. So when you plan an upgrade across a major, search the changelog for "stable", "stabilize" and "graduate" entries for every preview API you use: those are the places where your code may have to change even though no stable API was broken. ## Should production code use them? There is no blanket answer. The docs leave it to each team to decide whether the benefit is worth the risk of breaking changes. A reasonable policy: - **Developer preview: usually acceptable, with guard rails.** - Keep usage behind a small wrapper or a few call sites, so a changed signature is a local fix. - Rely on the lockfile, so even a patch update is a deliberate act. - Read the changelog for every update, patches included. - Cover the behaviour with tests that fail loudly if timing or semantics shift. - **Experimental: only with a concrete payoff and an exit plan.** Assume it may be redesigned or dropped; do not put it at the base of shared libraries that other teams depend on. - **Stable: the default.** When a stable alternative exists, prefer it. ## How to check an API's level 1. The guide for the feature says so up front; the error boundaries guide opens by stating that `@boundary` is in developer preview. 2. The JSDoc on each declaration carries the tag (`@publicApi`, `@developerPreview` or `@experimental`), usually with the version it was set in. 3. The changelog records the moment an API is marked stable, which is when the guarantees start. A candidate who says "it is in the official package, so it is covered by semver" has missed the point: being published and being stable are different things, and the tag decides which one you have.
- Can an Angular developer preview API change in a patch release?Yes. The versioning and deprecation policies explicitly do not apply to developer preview APIs, so they may change at any time, including in a patch. That is why teams using them rely on the lockfile and read every changelog, not only those of majors.
- Give an example of an Angular API that changed behaviour while in developer preview.effect() in v19: effects triggered outside change detection moved from running as a microtask to running as part of change detection, and effects triggered during change detection started running before the component's template. It was allowed because effect() was still developer preview; it became stable in v20.
saying these in an interview costs you the question
- Everything exported from an @angular package is covered by semver.
- Developer preview APIs cannot change until the next major release.
- Experimental and developer preview mean the same thing in Angular.
- An API that is still experimental is guaranteed to become stable later.
- Developer preview APIs are unfinished and should never reach production.