Reference
Redis compatibility
Nexir speaks RESP2 and exposes a deliberately small, scalar-only Redis-compatible command surface. It is not a Redis replacement.
Connect
redis-cli --raw -h 127.0.0.1 -p 6379
PING
# PONG
HELLO
# includes server nexir, proto 2, mode clusterConfigure client libraries for RESP2. HELLO does not negotiate RESP3, authentication, or RESP3 reply shapes.
Supported commands
This table is the complete surface. Every command not listed here returns ERR unknown command '<name>'. Command names are case-insensitive; keys and values are binary-safe.
| Command | Result | Semantics |
|---|---|---|
GET key | bulk value or nil | Reads one live scalar value. |
SET key value | OK | Unconditionally replaces the value and clears its deadline. |
SET key value EX seconds | OK | Replaces the value with a relative seconds deadline. |
SET key value PX milliseconds | OK | Replaces the value with a relative millisecond deadline. |
SET key value EXAT unix-seconds | OK | Replaces the value with an absolute seconds deadline. |
SET key value PXAT unix-milliseconds | OK | Replaces the value with an absolute millisecond deadline. |
DEL key | 0 or 1 | Deletes exactly one key. Variadic DEL is not supported. |
EXPIRE key seconds | 0 or 1 | Sets a relative seconds deadline. |
PEXPIRE key milliseconds | 0 or 1 | Sets a relative millisecond deadline. |
EXPIREAT key unix-seconds | 0 or 1 | Sets an absolute seconds deadline. |
PEXPIREAT key unix-milliseconds | 0 or 1 | Sets an absolute millisecond deadline. |
PERSIST key | 0 or 1 | Clears an existing deadline. |
TTL key | integer seconds | -2 when absent, -1 when persistent. |
PTTL key | integer milliseconds | -2 when absent, -1 when persistent. |
| Operational command | Purpose |
|---|---|
HELLO [2 [SETNAME name]] | RESP2 negotiation and server identity. |
PING [message] | Connection liveness. |
ECHO message | Connection diagnostics. |
QUIT | Clean connection shutdown. |
SELECT 0 | Accepts clients that explicitly select database zero. Any other index errors. |
COMMAND [subcommand] | Metadata generated from the authoritative command registry. |
CONFIG GET parameter | Read-only client-initialization compatibility for persistence probes. |
CLIENT READMODE LOCAL|LINEARIZABLE | Chooses local or linearizable reads for the connection. |
INIT id grpc redis | Initializes a fresh local Raft cluster when RESP administration is enabled. |
CLUSTER ... | Membership, leadership, health, and readiness administration. |
INIT and mutating CLUSTER subcommands are gated by server.enable_admin_commands, which is disabled by default. Enable it explicitly during bootstrap or membership changes, require client mTLS on the RESP listener on any network that is not strictly isolated, and disable it again when the operation is complete. Nexir has no AUTH command; the certificate is the only client authentication. See the CLI and network reference for the full CLUSTER subcommand list.
COMMAND metadata
| Form | Result |
|---|---|
COMMAND | Full detail array for every registered command. |
COMMAND COUNT | Number of registered commands. |
COMMAND INFO [name ...] | Detail entry per name; unknown names are null arrays. |
COMMAND DOCS [name ...] | Empty map; structured documentation is not exposed yet. |
COMMAND LIST | Names of all registered commands. |
Subcommands are case-insensitive. COMMAND GETKEYS, COMMAND HELP, and structured COMMAND DOCS output are not supported.
HELLO protocol negotiation
Nexir speaks RESP2 only. Bare HELLO and HELLO 2 return the RESP2 server-identity map. HELLO 2 SETNAME name is accepted for client compatibility, but the name is not retained.
HELLO 3, and every other unsupported numeric protocol version, returns:
-NOPROTO unsupported protocol versionThis deliberately differs from Redis, which negotiates RESP3. Explicit rejection prevents a client from switching to RESP3 while Nexir continues emitting RESP2 frames. A non-integer or out-of-range version returns -ERR Protocol version is not an integer or out of range. AUTH inside HELLO returns -ERR AUTH is not supported, because Nexir will not report an authentication it did not perform. Unknown or incomplete modifiers return -ERR Syntax error in HELLO. These command errors leave the connection open.
CONFIG GET
CONFIG GET save returns an empty value and CONFIG GET appendonly returns no, which is enough for client libraries that probe persistence during initialization. CONFIG GET * returns both. Any other parameter returns an empty array. CONFIG SET is not supported; change TOML or environment variables and restart the node.
TTL behavior
TTLandPTTLreturn-2for missing or expired keys,-1for a key with no deadline.- Relative deadlines are converted to absolute Unix milliseconds by the leader before proposal. Replicas apply the captured deadline and never re-derive it from their own wall clocks.
- A deadline at or before the captured command time deletes an existing key.
- Expired records are logically absent at the exact deadline, before background physical cleanup completes.
- Expiration cleanup carries the expected deadline, so a later overwrite cannot be deleted by an earlier cleanup request.
SETwithout a deadline option clears an existing deadline.- Only the four documented
SETdeadline options are valid. Invalid arity, syntax, integers, bounds, and request limits fail before Raft proposal and cannot partially change state.
Consistency and routing
Writes always require Raft quorum. A follower redirects writes with MOVED when it knows the leader.
CLIENT READMODE LINEARIZABLE
# OK — default; requires a Raft read barrier
CLIENT READMODE LOCAL
# OK — served by the contacted node; followers may be staleLinearizable reads may redirect from followers or fail during quorum loss. Local reads never redirect but can observe older state. READMODE is the only CLIENT subcommand; there is no write-mode selector, because every write is a quorum write.
Pipelining and command ordering
Nexir returns exactly one reply per request, in request order. Replies are never reordered, merged, or omitted. Execution order within a single connection's pipeline is guaranteed only in these directions:
| Pipelined pair, same connection | Guaranteed |
|---|---|
| write then write | Yes. Writes are proposed in submission order and Raft preserves it. |
| write then read | Yes. A read queued behind an uncommitted write on the same connection waits for it, so pipelined read-your-writes holds. |
| read then write | No. The read may observe the later write's effect. |
| read then read | No. Two reads in one pipeline may be evaluated against snapshots taken in either order. |
Concretely: GET k pipelined immediately before SET k v may return v, and GET k pipelined before DEL k may return nil. This is not a linearizability violation — pipelined commands are issued before any of their replies is received, so they are concurrent operations and any serialization of them is valid. It is a deliberate deviation from Redis, which executes one connection's commands strictly in submission order. The window is wider under LINEARIZABLE than LOCAL, because a linearizable read waits for a Raft read barrier before taking its snapshot.
A client that needs submission order across a read-then-write boundary must read the reply to the read before issuing the write. Sequential request/response clients are unaffected, and no ordering was ever guaranteed between commands on different connections.
RESP multibulk compatibility
Empty (*0) and null or negative (*-1, *-2, and so on) multibulk frames are consumed without producing a reply. The connection stays open and continues with the next frame, matching Redis.
Limits
- Command name: 512 bytes. Keys: 1 MiB.
- Values and aggregate request size: 60 MiB.
- Request multibulk: 128 arguments while the surface is scalar-only. Wider frames are rejected from the array header before payload parsing. The 25,000-element RESP array ceiling remains the outer bound; this tighter limit will be revisited with the multi-key and sharding design.
- Replies are bounded by
storage.max_read_reply_bytesand the client and global response budgets.
Unsupported features
Hashes, sets, lists, sorted sets, counters (INCR and friends), multi-key commands (MSET, MGET), EXISTS, TYPE, STRLEN, APPEND, DBSIZE, KEYS, cursor SCAN, FLUSHDB/FLUSHALL, Lua and functions, MULTI/EXEC/WATCH, streams, pub/sub, blocking operations, modules, geospatial commands, HyperLogLog, persistence commands, AUTH, and every other Redis command outside the tables above are unsupported and return ERR unknown command.
Because there is exactly one value type, Nexir never returns WRONGTYPE.
Common errors
ERR unknown command '<name>'for any command outside the surface.MOVEDwhen a request should reach the leader.CLUSTERDOWNwhen leadership or quorum is unavailable.NOPROTOfor an unsupportedHELLOprotocol version.ERR Server overloadedor queue/buffer errors when configured bounds are reached.- Explicit size errors for oversized command names, keys, values, requests, or replies.