From raw remotes
Flux replacesRemoteEvent, UnreliableRemoteEvent and RemoteFunction. The mapping is mostly
mechanical.
Before and after
UnreliableRemoteEvent per message, and no
RemoteFunction.
What changes behaviourally
Sends are delayed by up to one frame
Sends are delayed by up to one frame
FireClient puts bytes on the wire during the call. Fire appends to a buffer that flushes on
the next Heartbeat, up to about 16 ms later.This is almost always invisible, but a Fire immediately followed by destroying the referenced
instance may flush after the instance is gone.Connections are not RBXScriptConnections
Connections are not RBXScriptConnections
Connect returns a plain table with only Disconnect. There is no Connected property and no
Destroy, so helpers like Trove or Janitor will not accept it directly. Wrap it in a
function.More importantly, nothing is cleaned up when your script is destroyed. Raw remote connections
die with their script; Flux listeners do not. See Connections.Listener order is not registration order
Listener order is not registration order
Flux walks its listener list backwards and dispatches each with
task.spawn, so the most
recently connected runs first and all run concurrently. Raw RBXScriptSignal ordering
assumptions do not carry over.Invoke errors lose their stack
Invoke errors lose their stack
RemoteFunction errors propagate with more context. Flux transmits the message text and
re-raises it with error(tostring(...)), so there is no stack trace and no error object.Invocations have a 60-second timeout
Invocations have a 60-second timeout
A
RemoteFunction invoke can hang indefinitely. Flux raises "Request timed out" after 60
seconds, and the timeout is not configurable.One name means one channel
One name means one channel
Two
Flux.Server("Chat") calls share listeners, handlers and schemas, because the object is a
typed handle over state keyed by name. Two Instance.new("RemoteEvent") calls were genuinely
separate. Namespace your names.Replacing InvokeClient
Flux has no server-to-client invocation, so split the round trip into two events:From a Warp-style API
If you have used Warp, Flux’s shape will be familiar: named events, oneServer and Client
pair, Fire and Connect, and reliable plus unreliable on the same object. Most call sites port
directly.
These are the differences to check for.
No unified constructor
No unified constructor
There is no
ReferenceBridge or equivalent auto-detecting factory. Flux’s internal Bridge
module is the batching layer, not an environment selector, and it is not re-exported.Branch on RunService:IsServer() in shared modules. See
Shared Modules.Invocations are one-directional
Invocations are one-directional
Client to server only. The server has no
Invoke and the client has no OnInvoke.Connections are not auto-cleaned
Connections are not auto-cleaned
Do not carry over an assumption that destroying a script releases its listeners. Audit every
Connect in code that can re-run: respawn scripts, reopened UI, hot-reloaded modules.Circular tables are not supported
Circular tables are not supported
Flux’s encoder has no visited-set, so a self-referencing table overflows the stack rather than
being handled.
Schemas are a first-class option
Schemas are a first-class option
Flux.Server(name, schema) takes an optional positional layout that removes per-value type
tags and lets you declare exact widths. Worth adopting for high-frequency events. See
Schemas.Generics port directly
The generic form is the same idea:<Args...> for arguments, <Out...> for invoke returns.
Migration checklist
1
Install and bootstrap
Place Flux in
ReplicatedStorage and ensure one server script calls Flux.Server(...) during
startup. Without it, clients hang on WaitForChild.2
Port one system at a time
Flux coexists with raw remotes, because it only owns its own two instances. Migrate a single
feature, verify it, then move on.
3
Namespace your event names
Names are global keys and travel in every packet. Use
"Combat.Hit" over "Hit", and keep hot
names short.4
Audit every Connect for cleanup
This is the most common migration bug. Any
Connect in a script that can re-run needs an
explicit Disconnect.5
Re-check your validation
Generics and schemas are not runtime validation. Every server listener still needs type checks,
range clamps and ownership verification.
6
Add schemas to hot paths last
Get correctness first. Then schematise the handful of events that fire every frame, where
T.Float32() over an implicit f64 and T.Enum() over enum strings are the real savings.Next steps
Known limits
Read this before shipping.
Schemas
Optimising the events that matter.
