Forum Discussion

valuoc's avatar
valuoc
Copper Contributor
Feb 04, 2025

CosmosDb multi-region writes and creating globally unique value

Hi!

I am trying to understand how to deal with conflicts when using multi-region writes.

Imagine I am trying to create a Twitter clone and I have to ensure that when a user creates an account, it also select an unique user handle (a unique key like username ).

In a single region I would just have a container with no indexing and then create that value as a partition key, if I succeed it means that there was not another handle with that value and from this point nobody else will be able to add it.

But when thinking in multi-region writes, two persons in different regions could indeed add the same handle. Then the conflict resolution strategy would need to deal with it. But the only conflict resolution possible here is to delete one of them. But this is happening asynchronously after both persons successfully created their accounts, so one of them would get a bad surprise the next time they log in.

As far as I understood, https://learn.microsoft.com/en-us/azure/cosmos-db/consistency-levels#strong-consistency-and-multiple-write-regions

After thinking for a while about this problem I think there is no solution possible using multiple write regions. The only solution would be to have this container in an account with a single write region, and although the client could do a "tentative query" to another read-only region to see if a given handle is already taken, in the final step to actually take it I must force the client to do the final write operation in that particular region. Consistency levels here only help to define how close to reality is the "tentative query", but that is all.

Does this reasoning make sense?

Many thanks.

1 Reply

  • Your reasoning is incredibly solid, and you're tackling one of the trickiest problems in distributed systems: achieving global uniqueness under eventual consistency.

    Multi-Region Writes and Conflicts You're absolutely right: when you enable multi-region writes, each region accepts writes independently. Even with conflict resolution in place (like Cosmos DB’s "last write wins" or custom policies), if two users register the same handle nearly simultaneously in different regions, both operations could succeed locally. Then, conflict resolution kicks in later and overwrites one—leading to the surprise you mentioned. That’s a real UX risk.

    Why Strong Consistency Isn’t Enough Strong consistency can mitigate this, but only within one write region. Across multiple write regions, Cosmos DB (and other similar databases) don’t offer strong consistency, so you’re stuck with eventual consistency or session consistency at best. Even with "bounded staleness," there's a window for race conditions.

    Your Proposed Solution: Single Write Region You're spot on: keeping the username registration logic centralized in a single write region is the safest strategy. The tentative query from a nearby read replica improves latency, but the final write must go through the authoritative region to enforce uniqueness reliably.

    Here’s a refined breakdown of your architecture:

    • Clients perform a pre-check (tentative query) via local read regions.
    • Final write request is routed to the master region where you use CreateItem with a partition key on username. If it fails, you know the handle's taken—clean and atomic.
    • Optionally, you could implement a retry mechanism that asks users for a new handle if there's a conflict.

    Alternatives (with trade-offs):

    • Centralized Registration Service: Use a dedicated service (maybe an Azure Function or API) in the master region that clients call for username registration.
    • Leasing-based system: Use a temporary hold or reservation on handles before final commit, but this gets complex fast in distributed environments.
    • Globally synchronized cache (like Redis with RedLock): Advanced but potentially overkill for this case.

    So yes—your reasoning not only makes sense, it's the go-to approach used in many large-scale apps to handle unique user identifiers. 

Resources