Don't Use Phone Numbers as Primary Keys: The Identity Trap Behind Android's Verification Mechanism

A phone number describes a SIM card, not a person, so it shouldn't be a user primary key — and Android's new mechanism amplifies this design risk.
The article notes that Android automatically verifying device numbers and writing them to every signed-in Google account brings the "is a phone number suitable as a user primary key?" design question to the fore. A phone number describes a SIM card, not a person; number changes, lending, and carrier recycling all cause identity mismatches; one-number-many-people and one-person-many-numbers are the norm; and the number's lifecycle doesn't equal the account's. As the platform layer embeds verified numbers deeper into the account system, downstream systems that treat phone numbers as primary keys risk identity confusion and mismatches. The author recommends system-generated internal IDs (such as UUIDs) as primary keys, demoting the phone number to a verifiable attribute, and building a one-to-many user-to-identifier association model, plus practical advice on data model audits, separating identity from contact info, historical data migration, and number-change flow design.
Phone Numbers Are Quietly Becoming Your "Digital ID"
Android now automatically verifies the number in a device's SIM and adds that verified number to every Google account signed in on the device. On the surface this looks like a minor account security upgrade, but it pushes a long-neglected design problem into the spotlight: a phone number describes a SIM card, not a person.

Many systems are designed from the start to treat the phone number as a "unique and stable" user identifier — phone number to register, phone number to log in, phone number to recover a password. But once Android deeply binds the device number to the account system, the fragility of this approach is amplified further: number changes, shared devices, secondary SIMs, virtual numbers — any one of these links can cause an identity mismatch in systems that "use the phone number as the primary key."
Why Phone Numbers Don't Belong in the Primary Key
A Phone Number Describes a SIM, Not a Person
A phone number corresponds to a SIM card. A SIM card can change hands, be lent out, or be recycled and reassigned. The user bound to this number today may have handed the card to a family member tomorrow, or the number may have been reclaimed by the carrier and sold to a stranger. If a system treats the phone number as a person's unique identifier, the mismatch between "the number's current holder" and "the account's original holder" becomes a security hole.
One Number, Many People and One Person, Many Numbers Are the Norm
Family-shared devices, company-issued phones, dual-SIM phones, temporary secondary SIMs — in all these scenarios, a single phone number may be used by multiple people, and a single person may hold multiple numbers. Using a phone number as a primary key means the system must assume "one number always belongs to exactly one person," a assumption reality almost never satisfies.
The Number's Lifecycle Is Not the Account's Lifecycle
A user may change numbers without wanting to change accounts, or may close an account while keeping the number. The phone number's lifecycle is controlled by the carrier; the account's lifecycle is controlled by the product. Forcing the two together only makes unlinking and migration painfully difficult.
Primary Key is a field or combination of fields in a database used to uniquely identify each row in a table. Its core requirements are: non-null, unique, and as immutable as possible. In relational databases, primary keys are often referenced by other tables as foreign keys, so once the primary key value changes, every place that references it must be updated in sync — otherwise you get dangling references or data inconsistency.
Many early systems, for development convenience, used the phone number directly as the user table's primary key — because it was naturally unique, fixed-length, and easy for humans to recognize. But the primary key's stability assumption fundamentally conflicts with the phone number's mutable nature: numbers changing hands, being transferred, or being recycled all cause the "identity" represented by the primary key value to drift, and the database layer cannot perceive this drift. This is the fundamental engineering reason why using phone numbers as primary keys is dangerous.
What Android's New Mechanism Amplifies
Android automatically verifying the device number and writing it to every signed-in Google account means multiple accounts on one device may share the same "verified phone number." For third-party services that treat the phone number as a primary key, this has two direct consequences:
- Identity confusion: When multiple accounts are linked to the same verified number, phone-number-based deduplication, risk control, and recommendation logic may mistake different users for the same person.
- Mismatch risk: After a device is resold or a number is recycled, the new holder may inherit the old number's "identity traces" in the system, causing incorrect matches in verification, recovery, and similar flows.
Google treats the number as an attribute of the account to be verified, not as the identity itself — a reasonable design orientation. The problem is that many downstream systems misread "verified phone number" as "verified identity."
Device Fingerprinting refers to collecting a combination of device hardware and software characteristics (model, OS version, screen parameters, installed app list, network address, etc.) to generate a relatively stable device identifier, used to identify "this device" rather than "this person." It falls into the same "identifier" category as the phone number, but describes a different object: the phone number describes a SIM card, while the device fingerprint describes the hardware and system environment.
In identity system design, phone numbers, emails, device fingerprints, and third-party login IDs should all be treated as observable identifiers, not as the identity itself. Each has its own lifecycle and different levels of trustworthiness: a device fingerprint may change after a reflash or factory reset, and a phone number may transfer when the SIM is swapped. A sound identity architecture needs to layer "identity" and "identifiers," anchoring identity with an internal ID and using multiple identifiers for association and verification. Android writing the verified number into the account merely adds one observable identifier; if downstream systems treat it directly as an identity anchor, they conflate these two layers.
What to Use Instead of Phone Numbers as the Primary Key
Use a System-Generated Internal ID
The user table's primary key should be a system-generated internal ID (such as a UUID) unrelated to any external identifier. Phone numbers, emails, and device IDs should only serve as mutable contact methods or verification means, not as the identity itself. This keeps account relationships stable even when numbers change.
UUID (Universally Unique Identifier) is a 128-bit identifier generated by an algorithm, in the standard format 550e8400-e29b-41d4-a716-446655440000. It does not rely on a central registration authority and has an extremely low collision probability globally in theory, making it suitable for generating globally unique internal IDs in distributed systems.
Compared with auto-increment integer primary keys, UUIDs have the advantage of not depending on the database for generation, being convenient for sharding, and not leaking record counts. The drawbacks are poor readability, larger storage footprint (usually 16 bytes), and worse insert performance than auto-increment IDs when used as a clustered index. A common compromise in practice is to use "time-ordered" IDs such as UUIDv7 or Snowflake, which retain global uniqueness while improving index locality. For a user identity primary key, the key requirement is "unrelated to any external identifier and never changing" — UUID fits this precisely.
Treat the Phone Number as a "Verifiable Attribute," Not an "Identity"
Phone numbers are suitable for one-time verification, secondary confirmation, and risk notifications, but not for long-term identity anchoring. The design should allow users to change their bound number while preserving account history and permission relationships afterward.
Build a Multi-Identifier Association Model
A user may simultaneously have a phone number, email, third-party login, device fingerprint, and other identifiers. The reasonable approach is to build a one-to-many "user–identifier" relationship, letting each identifier be added or removed independently, rather than promoting any one of them to primary key.
The one-to-many association model is typically implemented in relational databases via a separate "identifier table," e.g. user_identifiers(user_id, type, value, verified_at, is_primary), where type distinguishes phone number, email, third-party OpenID, etc., and the user_id foreign key points to the users main table. This way each user can have any number of identifiers, and each identifier can be independently added, verified, unlinked, or replaced without destabilizing the users table's primary key.
This model also makes it easy to enforce the uniqueness constraint that "an identifier belongs to only one user at a time" (a unique index on type + value), preventing the same phone number from being occupied by two accounts at the database level. When a user changes numbers, only the record in the identifier table needs updating; data referencing user_id — accounts, orders, permissions — is completely unaffected. Compared with putting the phone number directly in the users table, the multi-identifier model fully decouples "identity" from "contact information" and is the foundational structure of a scalable identity system.
Practical Advice for Developers and Product Teams
- Audit existing data models: Check whether the users, orders, and log tables contain designs using the phone number as a foreign key or unique key.
- Separate identity from contact information: Move the phone number from the identity layer to the contact layer, decoupling verification logic from identity logic.
- Handle historical data migration: Add internal IDs for existing users and gradually replace phone-number references with internal-ID references.
- Design the number-change flow: Ensure that after a user changes numbers, accounts, orders, permissions, and history remain unaffected.
This Android change is a reminder: as the platform layer embeds phone numbers more deeply into the account system, the application layer should proactively take phone numbers off the primary key position. The foundation of an identity system should be a stable identifier for the "person," not a temporary description of the "card."
One-line Summary
A phone number describes a SIM card, not a person, and should not be used as a user primary key; Android's new mechanism amplifies this design risk.
Paragraph Summary
The article points out that Android automatically verifying the device number and writing it to every signed-in Google account brings the design question "is a phone number suitable as a user primary key?" to the fore. A phone number describes a SIM card, not an individual; number changes, lending, and carrier recycling all cause identity mismatches; one number, many people and one person, many numbers are the norm; and the number's lifecycle does not equal the account's lifecycle. As the platform layer embeds verified numbers more deeply into the account system, downstream systems that treat phone numbers as primary keys are prone to identity confusion and mismatches. The author recommends using system-generated internal IDs (such as UUIDs) as the primary key, demoting the phone number to a verifiable attribute, and building a one-to-many association model between users and multiple identifiers, along with concrete recommendations for data model auditing, separating identity from contact information, historical data migration, and number-change flow design.
Related articles

Cursor AI Programming in Practice: Build a Student Management System from Scratch in 30 Minutes
A Bilibili creator demonstrates Cursor AI programming: generating a student management system in 30 minutes with natural language. Details on Agent mode, Claude selection, prompt techniques, and thresholds.

Top 20 AI Coding Tools Ranking: From Rock-Solid to Lackluster, a Scored Matrix
Bilibili creator releases top 20 AI coding tools ranking, tiered T0–T4 from rock-solid to lackluster, with Claude Code and Codex tied at T0. This article details the scoring dimensions (capability, reliability, robustness, durability, cost, domestic availability) and tool performances to help developers choose the right AI coding assistant.

Vibe Coding Systematic Tutorial: Master AI-Assisted Programming from Zero
A three-month Vibe Coding tutorial from a Bilibili creator covering Codex, ClaudeCode, and Cursor, from core logic to commercial project practice for beginners.