Docs
  • 0.39.6latest
  • 0.39.5
  • 0.39.3
  • 0.39.2
  • 0.39.1
  • 0.39.0
  • 0.38.4
  • 0.38.2
  • 0.38.1
  • 0.37.1
  • 0.37.0
  • 0.36.2
  • 0.36.1
  • 0.36.0
  • 0.35.3
  • 0.35.2
  • 0.35.1
  • 0.35.0
  • 0.34.4
  • 0.34.3-beta
  • 0.34.2-beta
  • 0.34.1-beta
  • 0.34.0-beta
  • 0.33.4-beta
  • 0.33.3-beta
  • 0.33.2-beta
  • 0.33.1-beta
  • 0.33.0-beta
  • 0.32.0-beta

Replicas

Two statements that look alike and are written to different places on purpose: one describes this machine, the other describes the topology.

A node's configuration is in the language, not in a file beside it. There are two statements, they look similar, and the difference between them is the whole design:

statementdescribeswritten toin a backup
DEFINE NODEthis machine — what it is for, where it answersthe local META keyspaceno
DEFINE REPLICAthe topology — which peers exist and wherethe catalogyes
DEFINE NODE ROLES serving, writable ENDPOINTS 'here:9000';
DEFINE REPLICA second AT 'there:9001';

Why the split is not an implementation detail

Consider a node restored from another node's backup. If identity travelled in the log:

  • it would inherit writable and accept writes it is supposed to forward, and
  • every peer told to reach it would be given the original's address and reach the original.

Neither failure announces itself. The restored node would look healthy, answer requests, and take writes that the real writer never sees.

And the mirror case: if the topology did not travel, a restored node would come up knowing about no peers at all, and a cluster rebuilt from a backup would be a single node that believes it is the whole thing.

So a backup must carry the peers and must not carry the identity, and neither test is the criterion on its own — a design that got one right and the other wrong would pass half the checks somebody thought to write.

Configuring a node is done on it

There is no DEFINE NODE <other> …, and its absence is a decision. A statement that reached across would be a second mechanism for something the topology already decides, and the two would disagree the first time a node was unreachable while its row said otherwise.

Either clause stands alone, so a role change does not have to restate an address:

DEFINE NODE ROLES serving, writable;

A statement that sets nothing is refused rather than read as "clear both":

DEFINE NODE;

UnexpectedToken. And an unknown role is refused rather than stored:

DEFINE NODE ROLES leader;

Unknown.

Peers

A peer is named, and the name is what makes it one peer. second was declared above, so declaring it again at another address is not a second peer:

DEFINE REPLICA second AT 'elsewhere:9001';

NameTaken — that is a second address for one peer, not a second peer. A re-runnable start-up script says so out loud:

DEFINE REPLICA IF NOT EXISTS second AT 'there:9001';

A peer may be declared with the roles that say where writes go:

DEFINE REPLICA writer AT 'leader:9001' ROLES serving, writable;

A peer nobody has said takes writes does not take them. ROLES left off reads as no roles rather than as every role — the safe reading, and the one that makes a half-written declaration fail closed.

Reading it back

INFO FOR NODE;

Both halves, in one answer — what this machine is, and who its peers are. A node reports itself before anything has been configured, so this is also the first thing to run against a node you have just been handed.

Draining

Taking writable away is how a node is drained, and it stays readable throughout. That is covered in Serving, because it is an operation on a running node rather than a fact about the topology.

What is not here yet

This is the configuration surface: which nodes exist, what each is for, where each answers. Automatic failover, quorum and leader election are not statements in this language today, and no page here claims otherwise. What the store gives you now is that the topology is data — replicated, backed up, and readable with one statement — rather than a set of files that have to be kept in step by hand.