Do event handlers stop garbage collection from occurring?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Event handlers do not stop garbage collection globally, but they can keep specific objects alive longer than expected. The issue is not the garbage collector itself. The issue is that an event subscription can create a reference chain that keeps an otherwise unused object reachable.
Why Event Subscriptions Affect Lifetime
A garbage collector frees objects that are no longer reachable from application roots. When one object subscribes to events published by another, the publisher often stores a delegate or callback reference, and that reference may point back to the subscriber.
In C#, a typical subscription looks like this:
If Publisher lives for a long time, it keeps the delegate list alive. That delegate references the subscriber instance, so the subscriber remains reachable and cannot be collected yet.
The Garbage Collector Is Still Working Correctly
This point matters: event handlers do not block or disable garbage collection. The collector is doing the right thing. It sees a valid reference path, so it treats the subscriber as live memory.
A useful mental model is:
- A long-lived publisher stores a callback.
- The callback points to a method on a subscriber.
- The subscriber is still reachable through that callback.
- Because it is reachable, the collector keeps it.
If the publisher itself becomes unreachable, then the whole graph can usually be collected together.
A Real Leak Pattern in C#
The classic leak appears when a long-lived service publishes events and short-lived UI objects subscribe.
If TimerService is effectively a singleton and old Dashboard instances are never unsubscribed, they accumulate even after the UI no longer needs them.
That is why event-heavy C# code often pairs subscriptions with Dispose or another explicit cleanup step.
Browser Event Listeners Have the Same Risk
JavaScript uses different runtime internals, but the reachability issue is similar. A DOM node or other event target can keep a callback alive, and that callback can close over other objects.
If the listener is never removed and the target remains reachable, the closure may keep model in memory longer than intended.
When Event Handlers Are Harmless
An event subscription is not automatically a leak. If the publisher and subscriber have the same lifetime, the collector can often reclaim both at the same time.
For example, if a short-lived component creates a DOM element, attaches a listener, and then the entire component tree becomes unreachable together, there may be no practical leak.
The risky cases usually involve lifetime mismatches, such as:
- a global singleton publisher
- a cache or service that lives for the entire app session
- frequently created UI views that subscribe but never detach
- anonymous handlers that are difficult to remove later
Safer Cleanup Patterns
The most direct fix is explicit unsubscription.
And in browser code:
For more structured cleanup, modern browser code can use AbortController:
In .NET, weak event patterns are another option when you want the subscription not to keep the subscriber alive strongly.
Common Pitfalls
A common mistake is assuming the garbage collector will notice that an object is no longer useful and remove it anyway. If an event publisher still references it, the collector cannot safely do that.
Another pitfall is subscribing with inline lambdas and later having no direct handle for unsubscription.
Captured state can also hide the real memory cost. A tiny event handler may keep a much larger object graph alive through its closure.
Finally, memory leaks from event subscriptions often appear only after repeated navigation or repeated object creation, so they can be missed by simple manual testing.
Summary
- Event handlers do not stop garbage collection, but they can keep objects reachable.
- The leak risk comes from reference chains between publishers, delegates, and subscribers.
- Long-lived publishers and short-lived subscribers are the classic problem.
- Unsubscribe explicitly when object lifetimes differ.
- Both C# events and JavaScript listeners need cleanup discipline to avoid memory leaks.

