Skip to main content
Flux automatically serializes the following types.

Supported

Hover any icon for what it means in that column.
Six supported datatypes have no schema constructor: buffer, BrickColor, Region3, UDim, UDim2 and TweenInfo. Under a schema, use T.Any() or write a custom type.

Not supported

Sending any of these logs warn("Unsupported type: ...") on the sender, and the receiver gets nil.
This failure is silent on the receiving side. The argument count still matches, so your callback runs with a nil in that position and the only clue is one warning in the sender’s output. Check this table before sending an unusual datatype.

Tables

Written as TYPE_ARRAY plus a varint count. Round-trips exactly.
Written as TYPE_TABLE with alternating keys and values. Keys are themselves dynamically encoded, so any serializable type works as a key.
Fail the array test and take the dictionary path, which preserves both parts.
A table with gaps also takes the dictionary path, so it arrives as a dictionary with numeric keys rather than an array. #result is unreliable and ipairs stops at the first gap.
Recursion has no visited-set and no depth limit.
Break cycles before sending, or send an id and let the receiver rebuild.
Metatables are never transmitted, so a received table is always a plain table. Function-valued fields become nil with a warning, which means an OOP instance arrives as its data fields only, without its methods.

Numbers

The dynamic encoder narrows integers automatically.
There is no automatic f32 narrowing and no i8 selection. Every non-integer costs 8 bytes, and small negatives cost 2 where the same magnitude positive costs 1. Declare T.Float32() or T.Int8() in a schema to get those widths.
nan and inf are non-integers and go through f64, which transmits them faithfully. They will then propagate into the receiver’s arithmetic, so validate before sending.

Instances

varint index, 1 to 3 bytes
Instances ride in a side array passed alongside the buffer, and only an index is serialized. Cheap regardless of tree depth, and deduplicated within a batch.
nil
If the receiver cannot see the instance, whether server-only, not replicated, or destroyed before the flush, the index resolves to nil. No error is raised.

Multiple return values

OnInvoke may return any number of values, and all of them survive.
Invoke traffic always uses the dynamic encoder regardless of any schema, which is precisely why a variable return count works without you declaring anything. See Invocations.

Next steps

Known limits

Every rough edge in one place.

Serialization

Why the encoder makes these choices.