A profile store has one authoritative record per user ID. The authentication team needs to find an account using a verified phone number. You add a reverse mapping from normalized phone number to user ID. A customer changes numbers, another customer claims the old number, and a retry arrives during the change. Design the reverse lookup so it never assigns a verified number to two active accounts.
For this question, the service owns phone verification and identity assignment. A phone number is not, by itself, sufficient proof of account ownership. Assume the chosen database supports conditional per-item writes. We will compare a database with atomic multi-item transactions against one that does not offer them across these records.
Think first
Design unique public usernames for a globally distributed application. The profile store is sharded by user ID and usernames can change. Define claim ownership, retries, reassignment and cross-region behavior.
Take a few minutes to form an approach, then compare it with the worked explanation.
Reveal the worked explanation
Two ways to look up the same account
The existing record looks like user:4729 -> profile. A new record might look like phone:+15550102 -> user:4729. Both are fast point lookups. But they are two records describing one relationship.
A naive change writes the new phone mapping and then updates the user profile. Stop between those writes and the two records disagree. Reverse the order and the gap simply moves. If the old mapping is deleted first and the process crashes, the account may temporarily be unreachable by that phone number.
A phone-number claim and user profile record must change under one authority, or their states can diverge.
The tricky issue is not how to perform Get(phone). It is who is allowed to claim the value of phone when multiple requests race.
A useful invariant is that a normalized, verified phone number has at most one active owner in this identity domain. That says nothing about whether one person may have multiple phone numbers or whether old numbers can be recycled. Those are separate product rules.
A reverse index is not automatically a uniqueness constraint
Suppose users 4729 and 9811 simultaneously try to claim +15550102.
If both first query an eventually consistent secondary index and see nothing, both might proceed. A missing index result is not a serialized ownership decision. DynamoDB global secondary indexes, for example, are updated asynchronously and support eventually consistent reads only. Their presence alone is not an application-wide uniqueness constraint. DynamoDB GSI
I would make the phone-claim item the authority for that number and use a conditional creation that succeeds only if that key is unclaimed. In DynamoDB, a conditional PutItem with attribute_not_exists can prevent overwriting an existing item with the same full key. Conditional writes
The claim stores more than the user ID. It needs a normalized number, ownership generation, verification state, perhaps a verification proof reference, and lifecycle timestamps. The generation helps reason about delayed requests. It is not a substitute for conditions enforced at the storage authority.
Change a number without leaving misleading ownership
If both profile and phone claims live in a database supporting atomic multi-item transactions, I would change them together. For example, after verifying the new number, the transaction conditionally creates the new claim, updates the profile if it still has the expected generation, and removes or retires the old claim only if that old claim still belongs to the same account and expected ownership generation.
Imagine delayed cleanup from user 4729 arriving after number reassignment to 9811. An unconditional deletion of the old phone key might delete the new owner's valid claim. Conditional owner-and-generation checks make cleanup depend on the intended claim incarnation, including when the same account later reclaims the number.
DynamoDB's TransactWriteItems is one specific implementation option. It provides an atomic group of item actions within one Region and account, with documented limits. Its transaction support should not be generalized to every key-value store or to cross-region replicas. TransactWriteItems
There are subtle choices about how readers observe transitions. If a lookup resolves to a profile and then the ownership changes, the caller could be looking at an old relationship. For security-critical use, the final authorization step must validate that the resolved profile still owns the verified phone claim under the expected generation. A standalone reverse lookup should not be treated as a permanent permission.
What if the store cannot atomically update both records?
Then I would not promise instant, always-available, globally consistent ownership based on two independent writes. One reasonable design makes the claim record authoritative and the user profile's phone field a derived display copy. Changing ownership updates the claim through a conditional operation, while a recoverable projection worker updates the profile. Readers needing a security decision consult the claim, not the possibly stale display field.
That weakens the promise about when all copies match, but not the uniqueness rule enforced at the claim authority.
A second option is a durable registration workflow with PENDING, VERIFIED, ACTIVE, and RETIRED states. It must be explicit about which state grants ownership and how abandoned transitions are reconciled. Simply adding a queue does not eliminate the ambiguous outcome when a worker crashes after a conditional claim succeeds.
Phone-number recycling also creates a security risk beyond database races. A previously verified number may later belong to a different real-world person. Its long-lived use as an immutable account identity can be unsafe. Require appropriate re-verification and recovery policy when changing phone ownership, and retain audit evidence without exposing sensitive values unnecessarily.
Would the same design fit an optional report?
If product only wants a reverse lookup for optional marketing reports, an eventually consistent index may be fine. If the result decides which account gets a login credential, the freshness and ownership contract must be stronger.
The important question is where exclusivity is enforced and whether two competing claims can both succeed. A secondary index accelerates finding records. A conditional claim establishes an ownership rule. Those are related, but not the same feature.
Now imagine the same team starts storing all of a customer's blog comments inside the customer's profile document. The lookup is still easy, but the record itself begins to change shape and size as the product grows.
Go deeper
Optional depth: normalizing and transferring a number
Phone-number normalization is part of correctness. A trusted library and an explicit country-context contract are preferable to trimming punctuation and assuming two strings name different numbers. A transfer flow may require a hold or reassignment policy when an old account loses access, and high-risk transitions should be auditable. If the service supports multiple Regions, specify which Region owns the claim. An atomic DynamoDB transaction in one Region does not imply immediate globally serializable ownership across all multi-active replicas. DynamoDB transaction constraints
Check your reasoning
Represent one authoritative claim for a normalized phone number.
Explain competing conditional writes without check-then-insert races.
Handle delayed cleanup and ownership generation.
Use multi-item transactions only within their actual documented scope.
Distinguish reverse lookup freshness from verified account ownership.
Common mistake: A global secondary index automatically enforces globally unique phone numbers.
Read the answer explanation
Create the phone claim conditionally under the authoritative phone key — Conditional claiming at the owner arbitrates concurrent attempts. An index accelerates lookup but does not enforce that uniqueness.
Apply it elsewhere
A distributed artifact registry needs one globally unique package name that can be transferred between organizations. What relationship needs an owner and a version?
Compare your approach
Separate lookup performance from uniqueness. Establish one authoritative claim per value. Handle competing conditional writes and delayed cleanup. State whether multi-record atomicity is available. Distinguish verification from possession of a string. Explain stale read and migration effects.
One more constraint
An eventually consistent phone index returns no match. Does that establish the number is available for registration?
Quick revision
A reverse mapping makes lookup by a second field fast, but it does not automatically enforce that only one owner can claim that field. The ownership record needs an authoritative conditional write. If profile and mapping must change together, use supported multi-item atomicity or make one record authoritative and treat the other as a projection. Always define what happens during change, retries, recycling and cross-region replication.