Rasa architecture in one page
Rasa is easiest to understand if you separate the two jobs: deciding where a value lives, and moving the value bytes. The first job is normal metadata. The second job is one-sided RDMA.
The pieces
The client SDK is the user's entry point. It exposes normal cache
verbs: get, put, and delete. Under
the hood it resolves descriptors, manages libfabric addresses, posts RDMA
operations, polls completions, and validates the value header and CRC.
Valkey is the metadata store. It holds key-to-descriptor records, node records, leases, arena inventory, command streams, metrics, and the small amount of state needed to allocate and reclaim memory. It is on the control path, not the read data path.
The data node owns the bytes. It allocates fixed-size arenas,
registers them with libfabric, and publishes descriptors that name
specific slots inside those arenas. A descriptor is the bridge between
normal metadata and remote memory: {node, region, addr, rkey, len,
version, checksum}.
The read path
A read starts with metadata. The client asks Valkey where the key lives,
verifies the descriptor if signing is enabled, inserts the data node's
fabric address into its address vector, and issues fi_read.
After that, the data node's CPU is not serving the request. The NIC reads
from registered memory and the bytes land in the client's registered
buffer.
Rasa is therefore not Redis with a faster network stack. Redis answers every GET. Rasa makes the answer discoverable ahead of the transfer, then lets the NIC move the value.
The write path
A write is coordinated before it is visible. The client asks the control plane for space. The manager chooses a node and slot, returns a write grant, and the client RDMA-writes one framed value into that slot. The client then commits to the data node. Only after commit does the node publish the signed descriptor that readers can resolve.
This ordering is the safety line. Readers should see the old value, a miss, or the complete new value. They should not discover memory while a writer is still filling it.
Maintaining integrity
Rasa's hard problems are mostly lifecycle problems. A descriptor is a capability to read memory, so the system cannot casually reuse that memory while clients may still hold the old descriptor. Leases bound how long readers can keep a view. Arena rotation creates a new rkey, so stale descriptors fail in hardware instead of reading reused bytes.
Delete follows the same idea: unpublish first, reclaim later. Compaction, eviction, and failure handling are all variations on one rule: never make a remote pointer lie.
The split we kept coming back to
One line settled most of the arguments about where a given piece of logic belongs: policy in the control plane, mechanism in the data nodes.
A data node knows how to rotate an arena, seal one, or report its inventory. It does not decide when any of that should happen, and has no way to. Compaction is the clearest case: a node can see that an arena is mostly dead and propose compacting it, but the rotate that follows is only safe once manifests have been repointed and leases drained, and both are control-plane state a node has no view of. So the node proposes and executes, and the control plane decides. When we were unsure where something belonged, that sentence usually answered it.
What is intentionally not hot
Valkey is not moving value bytes. The manager is not in the read loop. The console is not a data-plane component. The data node is not parsing a request for every read. Those absences are the architecture. Rasa spends normal software where decisions are made, then keeps the byte movement small, direct, and boring.
Mental model: Rasa is a remote-memory data plane for large immutable or versioned values. Valkey says which memory is safe to touch. EFA/libfabric moves the bytes. The rest of the system exists to keep those two statements true.
