A property manager banks a rent check at a branch on Friday afternoon. The tenant’s bookkeeper, not knowing it was already taken in, photographs the same piece of paper on Monday and deposits it through a phone app. Two capture events, two image files, one instrument — and, unless something catches it, two debits against the same account.

The two files share nothing at the byte level. One is a duplex scan from a branch capture unit under even light. The other is a handheld photograph with perspective skew, a shadow across the endorsement and a crop that clipped the bottom edge. Any hash over the pixels reports them as unrelated documents, because in every sense that a hash understands, they are.

This is the part that makes duplicate detection on checks a different problem from duplicate detection on files. The thing being repeated is not the document. It is the instrument the document depicts. The pipeline has to decide that two dissimilar images describe the same claim on the same account — and it has to do that without flagging the fifty legitimately similar checks that arrive in the same batch.

Two images of one check are never the same file

The instinct to hash the image is a good instinct applied to the wrong layer. Content hashing is exact, cheap and completely reliable for detecting a re-submitted file — the same PDF uploaded twice, the same scan replayed by a retrying client. Those cases are real and worth catching, and a content hash catches them perfectly.

It catches nothing else. Recapture the same paper and every input to the hash changes: resolution, compression, colour balance, rotation, the exact pixel where the page begins. Two captures of one check are, to a hash function, two documents. Perceptual hashing narrows the gap but does not close it honestly, because the distance threshold that tolerates a phone photograph of a check also tolerates a photograph of a different check from the same pre-printed stock. Tighten it and mobile deposits stop matching; loosen it and every check from the same business starts matching.

So image similarity is the wrong primary key, for a reason that has nothing to do with model quality. The instrument has an identity printed on it, and that identity is what the banking system already uses.

Two checks with the same data are not the same check

The opposite instinct fails in the opposite direction. Match on payer, amount and date and a recurring payment becomes a duplicate: the same tenant, the same landlord, the same rent, the first of every month. Match on payer and amount alone and a company paying two identical invoices in one week gets one of them held.

These are not edge cases. Fixed, repeating amounts from the same account are the ordinary shape of rent, subscription, retainer and payroll payments, and a control that treats repetition as suspicion will spend its whole life holding legitimate money. A false positive here is not a logged warning — it is funds withheld from someone who is owed them, and an exception a person has to work.

What distinguishes two rent checks from one rent check deposited twice is not the payer, the amount or the date. It is the serial number, which is unique per instrument by design, and which is printed in the MICR line at the bottom of the page precisely so that it can be read by machine.

What the MICR line actually keys

The MICR line is a magnetic-ink strip at the foot of the check carrying the fields the clearing system routes on. It is the closest thing a check has to a primary key, but it is a composite one, and treating it as a single opaque string discards most of its value.

MICR fieldWhat it identifiesWhy it matters to a duplicate check
Routing numberThe paying financial institution.Scopes the account. Two checks from different institutions are never the same instrument, whatever else matches.
Account numberThe account the funds leave.Narrows the comparison set to one payer, which is what makes serial comparison meaningful.
Serial numberThe individual instrument.The discriminator. Same account and same serial is one check; same account and different serial is two.
Amount fieldThe value, encoded after presentment.Corroborates rather than identifies. It is absent on a check that has not been processed yet, so a key that requires it fails on first capture.

Two properties of that table decide the design. The serial number carries the identity, and the amount field cannot be relied on to exist. A duplicate control keyed on the whole MICR string as one token will therefore behave inconsistently between a first deposit and a re-presentment, for a reason that looks like a model failure and is not.

The MICR line also has to be read as characters, not inferred. It is printed in E-13B or CMC-7 type and it is often the most degraded region on a handheld capture, because it sits at the page edge where the crop is worst. The check OCR API documents the field set and the confidence model; the point for a duplicate control is that a low-confidence serial is not a serial, and a pipeline that silently accepts one has converted a read failure into a match failure.

The key, and the window it lives in

A workable duplicate key is a composite of the fields that identify the instrument, evaluated inside a time window, with the fields that merely describe the payment kept out of the key and used to rank review instead.

  • Routing plus account plus serial — the identity triple. All three read at usable confidence, or the item does not have a key and has to be routed on its read quality rather than on its match result.
  • A bounded window — serial numbers are reused when a payer exhausts a check book, so an unbounded lookback eventually matches a legitimate check against a years-old one. The window is a business decision about presentment practice, and it belongs in configuration, not in the matcher.
  • Amount as corroboration — a match on the identity triple where the amounts disagree is more interesting than one where they agree, not less. It may be an altered instrument, and it should never be silently merged.
  • Channel recorded, never keyed — branch, mobile, lockbox and ATM capture the same instrument differently. Knowing which channel produced each side of a match is what lets a reviewer read the pair; keying on it would split the very pair you are trying to find.

The window is where most of the tuning sits, and it is worth resisting the urge to tune it globally. A commercial account issuing sequential checks daily and a consumer account writing twelve a year have different reuse horizons, and a single number chosen for the fleet will be wrong for both.

The image is corroboration, not the detector

None of this makes the image useless. It relocates it. Image comparison is poor at deciding whether two captures are the same instrument and good at helping a person confirm it once the data has proposed the pair — which is the opposite of how it is usually wired.

Once the identity triple has matched, the two images become the evidence a reviewer reads: the same handwriting slope, the same signature, the same memo line, the same fold. A reviewer settles that pair in seconds. Asking the same reviewer to find the pair among four thousand items is the task that does not scale, and it is the task the key exists to remove.

The image also carries the one signal the MICR line cannot: whether the instrument has already been through a deposit. An endorsement on the reverse, a bank stamp, a “for mobile deposit only” restriction written across the back — these are visible on the page and absent from the data. They will not tell you which prior deposit, and they do not belong in the key for that reason. They tell you that a prior deposit exists, which is enough to route the item to review rather than to settlement.

Why this is a money question

The reason this control is worth building carefully is that the loss does not necessarily land where the mistake happened. Under Regulation CC, a bank that accepts a check deposited electronically and never receives the original paper item gives an indemnity to a depositary bank that later accepts that original and takes a loss because the check had already been paid — 12 CFR § 229.34(f), the remote deposit capture indemnity.

That is a narrow allocation rule about two banks, and it is not advice about any particular deposit. What it establishes is the shape of the risk: the double presentment that a duplicate control is looking for is one the rules already anticipate and already assign a cost to. Detection at capture is cheap. Detection after settlement is a claim between institutions, worked by people, against a document nobody indexed.

What the extraction has to return

A duplicate control is only as good as what the extraction hands it, and the difference between a usable payload and a lossy one is mostly about what was kept separate.

  • MICR as parsed fields — routing, account, serial and amount returned individually, each with its own confidence, never concatenated into one string the consumer has to re-split.
  • Read confidence per field — so the pipeline can distinguish “these differ” from “one of these was not legible”, which are opposite conclusions that an unqualified value collapses into one.
  • Both amounts, unreconciled — the courtesy amount in figures and the legal amount in words, kept apart and both reported, because their disagreement is itself the finding.
  • Endorsement state from the reverse — described as what was read on the page, with its region, rather than asserted as a deposit history the document cannot prove.
  • Capture provenance — channel, device and capture time, labelled with where each came from, so a matched pair can be explained rather than merely reported.

Each of those values should point back at the region of the image that produced it. A duplicate match that a person cannot audit is a match a person cannot release funds against, and releasing funds is the whole point of the control.

What a duplicate control is not

Three neighbouring problems get folded into this one, and each has a different answer.

It is not a fraud model. A duplicate deposit is usually an accident — two people in the same office, a retrying client, a bookkeeper who did not check. Nothing about the instrument is forged, which is what separates this from synthetic and manipulated documents; AI-generated document fraud is a problem about whether the page is genuine, and here the page is entirely genuine and simply arrived twice.

It is not a blocklist. A repeat-applicant blocklist keys on a party across unrelated submissions and needs expiry policy, an appeal path and a false-positive budget, because it decides how to treat a person. A duplicate check control keys on an instrument within one payment stream and decides whether two records describe one event. Same machinery, different subject, and conflating them produces a control that punishes a payer for the operations of their bookkeeper.

It is not statement reconciliation either. Matching a deposit against a categorized bank statement line happens after clearing and answers a different question: whether the ledger agrees with the bank. The duplicate control runs before that, on the images, and its job is to stop the second debit from existing.

The match is a claim about two documents

The useful reframing is that a duplicate detection is not a flag. It is an assertion that two specific captures depict one instrument, and like any assertion in a document pipeline it is worth exactly as much as the evidence attached to it.

That is why the key is built from the fields the instrument was issued with rather than from the picture, why the amount corroborates instead of identifies, and why the images come back at review time rather than at match time. Built that way, the control catches the Friday branch deposit and the Monday phone deposit, leaves twelve months of identical rent checks alone, and hands a person a pair they can settle by looking at it. Built the other way — on image similarity, or on payer and amount — it does one of those three things and fails the other two.