The owned keyspace · dive 03 · the reserve
The reserve
Some state belongs to the wire, not a queue. It needs a home no queue can occupy.
Not everything the protocol stores belongs to a queue — the version fence is one record for the
whole wire. It needs a home no queue can name. That home is the reserve:
{emq}:, built by EchoMQ.Keyspace.reserve/1, holding
version_key/0 → {emq}:version. The reserve is
first-byte-disjoint from every per-queue emq: key — so a queue named
emq still cannot collide with it.
Two spaces · pick one to read its first byte
First-byte-disjoint, by construction
The reserve exists because some state is the wire's own, shared by every queue and every speaker — and it needs a home that no queue can occupy. The mechanism is simple and total: the reserve and the per-queue space differ in their first byte.
A per-queue key starts with the literal emq: — emq:{orders}:pending
begins with the byte e. A reserve key starts with {emq}: — it
begins with the byte {. The two spaces can never share a prefix, so a key in one is never
mistaken for a key in the other. The reserve is also its own hashtag: {emq} routes every
cross-queue key to one slot, the same way a queue's {q} does, so the fence is single-slot
too.
- emq:{q}:<type>
- per-queue space — first byte
e; the hashtag is the queue. - {emq}:<suffix>
- the reserve — first byte
{; the hashtag isemq.
reserve/1 & version_key/0 — one base, one key in use
The reserve is a module constant; reserve/1 appends a suffix to it, and
version_key/0 is the one reserved key the core uses today — the version fence.
# echo_mq — EchoMQ.Keyspace # The reserve is the braced base {emq}: — the cross-queue space, structurally # disjoint from a queue's emq: prefix (different first byte). reserve/1 builds # any cross-queue key; version_key/0 is the one in use — the version fence. @reserve "{emq}:" @version_key @reserve <> "version" def reserve(suffix) when is_binary(suffix), do: @reserve <> suffix def version_key, do: @version_key
So version_key() is {emq}:version, and
reserve("anything") is {emq}:anything. Every cross-queue key the
core will ever need is built from the one reserved base, so there is exactly one place the wire's own state lives
— and it is a place no queue can name.
The reserve in use — the version fence
The fence is the reserve's reason to exist. The connector reads {emq}:version before it
runs a single command: if the record is absent it claims it (set-if-not-exists, then read it back); if it is
present it must match the wire version the connector was built for; a mismatch is fatal. A speaker that does not
agree on the wire is refused at boot — the fence is what keeps a stale or foreign client from writing into a
keyspace it does not understand.
The point here is only where the fence lives: in the reserve, not in any queue. Because
{emq}:version is first-byte-disjoint from every queue's keys, no queue's traffic can
ever touch it, and no queue can be created that would shadow it. The mechanism of the check — how the version is
compared, and the constant it is compared against — is the next module,
Immutability & branded ids.
Can a queue collide with the reserve?
The obvious worry: what if a caller names a queue emq? Type any queue name below. The
page builds its pending key the way queue_key/2 does and prints
the reserve key beside it, then compares their first bytes. A per-queue key always starts e;
the reserve always starts { — so even the queue named emq, whose
key is emq:{emq}:pending, cannot collide with {emq}:version.
queue_key vs the reserve · do they collide?
The reserve is disjoint by its first byte, not by a rule a caller could break. A queue named
emq is harmless: its keys still start e, and the reserve still
starts {.
Pattern → implementation
Reserve a disjoint key prefix for system-owned state, so application keys and infrastructure keys can never collide — a namespace partition by construction rather than by convention. Redis Patterns Applied R2.05 works the keyspace discipline this rests on.
EchoMQ.Keyspace.reserve/1 builds the {emq}: base,
first-byte-disjoint from any queue's emq:, so the version fence at
{emq}:version has a home no queue can occupy — and its own single-slot hashtag.
A reserved prefix is only safe if it cannot be reached from the application space.
{emq}: earns that by a structural property — a different first byte — not by asking callers
to avoid a name.
Recap — beside every queue, owned by none
The reserve is {emq}: — the cross-queue space, built by reserve/1,
holding version_key/0 → {emq}:version. It is first-byte-disjoint
from every per-queue emq: key, so a queue named emq cannot collide
with it, and it is its own single-slot hashtag. The reserve is where the wire's own state lives. With the grammar,
the slot, and the reserve in hand, the where of the protocol is complete; the next module reads the
what — the record hash.
Next in The Protocol: The record hash — the job HASH at the job key and the field names that are part of the wire.
References
Where the reserve's store and the fence's claim are documented.
Sources
- Valkey — Documentation — the store the reserve and the fence live in; the substrate of record.
- Valkey — SET (with NX) — the set-if-not-exists the fence uses to claim the version record once.
- Redis — Keyspace & cluster hash tags — the hashtag rule that makes
{emq}its own slot.
Related in this course
- The owned keyspace — the module hub.
- The braced grammar — the per-queue grammar the reserve sits beside.
- The hashtag & the slot — the slot the reserve is its own hashtag for.
- Immutability & branded ids — the version fence the reserve holds, in depth.
- redis-patterns R2.05 · Hash-tag co-location — the near side of the door.