Moving past Zone.js, Zoneless Angular introduces a leaner, more streamlined runtime. This article explores its implications and how to ensure your applications are ready for the future.

emoji_objects emoji_objects emoji_objects
Kevin Kreuzer

Kevin Kreuzer

@nivekcode

Jul 1, 2025

7 min read

Zoneless Angular
share

Lately, if you’ve been moving through the Angular ecosystem, you’ve probably noticed all the buzz about zoneless change detection. Here’s the thing: this is far more than a passing trend — it’s the direction Angular is taking for good.

By Angular 20, Zoneless has moved past its experimental stage, now sitting officially in Developer Preview.

But let’s step back before we jump into the details.

Hold On, What Exactly Is Zone.js?

For years, Zone.js has been the quiet engine behind Angular’s change detection, operating in the background to keep tabs on async activities. As a third-party library, it patches core browser APIs — such as setTimeout, Promise, and addEventListener — enabling Angular to detect when an async event happens and determine the perfect moment to inspect the DOM for updates. Quite ingenious.

Still, it has its downsides — Zone.js may fire off change detection cycles that aren’t needed, hampering performance. The Angular team has known about these issues for a long time, and zoneless mode is their solution. By dropping the dependency on Zone.js, zoneless mode delivers a more efficient and predictable approach to change detection for today’s Angular apps.

Zoneless Mode: Skip Zone.js, No Issue

First, let’s get one thing straight: zoneless mode doesn’t alter how change detection operates — it changes when it’s triggered and which areas of the app get pulled into that process. As a result, Angular can handle change detection with far greater precision and efficiency.

That really matters. Zoneless mode runs with absolutely no Zone.js at all, so Angular no longer depends on those patched browser APIs to decide when to refresh the UI. The job shifts over to more direct triggers instead — handing you more command and boosting performance by skipping extra change detection runs and dropping the cost of a third-party dependency.

So, in zoneless mode, what’s actually responsible for kicking off change detection? Here’s the quick rundown:

  • Any DOM event bound in the template (like (click))
  • A Signal gets updated
  • Applying the async pipe within the template
  • Using ComponentRef.setInput() to change inputs
  • Calling ChangeDetectorRef.markForCheck() manually
  • Creating or tearing down a component

To switch your application to Zoneless mode, add the method below to the providers array located in your app.config.ts.

provideZonelessChangeDetection();

With that line in place, Zone.js can be dropped entirely from your setup. If any Zone-related remnants are still hanging around, Angular will happily point them out in the console — a nice nudge to keep things clean 👏.

When you scaffold a fresh Angular 20 project via the CLI, it will ask upfront if zoneless change detection should be enabled, and if you say yes, it will insert the snippet above into your app.config.ts.

Zone.js vs. Zoneless Angular: A Side-by-Side Look

In a classic Zone.js-driven Angular app, change detection kicks off with just about any async operation — be it a setTimeout, a network call, or a Promise that has just fulfilled. That convenience, though, comes with a cost: it's not fine-grained, so you often end up with extra cycles that didn't really need to run.

Zoneless flips that premise. With Zone.js out of the picture (and its tendency to over-fire gone), the responsibility shifts back to you — with a hand from Angular's new reactive APIs — to signal exactly when the view should refresh.

Below, we'll walk through typical use cases, see how each mode handles them, and flag the spots where sneaky bugs tend to emerge.

🟢 Scenario 1: Click Handler

A simple event listener that modifies a property.

{{ count }}
<button (click)="count = count + 1">Update</button>

Zone.js: The count value is updated as expected.
Zoneless: The operation succeeds as well — this is largely because a fresh value is being set within the click handler. Still, a more robust and modern solution would involve converting the count variable into a Signal, which enhances reactivity and aligns more closely with Angular's recommended zoneless patterns.

🔴 Scenario 2: HTTP Request with subscribe

The traditional method of fetching data directly — ⚠️ Considered an anti-pattern and should definitely be avoided in most cases.

{{ data | json }}
this.http.get('/api/posts').subscribe((data) => {
  this.data = data;
});

Zone.js: Automatically initiates change detection.
Zoneless: Change detection is not triggered. In a zoneless setup, Angular lacks implicit knowledge of when to run change detection, so you must manage it yourself. The preferred solution is leveraging toSignal(), which obviates the need for a subscribe invocation. The next option is the async pipe, followed by explicit subscriptions that update signals. As a last resort—although generally discouraged—you can manually invoke markForCheck() when necessary.

🟢 Scenario 3: HTTP Request with async Pipe

This widely used strategy involves displaying template data retrieved as an Observable via HttpClient.

  <pre>{{ posts$ | async | json }}</pre>

Zone.js: Kicks off change detection
Zoneless: Operates without issues. Although the async pipe remains functional in a zoneless setup — and invokes markForCheck() on its own — transforming observables into signals via toSignal() is usually the preferred approach. It offers granular reactivity, prevents redundant checks, and integrates far more smoothly with zoneless detection. While the async pipe is still a viable choice, toSignal() delivers superior control and efficiency.

🔴 Scenario 4: Timer-Based Updates

A property that gets updated on a set schedule.

  setInterval(() => {
    this.count++;
  }, 1000);

Zone.js: This initiates change detection
Zoneless: No automatic trigger occurs here — change detection only fires when we explicitly invoke markForCheck() or modify a Signal. Both approaches will cause the component to re-render properly. The recommended fix is converting the count variable into a Signal.

🟢 Scenario 5: Signal Updates

Now we step into the Signals era.

  count = signal(0);

  increment() {
    this.count.update(c => c + 1);
  }

Zone.js: Triggers change detection
Zoneless: Works beautifully. Signals automatically notify the view.

If there's one takeaway from this article, it's that Signals are the solution. In short, when you adopt Signals, you're covered. They provide exact-level reactivity, fit perfectly with zoneless setups, and—critically—are built for the long haul. As Angular potentially shifts toward a change detection approach where only Signals prompt view refreshes, Signals become the safest bet you can make.

🟢 Scenario 6: ChangeDetectorRef.markForCheck()

This is a manual trigger—handy when Angular's change detection fails to pick up updates on its own. Call it to explicitly tell Angular to check for changes.

  this.data = newValue;
  this.cdRef.markForCheck();

Zone.js: Executes change detection.
Zoneless: Behaves precisely as expected.

🟢 Scenario 7: Refreshing Inputs with ComponentRef.setInput() or Template Bindings

The ComponentRef.setInput() method offers a direct, programmatic approach for modifying input properties on components created at runtime. Although this differs from how template bindings such as <my-component [data]="updatedData" /> operate, it fulfills an analogous function in dynamic contexts, guaranteeing that input values are refreshed and change detection is invoked.

In a zoneless setting, both template bindings and ComponentRef.setInput() function consistently without issues.

  componentRef.setInput('data', updatedData);
  // or
  <my-component [data]="updatedData"/>

Zone.js: Fires change detection
Zoneless: CD gets triggered by design. Angular detects input changes on its own, with no dependency on Zone.js.

Preparing Your App for a Zoneless World

With Angular’s transition to a zoneless architecture on the horizon, two main approaches can help you get your application ready. The first—fully committing to OnPush—tends to be the easier path and generally doesn’t demand a complete overhaul. The second—adopting Signals across the board—offers greater resilience and long-term advantages, but it can require a deeper and more extensive refactor.

1. Commit Fully to OnPush

If OnPush is already working well in your project, you’re set — it will carry over without a hitch into a zoneless setup.

2. Drive Everything with Signals

Honestly — Signals are the ultimate secret weapon for Zoneless Angular. When every piece of dynamic state flows from Signals, your application will run seamlessly even in the absence of Zone.js.

And when you run into those unavoidable Observable-based APIs? Just bridge them:

  const posts = toSignal(this.postService.getPosts());

Boom — reactive, streamlined, and free from Zoneless complications.

Hybrid Scheduling (> Angular 18+)

Moving on to the interesting part. From Angular 18 onward, Zoneless and Zone-based approaches merge through hybrid scheduling. This is what it addresses:

In the past, modifying a Signal outside Angular’s zone—for instance, within setTimeout or runOutsideAngular()—could leave your UI in the dark, failing to refresh. 😬

What’s the situation now?

   ngZone.runOutsideAngular(() => {
      setInterval(() => signal.set(newValue), 1000);
   });

ℹ️ The ignoreChangesOutsideZone flag first appeared in Angular v18 as a conservative measure to disable the updated scheduling behavior that triggers change detection for select events happening beyond the Zone. Once the release showed encouraging outcomes, the Angular team determined the approach was sound, leading to the deprecation of this option. Setting it to true should be a rare exception, if it happens at all.

✅ Flawless performance. Signal changes reliably kick off change detection from any context, eliminating the need for those fragile workarounds.

Angular 20’s Zoneless: Entering Developer Preview 🎉

The Zoneless approach has moved past the experimental phase—Angular 20 brings it into Developer Preview status.

In the past six months, the Angular team made substantial progress on Zoneless, particularly in the realms of server-side rendering (SSR) and error management.

A lot of developers overlook that Zone.js is silently handling error capture for them. Additionally, during SSR, Zone.js is essential for determining the right moment to send rendered output to the client. Transitioning to Zoneless required tackling these challenges head-on.

What’s new in v20:

  • Angular now provides built-in handlers for unhandledRejection and uncaughtException in Node.js, preventing server crashes while rendering via SSR.
  • On the browser side, provideBrowserGlobalErrorListeners() gives you the ability to handle global errors.

Curious to give it a spin? Here’s how to configure it:

 bootstrapApplication(AppComponent, {
   providers: [
     provideZonelessChangeDetection(),
     provideBrowserGlobalErrorListeners()
   ]
 });

And one more thing: make sure the Zone.js polyfill is stripped out of angular.json.

When you kick off a brand-new Angular project, here’s the good news: the CLI can set it up as Zoneless right away.

Final Thoughts

Zoneless change detection is far from a side project — it’s the future of Angular. The earlier you adopt OnPush, Signals, and solid reactive patterns, the easier your transition will be.

So, whether you’re modernizing an existing codebase or building greenfield, now is the moment to look past the Zone.

And if you’re already shipping Zoneless apps out there, I’m curious to hear your experience. Reach out whenever. ✌️

Liking how the code looks? Check out our brand-new theme plugin

Skol - the ultimate IDE theme

Skol - the ultimate IDE theme

Bring the aurora directly into your editor. A clean, minimal dark theme designed for comfort and visual clarity.

Create responsive applications using Angular and AI

AI-Powered Angular Video Series

Angular + AI Video Course

A practical guide to embedding AI directly into Angular applications with Hash Brown, crafting responsive and smart interfaces.

Discover how to implement real-time chat streams, invoke tools, generate dynamic UI components, and parse structured outputs, all in a progressive tutorial.

Get ready for Angular's next evolution and master Signals with this comprehensive resource!

Angular Signals Masterclass eBook

Angular Signals Mastercalss eBook

Angular Signals are a cornerstone of modern development. Here, you’ll get to know their full API and see how they work under the hood.

Sharpen your skills and get ready for what Angular has in store. Stay ahead of the pack today!

Enjoying this read? Want to dive deep into Angular's cutting-edge Signal Forms?

Angular Signal Forms: A Practical Deep Dive

Angular Signal Forms: Hands-On Masterclass

Work through 12 step-by-step chapters that blend core concepts with practical exercises to get a firm grip on Angular's newly launched Signal-Forms.

You'll cover the essentials of form handling, validation rules, bespoke controls, nested form groups, approaches for transitioning existing code, and a whole lot more.

Win win deal illustration

Get notified
about new blog posts

Register for Angular Experts Content Updates & News, and we'll let you know the moment a fresh blog post on Angular, Ngrx, RxJs, or other fascinating Frontend subjects goes live!

Your email stays between us—rest assured, **it will never be shared with a third party, and unsubscribing is painless.

Occasional promotional extras might accompany these emails; refer to our Privacy policy for full details.

Responses & comments

Feel free to raise questions, share your personal stories, and offer your viewpoint on the subject at hand.

You might also like

Dive into other posts from the Angular Experts team for deeper insights on associated subjects, with a spotlight on Modern Angular !

Angular Signal Forms: Custom Controls Without ControlValueAccessor

Angular Signal Forms: Custom Controls Without ControlValueAccessor

Build reusable Angular custom controls with FormValueControl, model(), touch events, and schema-driven validation—without writing a ControlValueAccessor.

emoji_objects emoji_objects emoji_objects
Kevin Kreuzer

Kevin Kreuzer

@nivekcode

Aug 12, 2026

7 min read

Angular Signal Forms: The Missing Create/Edit Pattern

Angular Signal Forms: The Missing Create/Edit Pattern

Learn a practical Angular Signal Forms pattern for create and edit flows, with route-based mode, edit data loading, linkedSignal prefilling, submit branching, and validation context.

emoji_objects emoji_objects emoji_objects
Kevin Kreuzer

Kevin Kreuzer

@nivekcode

Aug 1, 2026

6 min read

Angular Signal Forms Essentials

Angular Signal Forms Essentials

Understand the core concepts behind modern Angular Forms. Learn how to create Signal Forms, wire them up in templates, use built-in and custom validators, handle cross-field validation, submit forms, and more.

emoji_objects emoji_objects emoji_objects
Kevin Kreuzer

Kevin Kreuzer

@nivekcode

Feb 14, 2026

12 min read

Put our deep expertise to work for your team

For years, the Angular Experts team has partnered with both large enterprises and emerging startups, delivering workshops and tutorials, and cultivating a rich ecosystem of open source projects. Our deep knowledge of modern front-end development is something we are genuinely proud of, and we would love to see your business thrive with our support