Angular's OnPush: Faster Apps by Doing Less

OnPush tells Angular to only re-render a component when its inputs change or its own events fire, not on every global event. It's a key performance boost for large apps, but mutating an input object directly won't trigger a re-render, causing a stale UI.
Why it exists
By default, Angular checks every component for changes after any browser event, timer, or data fetch. In large applications, this constant checking from the top of the component tree down can become a major performance bottleneck. ChangeDetectionStrategy.OnPush was created to give developers a way to opt out of this constant checking and define stricter, more performant rules for updates.
The mental model
Think of OnPush as changing a component's update subscription from "check me constantly" to "notify me only when it's important." Instead of Angular's default strategy of actively polling every component for changes, OnPush components are passive. They are considered "clean" and are skipped during the change detection cycle until a specific event explicitly marks them as "dirty" and in need of a check.
How it works
A component using OnPush will only be checked and re-rendered if one of four conditions is met. First, one of its @Input() properties receives a new object or value reference. Second, an event handler is triggered within that component or one of its children (like a button click). Third, an observable bound to its template via the async pipe emits a new value. Fourth, you manually tell Angular to check the component using ChangeDetectorRef.markForCheck().
When to use it
Use OnPush for any component whose state is primarily determined by its inputs, especially "presentational" or "dumb" components. It is the standard and most effective strategy when using state management libraries like NgRx or data services that provide immutable state objects. The goal should be to use OnPush as the default for all new components to build performant apps from the start.
When not to use it
Avoid OnPush if your component's rendering depends on a shared, mutable service or some other global state that is not passed in via @Input or an observable with an async pipe. In such cases, the component has no signal that the external data has changed, and its view will become stale unless you manually inject ChangeDetectorRef to trigger updates, which can become complex.
One canonical example
Consider a UserProfile component with an @Input() user property. If you pass it a user object and then another component mutates a property (user.name = 'new name'), OnPush will not update the UI because the object reference for user has not changed. The correct way to trigger an update is to pass a completely new object, for example: this.user = { ...this.user, name: 'new name' };. This new reference is the signal OnPush needs to run change detection.
Interview question
When an Angular component uses ChangeDetectionStrategy.OnPush, which scenario will NOT automatically trigger its change detection cycle?
- a.An event handler within the component is triggered.
- b.A property within an @Input() object is mutated directly.Correct
- c.An observable bound via an async pipe emits a new value.
- d.An @Input() property receives a new object reference.
Why? this is the answer
OnPush components only re-render if their input property reference changes, an event fires, or an async pipe emits. Mutating an existing input object's internal property does not change its reference, so OnPush will not detect it automatically, leading to a stale UI.
Just read this? Test yourself on what you have been reading.
Read the original → angular.dev
- #angular
- #performance
- #change detection
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on angular — each one lists the topics its interview covers.
See open roles