Memory Management In Javascript. Part I - Garbage Collection


In software engineering, garbage refers to variables and references that are no longer in use. These leftover values still take up memory and should be cleaned up, either manually (in low-level languages like C or C++) or automatically (in higher-level languages like JavaScript).
JavaScript handles memory automatically through a built-in process called garbage collection. As a developer, you don’t need to explicitly free memory, but understanding how the garbage collector works can help you avoid memory leaks and write more efficient, performant code.
Bad programmers worry about the code. Good programmers worry about data structures and their relationships.
- linus torvalds
JavaScript memory is divided into two main regions: the stack and the heap. The stack is where primitive values like numbers, booleans, null, undefined, and symbols are stored. It’s fast and automatically cleaned up when a function finishes executing(no need to be garbage collected). The heap, on the other hand, is used for storing objects and functions. This is where garbage collection takes place, because heap memory is dynamic and sticks around until the runtime determines it’s no longer needed.
How Garbage Collection Works in JS
Modern V8 uses a strategy called generational garbage collection. This approach is based on the observation that most objects die young — meaning they are created and discarded quickly. So, the heap is split into two regions: the young generation and the old generation.
old v8 use refrence counting strategy for GC but it had issues, especially with cyclic references
The young generation, often called the nursery, is where newly created objects live. This area is scanned frequently and collected using a copying algorithm. When collection happens, only the live objects are copied to a new space, and the rest are discarded. This makes collection fast and naturally compacts memory, as live objects are packed together.
If an object survives several rounds of garbage collection in the young generation, it gets promoted to the old generation. This region is scanned less frequently and cleaned up using a mark-sweep-compact algorithm. First, the runtime marks all reachable objects. Then, it sweeps away the unreachable ones. If there’s significant memory fragmentation, it may also compact the memory by moving live objects around to make allocation more efficient.
While some phases of garbage collection are non-blocking — such as marking, which can happen asynchronously — others are not. Sweeping and compacting are Stop-The-World (STW) operations. That means JavaScript execution is paused entirely while the garbage collector frees memory or rearranges the heap. This can lead to small but noticeable delays, especially in memory-heavy applications or those with poor memory hygiene.
Virtual Memory vs Physical Memory (and JavaScript’s Role)
Physical Memory
This is your actual RAM — the real hardware inside your computer or phone. It’s fast but limited. For example, your laptop might have 8GB of physical memory.
Virtual Memory
Virtual memory is an abstraction provided by the operating system (like Windows, macOS, or Linux). Each running program thinks it has access to a big, private, continuous chunk of memory — this is virtual memory.
Virtual memory gives each JS runtime its own memory sandbox.
But under the hood, this virtual space maps to real physical memory (RAM) and disk storage (like swap/page files) if RAM gets full.
So even if your app asks for more memory than physically exists, the OS tries to manage it by:
Moving inactive memory to disk
Loading it back when needed
JS allocates memory in the virtual space, but performance depends on physical memory availability.
What This Has to Do With JavaScript
JavaScript runs inside a runtime like V8 (in Chrome and Node.js). V8 itself is a program running in your system’s virtual memory space.
When your JS code allocates memory (like creating an object):
V8 asks the OS for a block of virtual memory.
The OS gives V8 access to a portion of physical memory (RAM).
If your app uses too much memory, the OS might swap some to disk, making things slow.
Why This Matters for JS Developers
Just because you can allocate 1GB of objects in JS doesn’t mean your device has that much RAM available. It may crash or slow down, especially on mobile or low-spec devices.
Memory fragmentation (holes in allocated memory) can lead to inefficient use of RAM, even if total memory usage looks OK.
Garbage Collection (GC) is designed to free up memory — but if you’re using virtual memory inefficiently, or your heap grows too large, GC has to work harder, causing jank (UI stutter or delays).
In this part we covered how GC works in JS but In the next part, I’ll explore how to write GC-friendly JavaScript — covering techniques, patterns, and tools to reduce memory pressure and avoid leaks in real-world apps.
Stay tuned, and feel free to follow me on:
Subscribe to my newsletter
Read articles from Meiti directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Meiti
Meiti
TS/JS Engineer