CockroachDB Geographic Distribution
Survival goals, table localities and data residency — placing data so latency and failure tolerance match the requirement.
CockroachDB expresses multi-region behaviour declaratively: you state which regions exist, what the database must survive, and where each table's rows belong.
Declaring regions
ALTER DATABASE shop SET PRIMARY REGION "eu-central-1";
ALTER DATABASE shop ADD REGION "eu-west-1";
ALTER DATABASE shop ADD REGION "us-east-1";Nodes are assigned to regions by locality flags at startup:
cockroach start --locality=region=eu-central-1,zone=eu-central-1a …Survival goals
ALTER DATABASE shop SURVIVE ZONE FAILURE; -- default
ALTER DATABASE shop SURVIVE REGION FAILURE;Table localities
-- Regional by table: all rows homed in one region. Good for region-specific data.
ALTER TABLE orders SET LOCALITY REGIONAL BY TABLE IN "eu-central-1";
-- Regional by row: each row homed by a column value. Good for per-user or per-tenant residency.
ALTER TABLE users ADD COLUMN region crdb_internal_region
AS (CASE WHEN country IN ('DE','FR') THEN 'eu-central-1' ELSE 'us-east-1' END) STORED;
ALTER TABLE users SET LOCALITY REGIONAL BY ROW AS region;
-- Global: read-mostly reference data, fast reads everywhere, slower writes.
ALTER TABLE currencies SET LOCALITY GLOBAL;GLOBAL tables use non-blocking transactions so reads never wait for consensus; the cost is moved
onto writes. It is right for currency codes and feature flags, and wrong for anything written often.
Data residency
REGIONAL BY ROW is the mechanism for legal residency requirements: a row's region column
determines which region physically stores it. Combined with zone configurations, it can pin data to
specific regions and keep it there.
Verify rather than assume:
SELECT crdb_region, count(*) FROM users GROUP BY crdb_region;
SHOW RANGES FROM TABLE users;Latency expectations
Combine locality with follower reads so read traffic is served locally even when the leaseholder is elsewhere.