A pipe transforms a value for display. By default a pipe is pure: Angular calls transform only when the input reference changes. Marking it pure: false makes it impure, and Angular runs it on every change-detection cycle, which is powerful and easy to misuse.
Before you start
You should be comfortable with templates and change detection. This article explains pipe purity; it assumes you know how to declare a standalone pipe.
Step-by-step walkthrough
Step 1: Rely on purity and memoization
A pure pipe runs when its input changes by reference and its result is cached between runs. *ngFor with filter on an array works because a new array reference triggers the pipe, and Angular skips it otherwise. This is why pure pipes are cheap and are the default.
Step 2: Know when a pipe becomes impure
A pipe is impure if you set pure: false or if it depends on mutable state such as Date.now() or a service property that changes without the input changing. An impure pipe runs on every cycle, so a filter over a large list re-runs on every keystroke anywhere in the app.
Step 3: Prefer derived state over impure pipes
When the transform depends on more than the input, compute it in the component with a signal or getter and pass the result in, so the work is tied to the real dependency. Reserve impure pipes for genuinely time-based or global-state displays, and keep them trivial.
Worked scenario
The pure pipe transforms only when the list reference changes.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'active', pure: true })
export class ActivePipe implements PipeTransform {
transform(items: { active: boolean }[]): { active: boolean }[] {
return items.filter((item) => item.active);
}
}Walk through the example
ActivePipe runs when a new array reference arrives and caches the filtered result otherwise. Replacing the array immutably triggers it correctly; mutating the array in place does not, because the reference is unchanged. That trade-off is why immutable updates pair with pure pipes.
Common mistake
Marking a pipe impure to make it notice a mutated array, which runs it on every cycle and hides the real problem, a mutation that should have produced a new reference. Another is putting an HTTP call or heavy computation in a pipe, which is a job for the component or a service.
Verify the behavior
Log inside transform and confirm a pure pipe runs only when the input reference changes. Switch the pipe to impure and count the calls during an unrelated keystroke; the count should jump on every cycle. Replace the in-place mutation with an immutable update and confirm the pure pipe runs again.
Interview exercise
A filter pipe misses updates after a push to the source array. Why, and what is the fix?
Answer and reasoning
A pure pipe compares by reference, and push mutates the existing array without changing its reference, so Angular sees no input change and skips transform. The fix is to produce a new array, for example with the spread operator, so the reference changes; making the pipe impure would work but re-runs it on every cycle and hides the mutation.
Continue learning
Compare derived state in Angular signal derived values and OnPush and input identity. Read the Angular pipes guide and try the Angular interview questions.