
Ever noticed your Angular app slowing down over time, freezing, or even crashing? These are common symptoms of memory-related issues — and they can creep in silently. If you want a smooth, high-performing app, managing memory is non-negotiable.
In this guide, I’ll walk you through practical strategies to reduce memory usage in Angular, backed by real-world patterns and tools.
🧠 What Causes High Memory Usage in Angular?
Before jumping into fixes, let’s quickly understand what’s eating up memory in the first place:
- 🔁 Memory Leaks: Unsubscribed observables, forgotten timers, or lingering DOM refs
- 🧱 Too Much DOM: Over-rendering or large, unoptimized templates
- 📦 Heavy Objects: Storing giant arrays/objects you don’t really need
- 🔄 Overactive Change Detection: Everything re-evaluating when only one thing changed
- 🕳️ Dangling Subscriptions: Observables that never complete or unsubscribe
- 💥 Big Bundle Size: Everything loading at once, even stuff users may never see
🛠️ Fixing It: Strategies to Slim Down Memory Usage
1. 🔍 Find and Fix Memory Leaks
Memory leaks are the silent killers. They keep unused data hanging around in memory. Here’s how to detect and prevent them:
✅ Use Chrome DevTools Memory Profiler:
- Go to Chrome DevTools → Memory
- Take heap snapshots before and after navigation
- Look for retained objects that shouldn’t exist anymore
✅ Always Unsubscribe from Observables
import { Subscription } from 'rxjs';
export class MyComponent implements OnDestroy {
private sub = new Subscription();
ngOnInit() {
this.sub = this.myService.getData().subscribe(data => {
console.log(data);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
💡 Better: Use the async
pipe in templates whenever possible — no manual cleanup needed!
<div *ngIf="data$ | async as data">
{{ data }}
</div>
2. 🧼 Optimize Change Detection
Angular’s default change detection strategy checks everything. That’s powerful but not always efficient.
✅ Use OnPush
for Smarter Checks
@Component({
selector: 'app-lite',
templateUrl: './lite.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LiteComponent {
@Input() data: any;
}
✅ Detach Change Detection if Needed
For components that don’t need reactive updates:
constructor(private cdRef: ChangeDetectorRef) {}
ngOnInit() {
this.cdRef.detach();
}
3. 🧳 Don’t Keep Everything in Memory
Don’t load thousands of records when you only need 20.
✅ Use Pagination or Infinite Scroll
- Fetch small chunks from your backend
- Use Angular Material’s paginator or build your own
✅ Use Lazy Loading for Routes
const routes: Routes = [
{
path: 'analytics',
loadChildren: () => import('./analytics/analytics.module').then(m => m.AnalyticsModule)
}
];
4. 🖼️ Render Smarter: DOM Optimization
Huge lists and deeply nested components can hammer performance.
✅ Use Virtual Scrolling
<cdk-virtual-scroll-viewport itemSize="60" class="scroll-container">
<div *cdkVirtualFor="let item of items">{{ item }}</div>
</cdk-virtual-scroll-viewport>
✅ Avoid Complex Logic Inside Loops
Heavy pipes or conditionals inside *ngFor
can kill performance. Move that logic outside the template or memoize it.
5. 📦 Keep Your Bundle Lean
Big bundles = more memory + slower boot.
- ✅ Use
ng build --prod
to enable tree-shaking and minification - ✅ Audit and remove unused npm packages
- ✅ Split code using lazy loading
- ✅ Consider dynamic imports for rarely-used components
6. ⚙️ Offload Heavy Work with Web Workers
If you’ve got expensive computations, don’t block the UI thread. Use web workers:
const worker = new Worker(new URL('./math.worker', import.meta.url));
worker.postMessage({ input: 1000000 });
worker.onmessage = ({ data }) => {
console.log('Result from worker:', data);
};
7. 🧠 Smarter State Management
Avoid keeping multiple copies of the same data floating around.
- ✅ Use NgRx, Signals, or a shared service
- ✅ Centralize shared data and clean it up when no longer needed
- ✅ Remove unused services or avoid singletons with retained memory
✅ Final Thoughts
Memory optimization in Angular isn’t just about speed — it’s about scalability, stability, and user trust. Sluggish apps cost users, and crashes damage credibility.
TL;DR:
- 🔍 Fix leaks with DevTools + unsubscribe properly
- ⚙️ Use OnPush + detach when possible
- 📦 Keep your bundles small and lazy-load
- 🖼️ Use virtual scroll for lists
- 🧠 Manage memory like a pro with centralized state and services