Phase two of the job fair website: the registration flow from phase one was running smoothly, so this round was about resumes.
What the Duplicates Looked Like
A single event brought in over 2,000 submissions. Digging through the data we found several kinds of duplicates:
- The same person applied to 3 positions, filling the form 3 times, with the same phone number.
- Someone uploaded a PDF, then a revised version half an hour later — both files in the system.
- And a batch with identical names but different phone numbers — genuinely different people.
Deduplicating by name alone would have been a disaster. The primary key we settled on: phone number plus email. Only when both are empty do we fall back to name plus school, and even then the record is flagged "needs manual review", never auto-merged.
How Files Were Consolidated
Resume files are hashed by content with SHA-1; identical hashes store one copy, with all submission records pointing to it. Different versions of a PDF don't overwrite each other — sorted by upload time, the latest shows by default in the backend, older versions collapsed below, one click away for HR.
Our first version deleted old versions outright. HR stopped us: in interviews candidates get asked "how did you phrase it in your previous version?" So we kept them — they hardly take any space.
The Manual Review Queue
What the system can judge, it merges automatically; what it can't goes into a review table: same phone but different email, same email but different phone, name plus school colliding while contact details don't match. That round left 40-plus rows; HR cleared them in two days.
The backend has a "merge" button: before merging, both records display side by side, and which one survived, which got archived, and who did it all go to the log. No auto-merge — when this kind of thing goes wrong, it's hard to trace.
How HR Cleared Those 40+ Rows
The most time-consuming category was "same phone, different email" — 19 rows. Some had switched company emails, some had entered a spouse's, and two were the same person deliberately applying to two different positions, hoping the duplicate wouldn't be noticed. HR didn't merge those; they flagged them "one candidate, multiple applications", notified for both interviews, but counted one resume.
The "same name and school, contact details don't match" category had 8 rows — ultimately 3 groups of genuinely different people sharing a name and school, plus 2 rows of one person who'd changed phone numbers. Automated judgment is least reliable here, which is why it never auto-merges: it only sorts and shows records side by side.
The merge log earned its keep once. A candidate claimed a submission was missing; the log showed HR had merged records the week before, and both pre-merge records were still in the archive — found in one click. Had we hard-deleted, there'd have been no explaining it.
That Bit of Storage
Some worried old PDFs would eat storage. We ran the numbers: 2,000-plus submissions, fewer than 200 duplicate versions, averaging 300 KB each — under 60 MB total. Compared with being able to pull up a previous version during an interview, that's nothing. SHA-1 dedup only blocks byte-identical files; a version changed by one character still gets its own copy. That's exactly what we wanted.
The Phone Number Column
Setting the phone column to text format in exports only made it into the template after we got burned twice. The first time, HR dialed a number that had become 1.38E+10. The second was sneakier: all 11 digits ended in zeros because Excel stores only 15 significant digits. After switching to text, the third export template never produced such a complaint again.
One column, "Source Channel", was later added to those 9 — a request from the client's marketing team. The export script barely changed, just one more field. The 40-plus-row review table was exported and archived once HR finished, with "verified" in the filename, and no scenario requiring auto-merge ever appeared again.
The Export
Exports split by position into separate sheets, one position per sheet, a fixed 9 columns each: name, phone, email, school, degree, position applied, resume version, submission time, status. Each HR contact gets their own pages instead of scrolling through 2,000 rows.
One detail: the phone column must be text-formatted, or Excel renders 11-digit numbers in scientific notation and HR has to fix them one by one before dialing. We've stepped on that rake more than once.
March 7
On launch day we imported historical data, and the preview flagged 6 rows with "all contact fields empty" — collected in the early days before validation existed. Fixed by hand.
The client later added a "filter by school" dropdown — a small change. Those 9 export columns haven't been touched since.

