Where the Ocean Comes Back
priya:r9, must be unique across the whole table, and as far as the database knows a row with that key could be homed in any region, like her US-trip rows in Iowa (Part II’s panel 02). So by default the insert asks Iowa and Europe whether priya:r9 is taken, and Mumbai’s write waits on both.BY DEFAULT, THE GATEWAY’S REGION
crdb_region column (Part II’s panel 01), so put that column into the unique keys, primary keys included. What must be unique is then mumbai/priya:r9, which only a row homed in Mumbai could share, so Priya’s insert is checked in Mumbai alone and never waits on Iowa or Europe. The docs say this removes the added latency from uniqueness checks.gen_random_uuid() skips the check by default, so there is no check for the insert to wait on. Don’t reach for the skip_unique_checks switch instead; used where uniqueness isn’t actually guaranteed, it can leave logically duplicate keys.SUPPORTING — SHOULD EACH USER HAVE ONE HOME REGION?▾
A row’s home can come from the gateway default or from a home region you keep for each user, and the choice decides whether a retry can duplicate a key (panel 02).
| GATEWAY DEFAULT | HOME BY USER | |
|---|---|---|
| Server must know each user’s home region | No | Yes, a new field per user |
| A travelling user’s history | Split across regions | All in one region |
| Region-level unique keys (panels 01 and 02) | The same key can exist once per region, so a retry that lands in another region can duplicate it | Safe |
Two questions, not one. Which region serves a request (the load balancer, in Part II’s “How does Priya’s request reach Mumbai’s nodes?”) and which region is a row’s home are separate questions; the gateway default just answers the second with the first.
Auto-rehoming exists but is in preview: when it’s on, a row’s home moves to the gateway region of any UPDATE or UPSERT that writes it. It only applies to newly created regional-by-row tables unless you add it to an existing one by hand.
SUPPORTING — WHAT ABOUT READS?▾
A read stays local when it reads rows homed in your own region and the query can tell that’s where they are. Reading the latest of rows homed elsewhere, or of rows that could be anywhere, crosses the ocean unless you ask for a stale (follower) read.
LIMIT that any matching rows can fill, can search the local region first and go remote only if it comes up short. Her newest is a LIMIT 1 that only the newest row can fill, and a newer reading could sit in another region, so a latest read has to hear from every region that might hold one, Europe included, even when the newest is right there in Iowa. A stale read answers from Iowa’s local copies of rows homed in all three regions.SUPPORTING — WHAT IF DATA MUST STAY IN ONE COUNTRY?▾
Read-only copies mean every region holds a copy of every row (Part II’s panel 03). If a rule says some data must stay in one country, CockroachDB has super regions (a preview feature): a named group of regions, where rows homed in a member region keep all their copies, voting and read-only, only inside the group.
You turn super regions on first (enable_super_regions), add one only once those regions are already in the database, and each region can belong to only one super region. To still survive losing a region, the super region itself needs 3 or more regions.
The other tool is ALTER DATABASE … PLACEMENT RESTRICTED, which keeps a table’s copies in its home region only (it needs the zone survival goal, the default, in Part II’s “How can the vote stay in one region and still survive failures?”), at the cost of fast stale reads from other regions.
One caveat on super regions: they ride on the replication system, whose “top priority is to prevent the loss of data and it may override the zone configurations if necessary”. The story above needs neither: read-only copies in other regions are fine there.