The wire and Redis compatibility
Structures speaks RESP2 and RESP3, the Redis protocol, over a raw TCP socket.
redis-cli connects to it. So do the standard Python, Node, Go and Java client
libraries, unchanged.
That is the adoption argument in one line: keep your clients, keep your command vocabulary, and gain everything a cache does not give you.
What a client gets
| Property | Detail |
|---|---|
| RESP2 and RESP3 | Both protocol generations |
| Per-connection registration | Client state is registered once per connection, not per command, so transactions, watches and protocol state persist across a session the way a Redis client expects |
| Cluster semantics | The Redis Cluster model: CRC16 over 16,384 slots, {hashtag} co-location for related keys, and MOVED and CROSSSLOT responses |
| KeyDB extensions | The command surface extends beyond baseline Redis |
| Scripting | Server-side scripting with SHA-based caching and function libraries |
| Pub/sub and keyspace notifications | Including an in-process dispatcher and a keyspace notifier |
The cluster semantics matter more than they look. A client library that already
understands MOVED will follow a redirect to the owning cell without special
handling, which is what makes multi-cell placement transparent to an application
that was written against Redis Cluster.
The wire is not an authorization bypass
This is the property that makes the compatibility safe to offer, and it is the first question a security reviewer should ask.
A standard Redis client connecting directly does not find an ungoverned back door:
- The connection is deny-by-default until it authenticates.
- The connection binds to a verified directory entity, not to a shared password.
- Every command re-enters the same engine-boundary authorizer the HTTP surface uses.
So a GET over RESP is subject to the same workspace scope, the same
classification and the same grants as the equivalent call over HTTP. The protocol
determines the syntax, not the authority.
Figure: the Redis wire, governed. Connecting is not authorization. The connection authenticates and binds to a directory entity, and then every command crosses the same authorizer an HTTP caller crosses.
Other ways in
The wire is the compatibility surface, not the only one.
| Surface | For |
|---|---|
| RESP2 / RESP3 | Existing Redis clients and tooling |
| An external HTTP face | Credential-authenticated callers that do not speak RESP |
| An in-process workspace client | Co-located callers inside the cell, including agents |
| An operator surface | Browsing and administering structures from the console |
| Agent tools | Query and execute verbs exposed to a reasoning agent, including on a disconnected device |
All of them land on the same engine behind the same authorizer.
What you gain over a cache
The same set or sorted set that would sit in an ungoverned cache becomes, here:
- Workspace-scoped, so it belongs to a boundary rather than to a shared namespace.
- Classified, on the same ladder as a table.
- Authorized per command, against real grants.
- Audited, into the same record as everything else.
- Replicated across cells, with conflict-free convergence.
- Metered, so its consumption is attributable.
A cache gives you none of those, which is why a cache is where governance quietly ends in most estates.
Related
- Structures, the type surface and the engine.
- Concurrency and expiry, what happens when two callers touch the same key.
- Distribution and protection, how slots and replicas work across cells.
- Engines and access methods, the wider protocol surface.