---
title: "Zoneless change detection and render lifecycle"
chapter: "05"
---

# Zoneless change detection and render lifecycle

Zoneless is the default in Angular 21 and later. Angular refreshes views from
known notifications instead of patching every browser async API through
Zone.js.

## Notifications

Angular learns a view may need work when a template-read signal changes, an
input is set, a listener runs, `AsyncPipe` emits, a marked view is attached, or
code calls `markForCheck`.

Code that mutates an untracked plain field after a timer may not update the
view. Make state visible through signals, inputs, or supported notification.

## OnPush

OnPush remains useful because it encourages explicit data flow and zoneless-
compatible components. It is not a magic performance flag and does not repair
mutated inputs.

## Lifecycle

Use constructor/field initialization for dependency setup, `ngOnInit` for input-
dependent initialization, and `ngOnDestroy` or `DestroyRef` for cleanup. Avoid
work in frequently invoked checked hooks.

## Render callbacks

`afterNextRender` and `afterEveryRender` coordinate DOM-dependent work after
rendering. Keep browser-only APIs guarded for SSR. Use cleanup when the callback
owns observers or third-party instances.

## Expression changed errors

These errors expose a state mutation during a check that made the rendered
result unstable. Fix ownership and timing rather than adding arbitrary
`setTimeout`.

## Performance model

Signals reduce the affected graph; component boundaries, stable identity,
deferred code, DOM size, JavaScript work, and network latency still matter.
Measure with browser performance tools and Angular DevTools.

## Feynman check

Zoneless does not mean “Angular never checks.” It means Angular checks in
response to explicit notifications. Name the notification for every state
update on one page.
