A memory leak is memory that a program reserves and then never gives back, even though it no longer needs it. Every running program borrows memory from the system to hold its data. Normally it returns that memory when it is done. A leak happens when the program loses track of some memory and so never releases it. One small leak is harmless, but if it repeats, usage creeps steadily upward until the app slows to a crawl, gets killed by the system, or crashes the machine.
How a leak actually happens
When a program needs memory, it asks the system to set some aside. When it finishes with that data, it is supposed to release the memory so it can be reused. A leak occurs when the release never happens, usually because the program still holds a reference to data it has actually finished with. The system sees a reference, assumes the memory is still needed, and keeps it reserved forever.
The damage is cumulative. A leak in code that runs once barely matters. A leak in code that runs on every request, every frame, or every loop iteration adds up fast, which is why long-running servers and games are where leaks bite hardest.
Does garbage collection prevent leaks?
Many people assume languages with automatic garbage collection, like JavaScript, Python, or Java, cannot leak. They can. Garbage collection frees memory that nothing references anymore, but if your code accidentally keeps a reference, the collector sees it as still in use and never frees it.
| Memory model |
How memory is freed |
Leak risk |
| Manual (C, C++) |
You free memory yourself |
Forgetting to free it |
| Garbage collected (JS, Python, Java) |
Collector frees unreferenced memory |
Holding references you forgot about |
| Reference counted |
Freed when count hits zero |
Reference cycles that never reach zero |
So the cause differs, but no model is immune. Manual languages leak when you forget to free; managed languages leak when you forget to let go. It helps to understand what garbage collection is before chasing a leak in a managed language.
Common causes
// a classic managed-language leak: a growing cache no one clears
const cache = {}
function remember(key, value) {
cache[key] = value // entries are added but nothing is ever removed
}
Other frequent culprits include event listeners that are added but never removed, global variables that keep growing, and timers that hold onto large objects. The pattern is always the same: something keeps a reference alive longer than the data is actually needed.
How to find and fix leaks
- Confirm the leak first by watching memory usage over time; a steady upward slope under steady load is the signal.
- Use a memory profiler for your language to see which objects are growing and what is holding them.
- Look for collections that only ever grow, listeners that are never removed, and caches with no eviction.
- Fix by releasing references: clear caches, remove listeners, and let objects go out of scope when done.
- Re-measure after the fix to confirm usage flattens out, rather than assuming the change worked.
What to skip
- Skip guessing at the cause. Measure with a profiler first; the obvious suspect is frequently not the real leak.
- Skip restarting the app as a permanent fix. Scheduled restarts hide leaks but do not solve them.
- Skip unbounded caches. Always give a cache a size limit or expiry so it cannot grow without end.
- Skip ignoring small leaks in hot paths. A tiny leak per request becomes a crash over days.
FAQ
Can languages with garbage collection have memory leaks?
Yes. Garbage collection frees memory nothing references, but if your code keeps a reference you forgot about, the collector treats it as needed and never frees it. Forgotten references are the usual cause.
What are the symptoms of a memory leak?
Memory usage that climbs steadily under steady load, an app that slows down the longer it runs, and eventual crashes or the system killing the process. Restarting temporarily resets it, which is a strong clue.
How do I find a memory leak?
Use a memory profiler to watch which objects grow and what holds references to them. Look for ever-growing collections, caches with no limit, and event listeners or timers that are never removed.
Is a memory leak the same as high memory use?
No. High usage can be normal for a heavy workload. A leak is memory that is reserved but no longer needed and never released, so it grows over time even when the workload stays constant.
Where to go next
Learn what the kernel and memory management involve, understand what garbage collection is, and see how to write better code.