Skip to main content

Operating a cluster

Every change to a running cluster is an operation of the router's, made with snoutdata cluster, from the dashboard's Cluster tab, or through the router's admin API. They are the same operations everywhere; only how you reach the cluster differs:

# SnoutData Cloud: your project, as you
snoutdata cluster status --project <ref>

# Your own router: its admin API and token
export LEPIS_ADMIN_URL=https://router.internal:7432
export LEPIS_ADMIN_TOKEN=...
snoutdata cluster status

The examples below leave out --project and the admin flags.

A plan first, always​

Every operation takes --plan, which changes nothing and says what would happen: the steps, the rows and bytes that move, the estimated copy time, and the write pause to expect.

snoutdata cluster range split tenant:-9223372036854775808 --to node3 --plan

Without --plan it shows the plan again and asks. Anything that moves or deletes data needs your answer, or --yes where there is no terminal to ask at. The dashboard does the same: every action opens its plan, and runs only when you press Run.

Jobs​

An operation runs as a job recorded in the cluster's catalog, so it survives a router restart and can be followed from anywhere:

snoutdata cluster jobs # unfinished and recent jobs
snoutdata cluster jobs watch <id> # follow one to the end
snoutdata cluster jobs resume <id> # take a stopped one up again
snoutdata cluster jobs cancel <id>

Cancelled before its cutover, a job rolls back. After the cutover it finishes its cleanup instead, since the data has already moved.

How data moves​

A move copies the slice of rows that changes owner to the new node while writes go on, keeps it up to date, then cuts over at a transaction boundary: writes to just the keys that move pause, the catalog changes, every router acknowledges it, and writes go on at the new owner. Both sides are checked to agree before the old copy is deleted. Reads and writes to every other key never stop.

The cutover's limits are cluster settings, and each operation can override them:

SettingDefault
--max-write-pause-ms2000the longest a cutover may pause writes; one that would take longer is postponed rather than run
--drain-timeout-ms5000how long a cutover waits for open transactions on the moving keys to finish
--ack-timeout-ms2000how long it waits for every router to acknowledge the new catalog
--copy-mb-per-s50the copy rate a plan estimates with; chosen, not measured
snoutdata cluster settings # read them
snoutdata cluster settings --set max_write_pause_ms=1000

Nodes​

snoutdata cluster nodes # each node, its state and its ranges
snoutdata cluster nodes add # Cloud: a new node pod that joins by itself
snoutdata cluster nodes add node4 --host 10.0.0.14 # your own: a Postgres you run
snoutdata cluster nodes drain node4 # move every range off it
snoutdata cluster nodes remove node4 # detach it once drained
snoutdata cluster scale --nodes 4 # Cloud: this many nodes, the home included

Adding a node checks its Postgres version and settings and copies the roles and reference tables to it before it takes any range. A node is removed only once it holds nothing.

Keyspaces and tables​

snoutdata cluster keyspace create tenant --key-type bigint --ranges 8
snoutdata cluster table distribute public.orders --column tenant_id --keyspace tenant
snoutdata cluster table reference public.countries
snoutdata cluster table global public.countries # back to the home node only
snoutdata cluster keyspace drop tenant # once no table uses it

Distributing a table that already has rows creates it on the other nodes and moves its rows out to their owners. In SnoutData Cloud, snoutdata cluster spread does the keyspace, the distribution and the rebalance in one go (see clusters in Cloud).

Ranges​

A range is named keyspace:lo, as cluster status prints it.

snoutdata cluster range split tenant:-9223372036854775808 --to node3 # half of it to node3
snoutdata cluster range split tenant:0 --at 4611686018427387904 # at a chosen bound
snoutdata cluster range move tenant:0 --to node2
snoutdata cluster range merge tenant:0 tenant:4611686018427387904 # two neighbours into one
snoutdata cluster rebalance # even the nodes out

Pin a tenant​

One key value much bigger than the rest can have a range of its own and, if you name one, a node of its own:

snoutdata cluster tenant pin tenant 42 --node node5

Verify and clean up​

snoutdata cluster verify # every node holds only the rows its ranges say
snoutdata cluster cleanup # delete rows a node no longer owns, in batches, then vacuum

A move verifies before it deletes anything; verify checks the whole cluster on demand, with a row count and an order-independent checksum per range.

Recommendations​

snoutdata cluster advise

The advisor reads each node's size and load and recommends what to do (split a range that grew, move one off a busy node, add a node), each as an operation you can plan and run. It advises; it never runs anything by itself. The dashboard shows the same recommendations.

Back to one database​

A cluster whose home is its only node can be taken apart: snoutdata cluster dissolve on your own router, or turning clustering off in Cloud. Every fence is dropped and the catalog forgets every keyspace and table; the rows are untouched. Refused while another node holds data or a transaction across nodes is unfinished.