Skip to main content
Connect returns a handle with a single method:
The handle is a plain table, not an RBXScriptConnection. It has Disconnect and nothing else: no Connected property, no :Destroy(). It will not satisfy code or a cleanup helper that expects a real Roblox connection object.

Flux does not clean up after you

Listeners are not removed when the script that created them is destroyed.Flux stores listeners in module-level tables keyed by event name. Nothing watches script lifetime, Destroying, or AncestryChanged. A listener registered by a destroyed LocalScript stays registered for the lifetime of the session, keeps firing, and keeps its captured upvalues alive.Every Connect you make in a script that can be destroyed, or in a module you re-initialise, has to be disconnected explicitly.
This matters most in three places.
A LocalScript under StarterCharacterScripts runs again on every respawn. Without a disconnect, each life adds another listener and your callback runs once per life, cumulatively.
Connecting inside an Open() function and never disconnecting in Close() leaks one listener per open, along with every table the closure captured.
Reloading a module that connects at require time stacks listeners on top of the previous generation’s, and the old ones still hold references to stale state.

Patterns that hold up

Disconnect on destroying

Track a set of connections

Self-disconnecting listener

Useful when the condition to stop is known only inside the callback. This is also the workaround for Once not returning a handle.
If you already use a Trove, Janitor or similar helper, wrap the handle in a function so the helper can call it:
Passing the handle directly will not work, because those libraries look for :Destroy() or a real RBXScriptConnection.

Once and Wait

cleans up automatically
A Once listener removes itself from the listener list the moment it fires, so it cannot leak. It returns no handle, though, so it also cannot be cancelled if the event never arrives. A Once on an event that is never fired stays registered forever.
cleans up automatically
A Wait entry is removed when it resumes the parked thread. There is no timeout: if the message never comes, the thread is never resumed and both the thread and its listener entry stay alive for the session.
Guard a wait that might never be satisfied:

What Flux does clean up

For completeness, these are the internal resources Flux manages on its own.
Buffers larger than 64 KB are dropped rather than pooled, so a single oversized payload does not permanently inflate the pool’s memory footprint.

Next steps

Known limits

Every rough edge in one place.

Batching

How and when buffers are actually flushed.