Flo uses a custom binary protocol for client-server communication on port 9000 . The protocol supports TLV (Type-Length-Value) encoding for efficiency and zero-copy parsing.
Clients connect via TCP to the server’s client port (default 9000). The first bytes sent identify the protocol:
Magic Bytes Protocol FLO\x01Binary wire protocol *, $, +, -RESP (Redis protocol) GET, POST, …HTTP (redirected to dashboard) WebSocket upgrade WebSocket (binary protocol over WS frames)
The Acceptor thread peeks at the first bytes to detect the protocol and routes accordingly.
Every request has a fixed 32-byte header followed by a variable-length payload:
┌──────────────────────────────────────────────────────────────────┐
│ Request Header (32 bytes) │
├──────────┬──────────┬───────┬──────────┬──────────┬──────────────┤
│ magic │ opcode │ flags │ req_id │ payload │ namespace │
│ (4B) │ (2B) │ (2B) │ (8B) │ _len(4B) │ _hash (8B) │
├──────────┴──────────┴───────┴──────────┴──────────┴──────────────┤
├────────────┴─────────────────────────────────────────────────────┤
│ [key bytes] [value bytes] [optional TLV fields] │
└──────────────────────────────────────────────────────────────────┘
Field Type Description magicu32Protocol magic: 0x464C4F01 (“FLO\x01”) opcodeu16Operation code (see OpCode table) flagsu16Request flags (compression, etc.) req_idu64Client-assigned request ID for response matching payload_lenu32Length of payload following the header namespace_hashu64FNV-1a hash of the namespace string key_lengthu16Length of the key in the payload
┌──────────────────────────────────────────────────────────────────┐
│ Response Header (24 bytes) │
├──────────┬──────────┬───────┬──────────┬──────────────────────────┤
│ magic │ status │ flags │ req_id │ payload_len │
│ (4B) │ (2B) │ (2B) │ (8B) │ (4B) │
├──────────┴──────────┴───────┴──────────┴──────────────────────────┤
└──────────────────────────────────────────────────────────────────┘
Code Name Description 0x00OKOperation succeeded 0x01NOT_FOUNDKey / queue / stream not found 0x02BAD_REQUESTInvalid request parameters 0x03CONFLICTCAS version mismatch 0x04UNAUTHORIZEDAuthentication required 0x05OVERLOADEDServer at capacity (retry) 0x06INTERNAL_ERRORServer error 0x07NOT_LEADERNode is not the leader for this partition
The protocol defines 167 operation codes organized by subsystem:
OpCode Value Description kv_get0x10Get value by key kv_put0x11Set key-value pair kv_delete0x12Delete a key kv_scan0x13Prefix scan kv_batch_put0x14Batch put multiple keys kv_history0x15Get version history kv_cas0x16Compare-and-swap
OpCode Value Description queue_enqueue0x20Add message to queue queue_dequeue0x21Fetch and lease messages queue_ack0x22Acknowledge messages queue_nack0x23Negative acknowledge queue_peek0x24Peek without leasing queue_touch0x25Extend lease queue_dlq_list0x26List DLQ messages queue_dlq_requeue0x27Requeue from DLQ
OpCode Value Description stream_append0x30Append record stream_read0x31Read records stream_create0x32Create stream stream_info0x33Stream metadata stream_trim0x34Trim old records stream_group_create0x35Create consumer group stream_group_read0x36Consumer group read stream_group_ack0x37Consumer group ack
OpCode Value Description ts_write0x40Write data point ts_write_batch0x41Batch write points ts_query0x42Execute FloQL query ts_create_measurement0x43Create measurement
OpCode Value Description action_register0x50Register action type action_invoke0x51Invoke action action_status0x52Get execution status action_result0x53Get execution result
OpCode Value Description worker_register0x60Register worker worker_await0x61Await task assignment worker_complete0x62Complete task worker_fail0x63Fail task worker_heartbeat0x64Worker heartbeat worker_touch0x65Extend task lease
OpCode Value Description cluster_join0xC0Join cluster cluster_leave0xC1Leave cluster cluster_status0xC2Cluster health cluster_partition_table0xC3Get partition table
Some operations include optional TLV (Type-Length-Value) fields after the key and value:
┌──────┬────────┬───────────┐
│ type │ length │ value │
└──────┴────────┴───────────┘
Type Name Used By 0x01TTL KV put 0x02CAS version KV put/delete 0x03Priority Queue enqueue 0x04Delay Queue enqueue 0x05Dedup key Queue enqueue 0x06Block timeout Get, dequeue, stream read 0x07Consumer group Stream group operations 0x08Idempotency key Action invoke
Flo also accepts Redis RESP protocol on the same port. The Acceptor detects RESP by the leading character (*, $, +, -, :). RESP commands are translated to Flo operations:
RESP Command Flo Operation SET key valuekv_putGET keykv_getDEL keykv_deleteSCAN cursor MATCH patternkv_scanLPUSH queue valuequeue_enqueueRPOP queuequeue_dequeueXADD stream * field valuestream_appendXREAD COUNT n STREAMS stream idstream_read
This allows Redis clients to connect to Flo without modification for basic operations.