Illustrative editorial image generated with AI.
Two names can look identical on screen yet contain different sequences of Unicode code points. That matters when software compares strings, searches for a customer or checks whether an import already exists. Normalization provides a consistent representation for certain equivalent sequences; it does not prove that two records describe the same person.
A small example explains the problem
The letter “é” can be represented as U+00E9, or as an ordinary “e” followed by the combining acute accent U+0301. A font may display these alike, while a direct string comparison sees different sequences. Unicode Standard Annex #15 defines normalization forms for these relationships. NFC uses canonical composition; NFD uses canonical decomposition. Both preserve canonical equivalence rather than stripping accents.
In a name-processing system, the question is therefore not simply whether the text looks right. It is whether all the paths that compare the text agree on a representation and whether the original supplied value remains available when needed.
Normalize both sides of a comparison
JavaScript exposes this operation through String.prototype.normalize(). An explicit NFC comparison can look like this:
const first = "José";
const second = "José";
const same = first.normalize("NFC") === second.normalize("NFC");The strings compare equal after normalization in this example. Applying the rule only to new form submissions would leave old imports and other entry points inconsistent. Decide where the transformation belongs, then cover the API, import job and search index as well as the browser form.
Compatibility forms need a separate decision
NFKC and NFKD also account for compatibility relationships. They can change distinctions you may want to preserve in displayed text. Do not choose a compatibility form merely because its name sounds more comprehensive. Write down the intended outcome and test examples relevant to your users before using it in a permanent storage transformation.
For a display name, preserving what the person supplied and maintaining a separate comparison value is often a practical design. That is an implementation choice, not a claim that the Unicode standard dictates your database schema.
Normalization is not identity resolution
It does not translate between scripts, remove every spelling difference or decide whether a nickname belongs to an account holder. It also does not turn visually confusable letters from different scripts into a trustworthy identifier. If a name match controls account access, payment or a record merge, additional verification is necessary.
Consider two people whose names are both José. Their strings may match perfectly; they remain two people. Conversely, one person's preferred name can change without changing their account. Use a stable internal identifier for records and treat names as user-facing attributes.
Test the system beyond the happy path
Create fixtures containing the composed and decomposed example, a genuinely different spelling and an unrelated record with the same name. Confirm that lookup finds the equivalent forms without automatically merging the unrelated record. Export and re-import them, then repeat the comparison.
Keep the normalization rule documented and consistent across services. If you change it, rebuild derived indexes from preserved source values and inspect possible collisions before applying uniqueness constraints. The goal is predictable text handling: equivalent encodings behave consistently, while decisions about people remain explicit.
