Going Zoneless: The Checklist and the Failure Modes In short: Zoneless is the default for new apps from v21 and the target from v22. Existing apps are not switched for you — and that is deliberate, because this is the one change where Angular cannot fully protect you. The good news: the things that break are a short, well-known list. The switch And remove the polyfill: Do the provider change first, check everything works, then remove the polyfill. Keeping loaded while running is a valid middle step and a useful one — it means a mistake shows up as "updates slightly late" rather than "does not update at all." Two things to do first Skipping these is the main reason this goes badly: 1. everywhere , or v22's default with cleared up. If a component needs "check always," zoneless will break it — and you will be debugging two problems at once. 2. Signals in your data. Not everywhere, but anything that changes after the first draw and drives a template should be a signal, an input, or an pipe. An app still setting plain properties from callbacks is not ready. Do that work first. It is valuable on its own. The five things that break 1. / setting plain properties 2. Outside library callbacks The biggest real-world group. Any library that calls you back — maps, charts, payment widgets, video players, editors: 3. Promises and / setting plain properties Better still, this whole method is an . 4. Subscribing and setting plain properties and the pipe both tell Angular. A plain setting a property does not. 5. added by hand Note that in a template does tell Angular. The exception is only for listeners you attach yourself. Finding problems before your users do still exists in a zoneless app so libraries do not break, but no longer does anything — there is no zone to be outside of . Every occurrence is dead code you can delete. Testing without a zone , , and exist to control the zone. Without one, they are not available the same way. Vitest — the default runner from v21 — gives you , , and , which cover what and did with a clearer model. still works. Set up your tests to match production: Do this early. Running tests with a zone while shipping without one means your tests pass on behaviour you do not have. "But doesn't zoneless mean calling detectChanges() everywhere?" This is the fear that keeps teams on Zone.js, and it is backwards. What tells Angular in a zoneless app — none of which you write: A signal read in a template changes A template event fires An pipe produces a value A query signal changes A host binding value changes An changes In a signal-based component that is everything . The number of manual calls in a properly prepared app is typically zero . Where the fear comes from: teams that tried zoneless before doing the signals work. Turn the zone off on a project that sets plain properties from callbacks and yes — you will be adding everywhere and it will feel awful. That is not zoneless being hard. That is attempting the third change without the second. The two prerequisites at the top of this lesson are the whole difference. The second myth: "zoneless is just a smaller download." The payload is the least interesting part. Angular's guide lists four benefits, and only one is about size: Zone.js Zoneless --- --- --- Payload and startup Overhead in both Removed Work per event Any async task may mean a check Only reported changes Error reports Route through Zone.js Your code / Downlevelled to promises Native Tests / / Plain / The error-report row is quietly one of the most valuable. Debugging a production failure where every line between your handler and the error is framework internals is genuinely worse — and it has been normal in Angular for a decade. The architect's view The clearest illustration is any screen with a high-frequency interaction — dragging, panning, a canvas, an interactive map. The problem under Zone.js. It patches , so panning triggers a change-detection pass on every pointer move — potentially sixty times a second, each one checking the whole component tree. The interaction stutters, and the framework is doing the work despite almost nothing having changed. The workaround teams live with: This works, and look at what it costs. Every developer touching this file has to know which code runs inside the zone and which does not, and remember to hop back when it matters. Forget one and the screen silently stops updating — a bug that reads as "the selection is broken" and takes a while to trace back to a missing wrapper. The zoneless shape: No . No hopping in and out. Panning updates one signal, which marks exactly the components whose templates read it — the wrapper, not every seat. What actually changed, and why it matters beyond speed: A category of bug becomes impossible. "Forgot to re-enter the zone" cannot happen when there is no zone to be outside of. That was not a rare mistake — it was an ongoing tax on everyone who touched the file. The knowledge requirement drops. The first version needs e…