Skip to main content
Flux never sends immediately. Fire appends bytes to a Writer and returns, and the Bridge flushes accumulated writers on RunService.Heartbeat.

Flush timing

The accumulator drains in FRAME_TIME steps, but FlushAll is called at most once per Heartbeat. A frame that overshoots, say a 50 ms hitch, drains three steps and still performs a single flush, so the queue never backs up into a burst of sends.
The effective cadence is therefore min(heartbeat rate, 60Hz). At a healthy 60 FPS that is one flush per frame. On a client rendering at 30 FPS it is one flush per frame at 30 Hz, because Flux does not send faster than the heartbeat that drives it.

Writer groups

Sends are grouped by recipient and channel, because each group becomes one remote call.
Four groups:The per-player groups are maps keyed by Player, so a frame with sends to twelve different players produces twelve FireClient calls, one each, however many events were involved.
Broadcasts are flushed before per-player buffers. Across the two, ordering is not guaranteed: a FireAll issued after a Fire(player, ...) in the same frame will arrive at that player first, because it belongs to a different buffer. Ordering is only guaranteed within a single writer group.

What batching buys

One remote call, many events

Twenty Fire calls to one player in a frame become one FireClient with one buffer, instead of twenty separate network events.

Amortised per-call overhead

Roblox’s per-remote-invocation cost is paid once per group per frame rather than once per message.

Reused allocations

Writers come from a pool of up to 512 and are returned after each flush, so steady traffic stops allocating.

Shared instance table

Instances referenced by several events in one batch are deduplicated into a single side array.

Deduplicated instances

Within one writer, an Instance is only appended once. Repeat references write a varint index to the existing entry.
Instances never enter the buffer at all. They ride in the {Instance} array that FireClient takes as its second argument, and Roblox handles their reference translation. Only the index is serialised. This is also why sending an instance the receiver cannot see yields nil rather than an error.

Latency cost

Batching adds up to one frame of delay, roughly 16 ms at 60 FPS, between Fire returning and the bytes leaving. This is on top of normal network latency.For almost all gameplay this is invisible and well worth the throughput. It does mean Flux is not the right tool if you need a message on the wire this instant, and that a Fire immediately followed by a Destroy of the referenced instance may flush after the instance is gone.
There is no public flush API. Bridge.FlushAll() exists but the Bridge module is internal and not re-exported from the root, so reaching into it to force a send is unsupported and will fight the accumulator.

Ordering rules, summarised

Two reliable sends to the same recipient in the same frame arrive in the order you made them, because they are adjacent in one buffer and the receiver decodes sequentially.This holds across different event names, since all events share the writer.
  • Reliable against unreliable, which use separate remotes and separate buffers.
  • FireAll against Fire, which use separate writer groups, and broadcasts flush first.
  • Anything unreliable against anything else, since those packets may be dropped or reordered in transit by definition.
  • Listener execution order for a single packet, because each callback is task.spawned and the list is walked backwards.

Player disconnects

When a player leaves, the server frees both of their pending writers and drops the map entries in Players.PlayerRemoving. Anything written to them that frame but not yet flushed is discarded.
Fire(player, ...) on a player who has already left creates a fresh writer for a Player object that no longer has a map entry, and FireClient on a departed player does nothing. It will not error, but it does briefly hold a reference, so check player.Parent == Players before firing in long-lived loops.

Next steps

Wire format

What a flushed buffer actually contains.

Bridge API

The batching module in full.