Normalize account email addresses without merging users accidentally

A login repair lowercases every stored email address. Two existing accounts differ only by case and now produce the same login key. The script chooses the older account and deletes the other, assuming both belong to one person. Their memberships and billing records differ. A text cleanup has become an identity merge without evidence or a recovery plan.
This example assumes an account system using email as a login identifier and MongoDB storage. Email standards, provider behavior, and product policy are related but not identical. Define the application's identity rule rather than claiming a universal normalization that safely merges every address.
Separate display address from login key
Keep the user-entered or verified display address when it is useful for communication, and derive a separate login key under an explicit policy. The key exists to support lookup and uniqueness. The display field exists to preserve the address representation the product intends to show or use.
Trimming surrounding input whitespace is a different operation from changing the local part. Domain names are case-insensitive under relevant mail standards, while the local part has more nuanced semantics. Many products deliberately use case-insensitive login keys for usability, but that is a product identity decision that can conflict with existing accounts.
Do not apply provider-specific rules globally. Removing dots or plus suffixes may match some provider alias behavior but not every domain. Internationalized domains and Unicode local parts need a defined support policy and appropriate libraries. Avoid inventing a general parser from a simple split on the at sign.
Audit before changing values
Compute proposed login keys in a read-only preview. Group records by the proposed key and report collisions with safe identifiers and relevant account state. Include verified and unverified accounts, soft-deleted accounts, and legacy missing values according to the intended uniqueness scope.
A collision does not prove shared ownership. Two accounts may be an accidental duplicate, an intentionally separate identity, or an input error. Decide the resolution with a verified user or responsible account process. Do not merge memberships, balances, or private data automatically because strings normalize to the same key.
Count records requiring simple key addition separately from conflicts requiring decisions. A migration can proceed for unambiguous records while leaving a documented conflict set, provided login behavior remains safe and the deployment transition is compatible.
Define the transition contract
Decide how existing users log in while keys are being added. A fallback lookup must not choose an arbitrary matching account when multiple records collide. It should produce a safe resolution path or preserve the existing exact lookup until the conflict is handled.
Plan uniqueness enforcement on the new key. A partial unique index can sometimes limit enforcement to records with a valid key, but its predicate and query use must be verified. Do not assume missing values are harmless under every index configuration. Audit null and absent fields explicitly.
New registrations and email changes must use the same normalization policy during the transition. Otherwise the migration repairs existing rows while live writes create new inconsistent ones. Version the policy if future changes may alter keys so the system can identify which rule produced a stored value.
Implement a pure policy function
Keep parsing, accepted-address policy, and key derivation in a small tested module. The module should return a valid display address and login key or a deliberate validation result. It should not query accounts or merge identities.
Use the function in registration, login, email change, invitation matching, and migration only where those operations truly share identity semantics. An invitation display address may not need the same matching behavior as an account login. Document exceptions rather than forcing every email-looking field into one key.
At write time, enforce the chosen unique key in storage and handle concurrent conflicts. A pre-registration lookup cannot prevent two simultaneous requests from creating the same login identity. Storage uniqueness explains that race.
Preserve ownership during email changes
Changing an account's email should verify control of the new address according to the product's security policy. Do not treat a normalized key match as proof that a caller owns the existing account. An address-change flow can require current authentication, new-address verification, and careful session or recovery handling.
If the proposed new key belongs to another account, return a deliberate conflict without disclosing private account details. A support-assisted merge, if the product supports one, should be a separate operation with verified ownership and a plan for related data.
Keep password-reset and notification paths aligned with the verified address. A migration that changes login keys should not accidentally redirect recovery mail to an unverified replacement. Single-use reset grants cover a related credential boundary.
Verify policy and migration cases
Create synthetic fixtures for mixed-case domains, mixed-case local parts, surrounding whitespace, plus signs, dots, missing values, and unsupported internationalized forms. Assert the chosen policy rather than an imagined universal email rule.
Create two accounts that collide under the new key but have different related records. Verify the preview reports both and the write mode refuses an automatic merge. Test concurrent registrations for one key against isolated storage with the intended index installed.
Test login before, during, and after the transition. Include exact-match legacy accounts and unresolved conflicts. Test email change and password recovery separately. A migration can produce correct keys while the login adapter still reads the old field or applies a different lowercase rule.
Use AI to challenge identity assumptions
Give the assistant the policy statement, function, schema, and synthetic conflict set. Ask it to identify unsupported assumptions about provider aliases, local-part case, and ownership. Require sources for standards claims and code evidence for application behavior.
Do not ask a model to decide that two real users are the same person from their records. It can help explain a collision and enumerate resolution options, but identity merging needs trustworthy ownership evidence and a deliberate product process. Avoid providing real addresses when invented fixtures exercise the same policy.
A useful review checks that every write uses the same policy and every lookup handles ambiguity safely. It should not merely recommend lowercasing all strings or adding an index.
Keep cleanup separate from account merging
Normalization can make login behavior consistent and prevent future duplicate keys. It cannot recover lost identity evidence or prove that existing conflicting accounts should become one. Preserving that distinction keeps a reversible text transformation from becoming an irreversible data decision.
Checked migrations provide preview and precondition mechanics. Authorization tracing helps ensure that a normalized lookup does not become a shortcut around ownership.
Sources
About the Author

Kamruz
Full Stack Developer
A passionate developer who loves creating modern web applications and sharing knowledge with the community.
More About Me