Skip to content
KEDBYTE
Site navigation
How Data Works
Chapter
5

Identity, Keys and the Problem of Duplicates

Part A · Meaning Before Machines|6,240 words|about 27 min read|Volume A

5.0 What this chapter gives you#

  1. You will distinguish a thing, its record, its display name and the identifier used to refer to it.
  2. You will choose a key by examining its scope and lifetime, not merely whether its sample values look different.
  3. You will explain why generating an identifier and enforcing uniqueness are separate jobs.
  4. You will separate a repeated delivery of one event from a second genuine event with similar contents.
  5. You will design a reviewable matching process that can preserve an uncertain outcome instead of pretending every pair is a match or a non-match.
  6. You will preserve enough history to explain and reverse a mistaken identity merge without quietly rewriting unrelated records.

Keep the meanings separate#

This chapter concerns record identity: which product, order, source record or event a reference names. It is not a complete treatment of proving who a person is or deciding what they may access. Those are distinct problems. The existence of a database key is not authentication, and knowing that key is not authorisation.

The established shop fixtures remain unchanged. O-1042 still has two order lines; its first line is identified by (O-1042, 1). Multi-branch and matching examples below are new synthetic exercises. They do not assert that existing customers have been merged or that the shop has already deployed a multi-tenant service.

5.1 Names and identifiers#

5.1.1 PLAIN — in simple words#

  1. A name helps a person recognise something. An identifier helps a system refer to the intended thing under an agreed rule. Sometimes one value does both jobs, but the jobs remain different.
  2. Two products can both be called “Blue Notebook.” A product can also change its display name without becoming a different product in the shop’s catalogue.
  3. The system therefore needs a rule for what stays the same through a change. A product identifier might remain stable while its label, description or supplier changes.
  4. That stability is a design decision. Software cannot discover it merely by noticing that two strings look similar.

5.1.2 PLAIN — a picture in your head#

  1. Imagine a room of people wearing name badges. Two badges say “Dev.” Calling out the name does not identify one person unambiguously.
  2. Now give each visitor a numbered ticket for this event. The ticket can identify a particular admission record even when several visitors share a name.
  3. Where this comparison breaks: the ticket identifies an admission in its issuing system, not necessarily one person for life. A person can have two tickets, and a stolen ticket does not prove the holder’s identity.

5.1.3 PLAIN — a worked example#

  1. In our original catalogue, P-NOTE identifies the notebook product used by O-1042. Its agreed unit price in that order is 7,550 paise.
  2. Suppose a new display label is proposed: “Ruled Notebook.” Under this teaching policy the product identity remains P-NOTE. The historical order still points to the same product and retains its own agreed price.
  3. Now introduce a distinct catalogue item, P-NOTE-A5, whose display label also contains “Notebook.” Similar words do not justify replacing P-NOTE with P-NOTE-A5 in old orders.
  4. Finally, the supplier’s catalogue might call our P-NOTE NB-17. That creates a mapping between identifier systems; it does not make NB-17 universally meaningful.
Reference What it names in this example What it does not establish
P-NOTE One product in our catalogue A physical individual notebook
O-1042 One order in our shop fixture Payment settlement or delivery by itself
O-1042, line 1 One agreed order line Every line containing the same product
NB-17 under supplier SUP-A A supplier’s product reference The meaning of NB-17 at another supplier

5.1.4 PLAIN — what is really happening inside#

  1. A reference points into an identifier space. The receiving system looks up that reference and interprets the returned record under the correct contract.
  2. When a human-readable label changes, a stable identifier can keep references connected. When an identifier changes, the system needs a deliberate migration or mapping policy.
  3. A record ID should also have a lifecycle rule. Can it be reused after deletion? Can it be imported from another system? Can it survive a merge? Those choices affect old links, delayed messages and historical reports.
  4. For our teaching catalogue, retired product identifiers will not be reassigned to different products. That is an explicit policy for the story, not a universal property of the word “identifier.”

5.1.5 TECHNICAL — the engineer’s version#

  1. Distinguish an entity from its representations. A product can have a current catalogue record, an export row and historical order-line references. These records do not all have the same grain or identifier.
  2. A key identifies a record under the model’s uniqueness rules. A primary key is the selected identifying key of a table; other candidate keys can be enforced independently. PostgreSQL primary keys require uniqueness and non-null values. [S02]
  3. A displayed name is not a candidate key unless the domain actually guarantees uniqueness and the schema enforces the intended rule. A current dataset containing no duplicate names is only an observation about that dataset.
  4. Consider mutability. An email address may change, be shared or later be reassigned. Whether it is suitable for a particular key depends on the domain contract and lifecycle; a convenient login field is not automatically a stable entity identity.
  5. Store external identifiers with their authority or namespace. A useful mapping grain is one external identifier under one issuing namespace, linked to an internal record under a documented validity policy.
  6. The honest version: adding a generated key does not solve every identity problem. It guarantees neither that only one record represents each real-world entity nor that an existing reference was attached to the correct entity.

5.1.6 WORDS — remember these#

  1. Entity: the thing the model is about; technically, a distinguishable object, concept or occurrence represented within a domain model.

  1. Identifier: a value used to refer to something; technically, a designation interpreted within an issuing namespace and its lifecycle rules.

  1. Display name: the label shown to a person; technically, a presentation attribute that need not be unique or stable.

  1. Primary key: the table’s chosen identifying key; technically, a selected set of columns whose combined values uniquely identify each row and cannot be null under the relevant database rules.

5.2 Natural and generated keys#

5.2.1 PLAIN — in simple words#

  1. Some identifiers already exist in the work being modelled. Others are created by the new system solely to name its records.
  2. An existing catalogue code can be useful when its issuing organisation maintains it consistently. A generated number can be useful when ordinary attributes are mutable or ambiguous.
  3. Neither option is automatically correct. Ask who issues the value, whether it can change, where it must be unique and what happens when records arrive from elsewhere.
  4. A machine that generates new numbers is not the same thing as a rule that refuses duplicate stored numbers. Good designs examine both.

5.2.2 PLAIN — a picture in your head#

  1. Imagine organising books using the number already printed by the publisher, or attaching your library’s own accession label to each copy.
  2. The publisher’s number and the library label can both be useful because they name things at different levels. One edition can have many physical copies.
  3. Where this comparison breaks: database key terminology depends on the model. A value that looks “natural” in one system may have been generated by another. The important question is what it identifies and what rules govern it.

5.2.3 PLAIN — a worked example#

  1. In a new supplier-import exercise, SUP-A supplies product code 017, while SUP-B also supplies product code 017.
  2. Treating 017 alone as a globally unique product key incorrectly collides two issuing systems.
  3. The pair (SUP-A, 017) differs from (SUP-B, 017). An internal product record can have a separate generated ID while preserving either mapping as evidence.
  4. A second import of (SUP-A, 017) might be an update to the same supplier reference, not a new product. Its meaning depends on that supplier’s versioning and reuse policy.
  5. A generated internal ID therefore solves the naming of the receiving row, while the supplier mapping solves a different problem: recognising which source reference the row represents.
-- PostgreSQL 17 illustration; not an executed PostgreSQL lab.
CREATE TABLE supplier_reference_example (
    reference_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    supplier_id text NOT NULL,
    supplier_code text NOT NULL,
    UNIQUE (supplier_id, supplier_code)
);
  1. Read the two rules separately: the primary key identifies the receiving row, while the unique pair prevents two current rows from claiming the same supplier reference in this deliberately narrow model.

5.2.4 PLAIN — what is really happening inside#

  1. A sequence-like generator allocates values. A uniqueness constraint checks whether the relevant values conflict with accepted rows. The generator and the constraint can be configured or bypassed differently.
  2. PostgreSQL documents that an identity column is not, by itself, a uniqueness guarantee. The underlying sequence can be reset, and explicit values can be inserted under permitted rules. A primary-key or unique constraint is still needed for uniqueness. [S37]
  3. Another approach uses a large identifier format designed for distributed generation, such as a UUID. This reduces the need for every issuer to ask one shared counter, but it still needs correct generation and handling. [S38]
  4. Choosing a large identifier does not remove the need to reject reused IDs, preserve namespaces or distinguish duplicate source records from duplicate real-world entities.

5.2.5 TECHNICAL — the engineer’s version#

  1. A natural key is derived from domain attributes or identifiers already meaningful in the modelled work. A surrogate key is introduced to identify a record without carrying the same business meaning. These are modelling categories, not quality rankings.
  2. A natural key may be long, composite or mutable. A surrogate key can provide a compact reference, but it can also permit duplicate business records unless relevant alternate uniqueness rules remain enforced.
  3. In UUID version 4, 128 total bits include fixed version and variant fields, leaving 122 random bits in the specified layout. The collision model therefore has 2^122 possible random values, not 2^128. [S38]
  4. Under independent uniform generation, the approximate probability of at least one collision among n IDs is n*(n-1)/(2*N) when this probability is small and N is the number of possible values. This is the birthday approximation, derived by counting possible pairs.
  5. With n = 1,000,000,000 and N = 2^122, the approximation is about 9.4 × 10^-20. This is an arithmetic illustration under the stated random model, not an observed failure rate of a deployed system.
  6. Broken randomness, copied state, accidental identifier reuse and incorrect imports are outside that ideal collision calculation. Extremely small random-collision probability does not prove correct implementation.
  7. Different UUID versions encode different information. A time-ordered identifier is not automatically a globally authoritative event order or an authentication token. Interpret the actual version rather than assuming every UUID has the same meaning. [S38]
  8. Query patterns and storage costs matter too, but only after identity requirements are defined. Later index and storage chapters will examine the costs of different key layouts without turning them into universal “always use this type” rules.

5.2.6 WORDS — remember these#

  1. Natural key: a key drawn from the work’s own attributes; technically, an identifying set of domain attributes rather than a record-only identifier introduced by the receiving model.

  1. Surrogate key: an extra identifier created for the record; technically, a key whose principal role is row identity rather than existing business meaning.

  1. Unique constraint: a rule against repeated key values; technically, database enforcement that the relevant value combination cannot appear in conflicting rows under its null and comparison rules.

  1. UUID: a standardised large identifier; technically, a 128-bit identifier whose version and variant determine the interpretation and generation rules.

5.3 Scope and composite identity#

5.3.1 PLAIN — in simple words#

  1. “Number 17” is incomplete when two branches each issue their own number 17. The missing information is the scope in which the number was issued.
  2. A composite identity uses several fields together. The combination identifies the intended record even when none of the fields is unique alone.
  3. An order-line number is a familiar example. Line 1 appears in many orders. The order identifier plus the line number names the intended line.
  4. Do not lose the scope while exporting, joining or constructing an address. Keeping it in the database but dropping it in the next message reintroduces the ambiguity.

5.3.2 PLAIN — a picture in your head#

  1. Two apartment buildings can both contain flat 17. A courier needs the building and the flat, not just the number painted on the door.
  2. The full address works because its pieces belong together. Sorting the pieces independently and pairing them again can create an address that was never supplied.
  3. Where this comparison breaks: a database scope need not be a physical place. It might be a tenant, issuing authority, dataset version or parent record.

5.3.3 PLAIN — a worked example#

  1. Our established order lines include (O-1042, 1) and (O-1043, 1). They share a line number but not an identity.
  2. Now use a separate branch-local receipt example: (BR-A, 17) and (BR-B, 17). Both are legitimate under the policy that each branch numbers its own receipts.
  3. A lookup using only local_receipt_no = 17 may find two rows. Selecting the first one is not a valid resolution rule.
  4. A lookup using both fields expresses the complete key: branch_id = 'BR-A' AND local_receipt_no = 17.
  5. The same issue appears in joins. Joining receipt details to headers only by local receipt number can pair one branch’s details with another branch’s header.
Branch Local receipt Amount in this separate fixture
BR-A 17 500 paise
BR-B 17 900 paise
  1. The two amounts are invented for this exercise and do not replace either canonical order total. The example exists to reveal the missing key component.

Figure 5.1. The same local number can be valid in two namespaces. Keep the full identifier together through lookups, messages and joins.

Figure 5.1. The same local number can be valid in two namespaces. Keep the full identifier together through lookups, messages and joins.

5.3.4 PLAIN — what is really happening inside#

  1. A database can enforce a rule over a column combination. The combination is checked as a whole; the individual columns need not each be globally unique. [S02]
  2. The application must then carry the same combination through its workflows. A user-interface link that drops the branch component undermines the model even when the database schema is correct.
  3. The record’s parent relationship may also be enforced by a foreign key. That checks the relevant stored relationship; it does not decide whether the current caller is allowed to read the parent or child.
  4. The design therefore has two independent questions: which record is this? and may this caller perform this action on it? A complete key answers only the first.

5.3.5 TECHNICAL — the engineer’s version#

  1. A composite primary key such as (branch_id, local_receipt_no) identifies a row by the ordered set of its component meanings. Referencing tables should preserve the relevant scope in their foreign-key relationship.
  2. If a local number is unique only within a branch, enforcing a foreign key on the number alone does not express the intended relationship. Where a database rejects that incomplete reference, the error is useful feedback about the model.
  3. The order-line grain remains (order_id, line_no) in our original single-shop fixture. A future multi-tenant design might need a tenant component or a separately guaranteed global order ID. That is a future schema decision, not a silent reinterpretation of existing examples.
  4. Avoid ambiguous string concatenation. The pairs ('AB', 'C') and ('A', 'BC') both become ABC when joined without boundaries. Use a structured representation or a documented escaping and length rule.
  5. Nullability is also part of identity. A complete identifying key cannot rely on an absent parent component. Different databases have distinct null and uniqueness semantics, so state the actual constraints rather than relying on a label such as “unique.” [S02]
  6. A scope check is not a substitute for authorisation. In a tenant-scoped service, the server must connect the requested scope to the authenticated caller’s allowed actions. Accepting a user-supplied tenant ID without that connection does not enforce isolation.
  7. Preserve key components when generating reports and cache entries. A cache keyed only by a branch-local number can return a perfectly valid record belonging to the wrong branch.
  8. The honest version: “the ID is unique” is an incomplete claim until you state where, for what kind of record, over which lifetime, and under which enforcement rule.

5.3.6 WORDS — remember these#

  1. Namespace: the context in which an identifier has meaning; technically, an issuing or interpretive scope within which names are assigned and resolved.

  1. Composite key: several fields identifying a row together; technically, a key consisting of more than one attribute.

  1. Foreign key: a checked reference to another stored key; technically, a constraint requiring referencing values to correspond to an eligible referenced key, subject to the database’s rules.

  1. Tenant scope: the customer boundary in a shared service; technically, the domain boundary used to associate records and permitted operations with a tenant, requiring access control beyond identification.

5.4 Duplicate delivery versus repeated events#

5.4.1 PLAIN — in simple words#

  1. Receiving a message twice does not necessarily mean the underlying action happened twice. A sender may repeat delivery because the first acknowledgement was lost.
  2. The reverse also matters: two real actions can have identical-looking contents. A customer can buy one pen now and another pen a minute later.
  3. The system needs to distinguish the identity of an event from its contents and from the identity of one delivery attempt.
  4. “Delete every repeated-looking row” is therefore not a safe general duplicate policy. It can remove genuine work or preserve a harmful replay, depending on what it compares.

5.4.2 PLAIN — a picture in your head#

  1. Mira sends a photocopy of one signed dispatch note because the recipient says the first copy did not arrive. Two envelopes now carry evidence about one dispatch.
  2. On another day she sends two separate dispatch notes for two separate parcels containing the same product. Similar descriptions now concern two events.
  3. Where this comparison breaks: software can preserve an explicit source-and-event identifier and compare a replay against recorded content. A paper description may not contain those machine-checkable fields.

5.4.3 PLAIN — a worked example#

  1. Introduce four synthetic messages from source /miras-corner/till-a. None is a new statement about the already established stock discrepancy.
Delivery Event ID Meaningful payload Our proposed treatment
D-A E-700 One pen issued First accepted delivery of E-700
D-B E-700 One pen issued Replay of E-700; do not apply again
D-C E-701 One pen issued Distinct event; apply under its own rules
D-D E-700 Three pens issued Identifier conflict; investigate
  1. D-A and D-B are two deliveries describing one event. D-C describes a second event even though its quantity matches.
  2. D-D reuses E-700 with different meaningful content. Silently treating it as an ordinary replay would hide an inconsistency; applying it would reuse one identity for conflicting claims.
  3. Our toy consumer will therefore distinguish accepted, duplicate, and conflict. The conflict is rejected rather than resolved by choosing whichever value arrived last.
  4. The standard CloudEvents model similarly defines event uniqueness through the combination of source and id. Its specification permits a resent duplicate to retain that identity. [S39]

5.4.4 PLAIN — what is really happening inside#

  1. The receiver checks whether it has already accepted the source-and-ID pair within the relevant retention and processing boundary.
  2. If the pair is new, it validates the event and applies the intended update. If the pair is already present with the same agreed content, it returns the previous logical outcome without repeating the update.
  3. If the pair has conflicting content, the receiver needs an explicit failure path. A producer bug, import mistake or hostile input must not become an unnoticed change to the original event.
  4. Recording “seen” and applying the update are themselves related changes. In a persistent consumer they need appropriate coordination. Otherwise a failure between them can either lose an update or apply it twice.
  5. The companion lab keeps these operations in a single in-memory routine. That illustrates the contract; it does not test a durable multi-process consumer.

5.4.5 TECHNICAL — the engineer’s version#

  1. An idempotent operation produces the same intended state effect when repeated under its declared identity and conditions. Idempotency is a property of an operation’s semantics, not a magic attribute attached to a request header.
  2. Distinguish four possible identifiers: the business object ID, the command/request ID, the accepted event ID and the delivery-attempt ID. A retry can preserve some while changing others. Their relationship must be documented.
  3. CloudEvents 1.0.2 requires the source and id combination to identify distinct events. Its wire-level specversion value remains 1.0; the patch release number is not written as 1.0.2 in that attribute. [S39]
  4. A uniqueness rule on (source, event_id) prevents storing two rows under the same identity, but does not alone prove that the first update and its deduplication record were committed together.
  5. Compare meaningful content under a stable schema. Raw JSON text can differ in insignificant spacing or member order. Conversely, a comparison that drops a meaningful field can falsely classify conflicting events as equivalent. JSON representation and application semantics are separate boundaries. [S07]
  6. A hash can accelerate a comparison or bind a retained representation, but it must be interpreted with its algorithm and canonicalisation rules. The lab compares a fixed tuple of validated domain fields rather than presenting an arbitrary JSON hash as semantic truth.
  7. A deduplication record also has a lifetime. If it expires before a legitimate retry arrives, the consumer may treat the retry as new unless another durable business rule prevents the repeated effect. The guarantee must state its retention and recovery assumptions.
  8. “Exactly once” is therefore incomplete without an effect boundary: once in a table, once in a projection, once in an email service or once in the physical world are different claims.

5.4.6 WORDS — remember these#

  1. Event identity: the name of one accepted occurrence or change; technically, the identifier combination that distinguishes an event under the producer’s contract.

  1. Delivery attempt: one effort to transport a message; technically, a transmission attempt that may repeat the same logical event.

  1. Idempotency: repeating the operation without repeating its intended effect; technically, stability of the declared effect under repeated application within the operation’s identity and failure model.

  1. Deduplication: recognising a repeated identity; technically, detecting and handling duplicate deliveries or records under an explicitly defined equivalence and retention policy.

  1. Identity conflict: one ID attached to incompatible content; technically, a violation of the mapping from an identifier to the immutable or otherwise controlled claim it is supposed to name.

5.5 Matching imperfect records#

5.5.1 PLAIN — in simple words#

  1. Sometimes two systems describe the same thing without sharing an identifier. Matching then becomes a reasoning problem rather than a simple key lookup.
  2. Similar spelling is evidence, not certainty. Two supplier records can look alike and describe different products; one product can also appear under several spellings.
  3. A useful matching process can say same, different, or not enough evidence. Forcing every uncertain pair into one of the first two categories hides the uncertainty instead of solving it.
  4. The consequences matter. An incorrect suggestion is different from an automatic merge that changes orders, permissions or historical reports.

5.5.2 PLAIN — a picture in your head#

  1. Imagine sorting two boxes of old catalogue cards. Some cards share an exact issuing code; others share only an abbreviated name and a partial description.
  2. You can place uncertain pairs beside each other for review without gluing them into one card. That preserves the option to inspect more evidence.
  3. Where this comparison breaks: a software merge may redirect thousands of relationships instantly. A convenient-looking shortcut can have effects far beyond the two rows visible on screen.

5.5.3 PLAIN — a worked example#

  1. In an independent synthetic matching exercise, consider records SRC-A-17, labelled “Blue ruled notebook,” and SRC-B-88, labelled “Blue notebook.” Their names suggest a candidate pair, not a completed identity decision.
  2. A checked common manufacturer code would be different evidence from name similarity, but even that requires understanding the code’s issuing scope and reuse rules.
  3. Suppose a labelled evaluation set contains 10 genuinely matching pairs and 90 genuinely different pairs. A candidate rule accepts 8 of the matches and incorrectly accepts 3 different pairs.
  4. It has therefore accepted 11 pairs, of which 8 are true matches. Its precision on this set is 8/11 ≈ 72.7%.
  5. It found 8 of the 10 true matches, so its recall is 80%. Its false-positive rate among the different pairs is 3/90 ≈ 3.33%.
  6. These are different denominators. None of the figures means there is a 72.7% probability that any particular new pair is the same product.
Label in the fixture Accepted as a match Not accepted as a match
Same product 8 2
Different products 3 87
  1. The matrix is invented to teach the arithmetic. It is not a performance claim for a real KedByte matching service.

5.5.4 PLAIN — what is really happening inside#

  1. A matching workflow first prepares comparable features, then proposes candidates, evaluates evidence and applies a decision policy.
  2. Normalising spaces or case can make comparison useful, but it also changes a representation. Preserve the original source value when needed to explain the decision, subject to the purpose and retention policy.
  3. Unicode normalisation can make certain equivalent text sequences comparable. It does not prove that two named entities are the same, or that visually similar characters are safe to treat as identical. [S15]
  4. A human-review queue should show why a pair was proposed and what remains uncertain. “The system says 0.92” is not enough when the score’s meaning and validation are unexplained.
  5. For our teaching design, a candidate match has no authority to rewrite source records. Only an explicitly recorded decision can create a mapping, and that mapping remains reviewable.

5.5.5 TECHNICAL — the engineer’s version#

  1. Entity resolution attempts to identify records that refer to the same underlying entity. It is different from deduplicating identical source event IDs: one compares uncertain referents, while the other can enforce a known producer identity contract.
  2. Candidate generation, sometimes called blocking, reduces the number of pairs examined. It can improve computational efficiency while excluding some true matches. Evaluate that stage rather than measuring only the final scorer.
  3. Precision is true_positives / (true_positives + false_positives). Recall is true_positives / (true_positives + false_negatives). Define how zero denominators are reported instead of quietly inventing a perfect score.
  4. Performance measured on a labelled sample depends on the sample’s construction, label quality and relationship to the deployment population. A hand-selected easy test set does not establish production reliability.
  5. A threshold selects a trade-off between missed matches and false matches. The appropriate policy depends on consequences, review capacity and available evidence. A score is not automatically a calibrated probability.
  6. Separate matching from permissions. Linking two product records should not accidentally merge ownership rules. Linking person records is even more consequential and requires a separately designed access and decision process; this toy exercise does not implement one.
  7. Preserve provenance for each accepted mapping: source record IDs, rule version, evidence references, decision outcome and the applicable time or version boundary. W3C PROV’s distinctions between entities, activities and agents help describe this reasoning without confusing a source fact with a derived decision. [S05]
  8. The honest version: an algorithm that compares strings can be perfectly implemented and still make wrong identity decisions. Correct computation and justified inference are separate requirements.

5.5.6 WORDS — remember these#

  1. Entity resolution: deciding which records concern the same thing; technically, inference over records that may lack a shared reliable identifier.

  1. Candidate match: a pair worth investigating; technically, a proposed association that has not yet satisfied the final decision policy.

  1. Precision, matching: the share of accepted matches that are correct; technically, true positives divided by all positive predictions, not measurement precision from Chapter 4.

  1. Recall: the share of true matches found; technically, true positives divided by the actual positive cases under the evaluation labels.

  1. False positive: a match accepted when the entities differ; technically, a positive decision for a negatively labelled case in the stated evaluation.

5.6 Merge, split and identity history#

5.6.1 PLAIN — in simple words#

  1. A merge says that records should now be treated as referring to one entity under a decision policy. It does not make every original value true or erase why the records differed.
  2. A split reverses or revises that association. To do it well, the system needs to know which source records and relationships belonged to the disputed decision.
  3. “Delete the duplicate row” is often too crude. It can discard the evidence needed to repair a wrong merge or explain an old report.
  4. At the same time, keeping every detail forever is not the solution. Retain the information justified by the purpose and define what becomes impossible when particular evidence is removed.

5.6.2 PLAIN — a picture in your head#

  1. Imagine attaching a removable note to two catalogue folders: “For current purchasing, treat these as one product group; decision M-01.” The folders still show where their original information came from.
  2. If the decision proves wrong, you can remove the association and identify the work performed while it was active.
  3. Where this comparison breaks: undoing an association does not automatically undo purchases, exports or messages already produced from it. Those downstream effects need their own review and correction.

5.6.3 PLAIN — a worked example#

  1. Use a separate synthetic identity-history fixture with three source records: SRC-A-17, SRC-B-88 and SRC-B-89. No real customer information is present.
  2. Decision M-01 associates SRC-A-17 and SRC-B-88 with canonical product group CAN-10. SRC-B-89 remains in CAN-11.
  3. A later review finds that SRC-B-88 describes a different pack size. Decision M-02 supersedes the earlier association for that source record and places it in CAN-12.
  4. The original source IDs remain intact. A report can now distinguish “grouping under M-01” from “grouping under M-02” rather than quietly pretending the earlier interpretation never existed.
  5. The corrected grouping does not automatically recalculate every previously exported report. The system must identify which outputs depended on M-01 and decide what correction or notification is appropriate.
Decision version SRC-A-17 SRC-B-88 SRC-B-89
M-01 CAN-10 CAN-10 CAN-11
M-02 CAN-10 CAN-12 CAN-11
  1. A small reversible mapping is therefore more informative than overwriting SRC-B-88’s identity and losing its source history.

5.6.4 PLAIN — what is really happening inside#

  1. The source record and the current identity interpretation are separate layers. A mapping connects them under a decision version.
  2. Updating the mapping changes what a current query resolves, but it does not change the original observation’s meaning. A historical query may intentionally use the older mapping version.
  3. A safe change checks dependent records, invalidates or rebuilds affected derived views, and records the decision’s basis. Where the evidence is insufficient, the association can remain unresolved.
  4. The process must also prevent impossible mappings, such as a chain that loops back to itself or one source assigned to two current canonical records when the domain permits only one.
  5. These are proposed invariants for our exercise. The presence of a canonical_id column does not enforce them without the necessary constraints and change procedure.

5.6.5 TECHNICAL — the engineer’s version#

  1. One modelling option is a versioned crosswalk from (source_system, source_record_id) to an internal canonical ID, accompanied by a decision identifier and status. It preserves both source identity and the receiving system’s interpretation.
  2. Specify whether one source may map to several canonical entities. A bundled product might require a decomposition relationship rather than an ordinary identity mapping. Do not force a many-part relationship into a false “same thing” assertion.
  3. Distinguish effective time from recording time when needed. A decision can be recorded today while correcting a grouping used for an earlier period. Adding two timestamp columns alone does not implement a complete bitemporal system.
  4. Review reference redirection. A merged ID might become an alias rather than vanish; a split can make an old alias ambiguous. Returning an explicit unresolved or retired state can be safer than guessing a destination.
  5. Rebuildable projections should depend on named mapping versions or retain sufficient lineage to determine which outputs need reconsideration. A current dashboard and an archived decision report need not use the same grouping policy.
  6. Retention changes the evidence available for reversal. If original attributes or mapping history are removed, a later repair may no longer be reproducible. Document that limitation rather than promising perfect reversibility forever.
  7. The companion lab demonstrates two immutable mapping snapshots and verifies that changing the current grouping does not mutate the earlier snapshot. It does not implement a complete production merge workflow, cascading database migration or person-identity system.
  8. The lesson is architectural: identity decisions deserve explicit state, provenance and failure handling. They are not harmless string replacements.

5.6.6 WORDS — remember these#

  1. Canonical ID: the receiving system’s chosen reference; technically, an identifier used for the entity representation treated as the current reference under a stated mapping policy.

  1. Crosswalk: a mapping between identifier systems; technically, a relation connecting scoped source identifiers with identifiers in another model.

  1. Merge decision: an explicit association of records; technically, a versioned decision to treat selected representations as referring to one entity under stated evidence and rules.

  1. Split: revising an association into distinct entities; technically, a correction of mapping relationships whose downstream effects may require separate repair.

  1. Identity history: the record of how associations changed; technically, retained versions or events describing identifier mappings and their applicable decision boundaries.

5.97 Practice and worked answers#

First predict the result#

  1. Two catalogue rows both have display name “Notebook.” Does that prove one is a duplicate? What evidence is missing?
  2. SUP-A and SUP-B both issue code 017. Propose a source-reference key and explain why a generated receiving-row ID solves a different problem.
  3. A receipt join uses only local receipt number 17 and omits branch. Describe a possible wrong result using the two-branch fixture.
  4. E-700 arrives twice with the same validated content; E-701 arrives once with identical business fields. How many logical events should our proposed consumer apply?
  5. Recalculate precision, recall and false-positive rate for 8 true matches accepted, 2 true matches missed, 3 different pairs accepted and 87 different pairs rejected.
  6. After M-02 separates SRC-B-88 from CAN-10, which statements can be made about the current grouping, the old grouping and reports previously exported under M-01?

Worked answers#

  1. No. A shared display name does not establish shared identity. Check product definitions, issuing identifiers, pack sizes, source provenance and the domain’s equivalence rule. Keep an uncertain result when evidence is insufficient.
  2. Use (supplier_id, supplier_code) under the stated supplier-code lifecycle. The generated receiving ID identifies the receiving row; the scoped pair recognises the source reference. Neither alone proves that two supplier references describe the same product.
  3. BR-A’s detail could be paired with BR-B’s header, or a report could multiply the joined rows. Include the branch scope in the relationship and verify the resulting grain.
  4. Apply E-700 once and E-701 once: two logical events. The second delivery of E-700 is a replay, while E-701 has a distinct producer identity. A changed payload under E-700 is a conflict, not a third ordinary event.
  5. Precision is 8/(8+3) ≈ 72.7%; recall is 8/(8+2) = 80%; false-positive rate is 3/(3+87) ≈ 3.33%. Each uses a different denominator. These are fixture-level evaluation results, not individual-match probabilities.
  6. The current mapping places SRC-B-88 in CAN-12. The retained M-01 snapshot still records the former association. Previously exported reports require a separate dependency and correction review; they are not automatically repaired by changing the current mapping.

5.98 Common wrong ideas#

  1. Wrong: equal names mean the same entity. Right: names can be shared, changed or incomplete.
  2. Wrong: a generated key prevents duplicate business records. Right: it can give two duplicate business records two different IDs.
  3. Wrong: a UUID cannot collide. Right: random-collision models assign a small probability under assumptions; implementation and reuse failures remain separate risks.
  4. Wrong: an identity column is automatically unique. Right: generation and uniqueness enforcement are separate in PostgreSQL’s documented model.
  5. Wrong: an ID needs no context. Right: scope and lifecycle determine where its uniqueness claim applies.
  6. Wrong: knowing the full key grants access. Right: identification and authorisation are separate decisions.
  7. Wrong: identical contents always indicate a replay. Right: two real events can have identical business fields and distinct identities.
  8. Wrong: a matching score is automatically a probability. Right: its interpretation requires calibration and validation appropriate to the intended population.
  9. Wrong: merging records makes the source facts agree. Right: a merge is a decision about interpretation; contradictory source claims can remain.
  10. Wrong: undoing a merge repairs every consequence. Right: downstream reports, exports and actions need their own correction process.

5.99 Chapter summary in 20 lines#

  1. An entity, its record, its display name and its identifier are different things.
  2. Stable references depend on an explicit identity and lifecycle policy.
  3. A primary key identifies a row within the relevant table’s rules.
  4. Natural keys come from domain attributes; surrogate keys are introduced for record identity.
  5. Generated keys do not replace relevant business uniqueness constraints.
  6. PostgreSQL identity columns need separate primary-key or unique enforcement for uniqueness.
  7. UUID version 4 has 122 random bits within its 128-bit layout.
  8. Collision arithmetic is conditional on correct independent uniform generation.
  9. A namespace supplies the context required to interpret a local identifier.
  10. A composite key keeps all necessary identifying components together.
  11. Dropping scope in a join, cache key or message can select the wrong record.
  12. Identification never substitutes for authorisation.
  13. One event can have several delivery attempts.
  14. Two distinct events can carry the same business contents.
  15. Our consumer distinguishes accepted events, same-content duplicates and identity conflicts.
  16. Deduplication guarantees depend on coordinated updates and retention boundaries.
  17. Entity resolution evaluates uncertain references rather than merely comparing keys.
  18. Matching precision and recall describe different denominators and are not measurement precision.
  19. Versioned mappings preserve the distinction between source records and identity decisions.
  20. A merge or split needs provenance, explicit invariants and review of downstream effects.

Return to contents