nengi Binary Types

Updated for v1.7

Binary range cheat sheet

General note about optimization: for most actiony games 90-99% of network data is used transmitting id, x, y, rotation (if applicable) or their 3D equivalents. Therefore the binary type of properties such as x and y is 10-100x more important than everything else (and the best type for those is usually Float32). In fact, for many games it is probably not worth optimizing anything other than that. While prototyping I recommend using Float32s, UInt32, String, Bool, and the occassional UInt8 or UInt16 if sending sizable arrays of integers -- one may never need to go any further.


An integer is a whole number with no fraction such as 1, 2, 3, 10239, and -50. The number 1.5 is not an integer. If a number is not an integer but it is given a network type of integer via nengi, then nengi will convert it to an integer the same as `Math.floor` would have.

Unsigned Integer Types

Unsigned integers are always positive (unsigned means the number cannot include a +/- sign).

Type (bits) Min Max
UInt2 0 3
UInt3 0 7
UInt4 0 15
UInt5 (deprecated) 0 31
UInt6 0 63
UInt7 (deprecated) 0 127
UInt8 0 255
UInt9 (deprecated) 0 511
UInt10 0 1023
UInt11 (deprecated) 0 2047
UInt12 0 4095
UInt16 0 65535
UInt32 0 4,294,967,295

Signed Integer Types

Signed integers can be negative. These have the same number of distinct states as their unsigned counterparts but have 0 in the middle instead at the start. There are far fewer signed types implemented in nengi. Also remember that floats can be negative numbers.

Type (bits) Min Max
Int4 -8 8
Int6 -32 31
Int8 -128 127
Int10 -512 511
Int16 -32768 32767
Int32 -2,147,483,648 2,147,483,647

Other types

Type (bits) Description
Float64 aka JavaScript number, 64 bit floating point ~15-17 digits accurate
Float32 half precision float, recommended
Boolean true/false, legitimately compresses to 1 bit over the network
UTF8String utf8 string type, variable length
ASCIIString string made of 1-byte characters in a limited ascii set
String alias to UTF8String
JSON json is not an actual type, but you can put json into a string!
RotationFloat32 2PI radians that wraps from 2PI to 0 smoothly when interpolated

More details...

Float32 & Float64

Floating-point numbers can have the decimal position "float" (aka be anywhere in the number). The regular `Number` in JavaScript is a Float64. Using a Float32 is often sufficient for networking purposes, and the loss is just a matter of how many digits are accurate. Float32 has ~7 digits of precision, Float64 has ~15-17 digits of precision.


The values true and false. Sent over the network as 0 or 1 in a single bit.

UTF8String, String, ASCIIString

UTF8Strings allow many languages and emojis. There is not a consistent relationship between the number of characters and the length of the strings in bytes because it varies by language. Please note that JavaScript native string operations (such as substring) are not natively compatible with UTF8 and are capabale of producing corrupt UTF8 which nengi cannot handle. Always sanitize/trim/crop UTF8 strings with a UTF8-aware library before passing them off as nengi.UTF8String data.

String is an alias to UTF8String

ASCIIString uses one byte per character and supports a limited set of symbols.


This special type can be used to serialize a rotation in radians and send it over the network. Nengi will automatically handle wrapping from 0 to 2 PI in a way that is compatiable with the nengi interpolator. If you've got an object that suddenly does a glitchy-looking flip while being rotated, then try using RotationFloat32 to save the day.

Rotation8 (unsupported/broken)

This type does not currently work. The intent was to handle 2PI rotation but compress it down to 1 byte.

RGB888 (deprecated)

This type does not currently work. To send an RGB color as 3 bytes (instead of binary hex or a hex string)just add 3 UInt8s to a nengi protocol and put the color values in there.


To send JSON via nengi, simply use String or ASCIIString and use JSON.stringify/JSON.parse in your game's code. JSON is viable when used judiciously and outside of the hot path. The hot path is almost aways per-frame entity mutations. So for example, do not make a JSON string property on an entity that changes each frame, that would be trouble! However sending periodic messages to players via JSON is often fine, and particularly conveneient while developing (and if they're simple you can always optimize them later). Even I, the developer of all this binary stuff, will use JSON when stubbing out functionality such as an in-game leaderboard.

It is also worth noting that most numbers and particularly booleans will be *much* smaller in binary than json, but that strings will be almost the same size in either (consider that when looking for optimizable json->binary opportunities).