Explain Angular default change detection, zone.js, and OnPush

Deep knowledge of Angular's automatic vs explicit change detection. Explain zone.js monkey-patching async APIs to trigger default checks; contrast with OnPush requiring immutable inputs, async pipe, or markForCheck.
WHAT THIS TESTS: This question probes whether you understand the difference between Angular's implicit, global change detection model and the explicit, localized OnPush model. Interviewers want to see that you know zone.js is the mechanism that makes the default strategy automatic, and that you understand the architectural contract you must uphold when opting into OnPush for performance.
A GOOD ANSWER COVERS: First, zone.js monkey-patches browser APIs like setTimeout, Promise, and XHR so that any asynchronous task notifies Angular to run change detection from the root component downward. Second, the default CheckAlways strategy means Angular traverses the entire component tree during every detection cycle regardless of whether data changed. Third, OnPush short-circuits subtree checks unless one of three things happens: an input property receives a new object reference, an event originates from the component or its children, or ChangeDetectorRef.markForCheck is called explicitly. Fourth, to make OnPush reliable you must adopt immutable data patterns so input reference changes actually fire, use the async pipe in templates so Angular handles subscription and marking automatically, and call markForCheck after any manual async state mutation. Fifth, mention that OnPush is most valuable in large component trees where rendering is expensive.
COMMON WRONG ANSWERS: Claiming that OnPush completely disables change detection rather than making it conditional. Saying zone.js is still required for OnPush components to work, when in fact OnPush is often paired with zoneless strategies in modern Angular. Asserting that mutating object properties is fine as long as you use OnPush, which misses the reference equality check entirely. Suggesting two-way binding with ngModel works seamlessly with OnPush without understanding the reference contract.
LIKELY FOLLOW-UPS: How would you handle a third-party library that mutates state without notifying Angular? Can you mix CheckAlways and OnPush components in the same tree? How does Signals-based change detection in newer Angular versions affect the need for OnPush?
ONE CONCRETE EXAMPLE: Imagine a parent component fetching a user list via HTTP and passing it to an OnPush child table. If the parent pushes a new user into the existing array, the child never re-renders because the array reference is unchanged. The fix is to create a new array with the spread operator, const newList = [...oldList, newUser], which changes the input reference and triggers OnPush. If the child instead subscribed to an RxJS observable internally, it should use the async pipe in its template rather than subscribing in TypeScript, because the pipe calls markForCheck automatically when values emit.
Read the original → angular.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.