# Preventing Duplicates at Registration

**URL:** <https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821>\
**Category:** Community\
**Tags:** patient-duplicates, patient-merge\
**Created:** [April 11, 2025, 7:13am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821 "2025-04-11T07:13:31Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![veronica](https://talk.openmrs.org/user_avatar/talk.openmrs.org/veronica/32/20174_2.png) [@veronica](https://talk.openmrs.org/u/veronica)\
**Post date:** [April 11, 2025, 7:13am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/1 "2025-04-11T07:13:31Z")

</div>

Hello OpenMRS Community,

We’re working on implementing the “ **Prevent Duplicates at Registration** ” feature and would greatly appreciate your review and input on our current requirements and approach.

- [Prevent Duplicates at Registration](https://openmrs.atlassian.net/wiki/spaces/projects/pages/392691733/Prevent+Duplicates+at+Registration)

- [Prevent Duplicates at Registration Mockups](https://docs.google.com/presentation/d/1duFitDOpXFwE91NjvCD7pyZ4iXlUmt1ANDPPx6a1xps/edit#slide=id.g3408cb26eef_0_0)

## Current Requirements Overview

We’ve outlined requirements for preventing duplicate patient registrations based on our analysis, but we want to ensure we’re addressing the full scope of the challenge. Our current approach includes:

1. **Patient Search Enhancement** : Improving the search functionality to identify potential matches before new registrations are created
2. **Match Criteria Configuration** : Allowing the implementation to configure which demographic fields should trigger duplicate detection
3. **Review & Resolution Process** : Creating a workflow for reviewing and resolving potential duplicates

## Key Questions for the First Iteration

1. **Required Fields** : Currently considering name, gender, birth date and address as matching criteria. Are there other identifiers that have proven critical in your implementation?
2. **Cultural Considerations** : How can we account for naming variations across different cultures and regions? (e.g., name order, spelling variations, shortened names)
3. **Performance Impact** : Has anyone experienced significant performance issues with duplicate checking at registration?
4. **User Experience** : What has been most effective in your experience for presenting potential duplicates to users during registration?
5. **False Positives/Negatives** : What strategies have you employed to minimize false positives while still catching potential duplicates?

## Implementation Considerations

We would love to hear about your experiences, challenges, and any lessons learned.

## Timeline and Next Steps

We aim to finalize the requirements in the next **two weeks**. Your inputs would be incredibly valuable in shaping this work.

Thank you for your insights and continued support of the OpenMRS Community!

---

<div class="post-metadata">

**Author:** ![ibacher](https://talk.openmrs.org/user_avatar/talk.openmrs.org/ibacher/32/19751_2.png) [@ibacher](https://talk.openmrs.org/u/ibacher)\
**Post date:** [April 11, 2025, 1:02pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/2 "2025-04-11T13:02:14Z")

</div>

Before we go too deep into thinking about and creating requirements, have we assessed the “find similar patients” feature from the O2 RefApp and whether that’s a style / pattern we want to adopt?

---

<div class="post-metadata">

**Author:** ![veronica](https://talk.openmrs.org/user_avatar/talk.openmrs.org/veronica/32/20174_2.png) [@veronica](https://talk.openmrs.org/u/veronica)\
**Post date:** [April 11, 2025, 4:46pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/3 "2025-04-11T16:46:01Z")

</div>

Is it possible to include that feature in 03 or is there a reason why we don’t have it in 03?

---

<div class="post-metadata">

**Author:** ![dkayiwa](https://talk.openmrs.org/user_avatar/talk.openmrs.org/dkayiwa/32/179_2.png) [@dkayiwa](https://talk.openmrs.org/u/dkayiwa)\
**Post date:** [April 13, 2025, 8:10pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/4 "2025-04-13T20:10:59Z")

</div>

We also have it in the legacy ui (O1) 😃

---

<div class="post-metadata">

**Author:** ![kmuiruri](https://talk.openmrs.org/letter_avatar/kmuiruri/32/5_5575768a8748004e209b776fc1b2916d.png) [@kmuiruri](https://talk.openmrs.org/u/kmuiruri)\
**Post date:** [April 14, 2025, 8:10am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/5 "2025-04-14T08:10:35Z")

</div>

This used to work very well. Can we have it introduced in O3?

---

<div class="post-metadata">

**Author:** ![veronica](https://talk.openmrs.org/user_avatar/talk.openmrs.org/veronica/32/20174_2.png) [@veronica](https://talk.openmrs.org/u/veronica)\
**Post date:** [April 14, 2025, 10:30am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/6 "2025-04-14T10:30:17Z")

</div>

Oooh wow, let’s then talk about re-introducing it in O3 @dkayiwa @ibacher

---

<div class="post-metadata">

**Author:** ![grace](https://talk.openmrs.org/user_avatar/talk.openmrs.org/grace/32/16942_2.png) [@grace](https://talk.openmrs.org/u/grace)\
**Post date:** [April 15, 2025, 5:44pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/7 "2025-04-15T17:44:05Z")

</div>

> [@ibacher](#):
>
> Before we go too deep into thinking about and creating requirements, have we assessed the “find similar patients” feature from the O2 RefApp and whether that’s a style / pattern we want to adopt?

> [@dkayiwa](#):
>
> We also have it in the legacy ui (O1) 😃

Thanks both; yes, we have reviewed these. Screenshots and details that were obvious in the UI were captured in the wiki page. This Monday we also had a great session with PIH folks (Fiona, Dave, Mark, Mike) about this and they shared in great detail the UI and algorithm nuances they’ve been running into:

## Notes from Monday Session, 2025-04-14: BA & Dev Feasibility Meeting: Review of Existing PIH Algorithm & UI

@anon54923432 @veronica @grace @fanderson @ddesimone @mseaton @mogoodrich

_**Summary: Timing of this project is great because at same time PIH has been noticing they still have many duplicate patients being created, despite the O2 UI and algorithm. They think it’s a multi-factor problem, with UI and with the weights in the algorithm. Open to alternative algorithm approaches too. Next steps plan: (1) All agreed UI should have Interstitial page for Registration clerks; @veronica to work on that and re-present. (2) To find out if DIGI or other community members know of alternative logic approach.**_

- There is a means for configuring on the backend: APIs in backend allow for finding similar pts; 2 diff algorithms: **“Fast Search”** (run during workflow), and **“Precise Search”** (run at end of workflow, when user completes registration).
  - Fast Search occurs while _each_ field in Registration Form is completed. Seems performant, including with implementations with 100,000’s of patients.
  - Don’t have to use 2 algorithms; could just point to 1.
  - **Main Code location with Algorithm weights and explanations:** [openmrs-module-pihcore/api/src/main/java/org/openmrs/module/pihcore/search/PihPatientSearchAlgorithm.java at ab62accffc8fe6eb434b3b22e1eaaef07e3178c3 · PIH/openmrs-module-pihcore · GitHub](https://github.com/PIH/openmrs-module-pihcore/blob/ab62accffc8fe6eb434b3b22e1eaaef07e3178c3/api/src/main/java/org/openmrs/module/pihcore/search/PihPatientSearchAlgorithm.java#L33)
  - Data received from API call: The patient, the Match Quality (weighted score), and matched fields. In UI: ordering of the matches is based on the weighted score.

- Configured in Global Properties re. Which algorithm (fast or slow) you want to use. Rwanda and Haiti systems are configured this way.
- Includes phonetic name search: [Github Repo](https://github.com/openmrs/openmrs-module-namephonetics/tree/master/api/src/main/java/org/openmrs/module/namephonetics/phoneticsalgorithm). Specifically uses “Double Metaphone” approach. Does double-metaphone matches on first and last name (as starting point, for base cohort)
- PIH implementations also specificaly include considerations cor Chichewa and Kinyarwanda (eg r’s and l’s swapped in Rwanda).
- Main considerations from @mseaton:
  - Don’t want to have to have custom module; likely want added into Registration module and supported via Iniz.
  - Vision: Every single time a field is changed, javascript would hit this endpoint.

- Review of Current Algorithm: **Score/Points-Based.** Assigns score: Higher score —\> more likely match. Points weights are manually configured; last adjusted ~10-15 yrs ago at PIH.
- this is what is built into registrationcore: [openmrs-module-registrationcore/api/src/main/java/org/openmrs/module/registrationcore/api/search at master · openmrs/openmrs-module-registrationcore · GitHub](https://github.com/openmrs/openmrs-module-registrationcore/tree/master/api/src/main/java/org/openmrs/module/registrationcore/api/search) (the classes in the above folder are pretty readable. it should be pretty clear what they are doing by default).
- Points for address matching: In implementation-specific logic, includes nuanced address field matching (e.g. in Haiti, “cell”, “commune”…) but we could adjust generic one (and include config docs if ppl want to adjust for their implementation)
- @ddesimone did a review a few days ago of real patients’ results and their “possible match” scores. Findings: scores \>20ish were definitely matches; under 10 low/no-value

Next steps plan: (1) All agreed UI should have Interstitial page for Registration clerks; @veronica to work on that and re-present. (2) To find out if DIGI or other community members know of alternative logic approach.

---

<div class="post-metadata">

**Author:** ![grace](https://talk.openmrs.org/user_avatar/talk.openmrs.org/grace/32/16942_2.png) [@grace](https://talk.openmrs.org/u/grace)\
**Post date:** [April 15, 2025, 5:51pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/8 "2025-04-15T17:51:36Z")

</div>

@ibacher @caseynth2 @reagan @pmanko & DIGI team members: I know you have a lot of experience with patient matching challenges because of DIGI’s work with HIEs and MPIs / Patient Registries.

Based on your experience, would you recommend we carry on with a simple weighting/points/score-based algorithm for duplicate detection in the Registration Clerk’s workflow? Or is there a different approach you suggest?

(Keeping in mind IMHO we want to keep this relatively simple so it can be easy to maintain and configurable by implementation, such as in the example PIH has where they added weights for some locations’ township names etc.).

---

<div class="post-metadata">

**Author:** ![ibacher](https://talk.openmrs.org/user_avatar/talk.openmrs.org/ibacher/32/19751_2.png) [@ibacher](https://talk.openmrs.org/u/ibacher)\
**Post date:** [April 15, 2025, 6:05pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/9 "2025-04-15T18:05:34Z")

</div>

> [@grace](#):
>
> a simple weighting/points/score-based algorithm for duplicate detection in the Registration Clerk’s workflow?

What you’ve described above qualifies as fairly sophisticated. It would be better to have a pluggable and configurable algorithm to do the matching (double metaphone is fine, but focused on US pronunciation and useless with non-Latin alphabets), but the goal here is quickly surfacing possible matches more so than some perfect algorithm.

---

<div class="post-metadata">

**Author:** ![veronica](https://talk.openmrs.org/user_avatar/talk.openmrs.org/veronica/32/20174_2.png) [@veronica](https://talk.openmrs.org/u/veronica)\
**Post date:** [April 23, 2025, 9:43am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/10 "2025-04-23T09:43:37Z")

</div>

“As @grace mentioned, one of the suggestions that emerged during the design session was to introduce an interstitial page to manage potential duplicate patients. I’ve put together two mock-ups for your review and feedback.” All ideas are welcome. cc: @cduffy @pauladams @ibacher

 ![image](https://talk.openmrs.org/uploads/default/original/3X/c/a/ca3fc2d2b58478da14142d9a6b7cbbb8d28d7063.png)

 ![image](https://talk.openmrs.org/uploads/default/original/3X/9/7/97bbd0329b5761be4d721465e311f4cce32ae327.png)

---

<div class="post-metadata">

**Author:** ![veronica](https://talk.openmrs.org/user_avatar/talk.openmrs.org/veronica/32/20174_2.png) [@veronica](https://talk.openmrs.org/u/veronica)\
**Post date:** [October 9, 2026, 6:36am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/11 "2026-10-09T06:36:07Z")

</div>

Hello all, we would like to revive this conversation with the goal to address duplicates identification gaps in O3. Please chime in and share your inputs to help us move this work forward ([prevent-duplicates-mockup](https://openmrs-prevent-duplicates.surge.sh/#duplicate-check)).

## 1. The problem

- **Duplicates put patients at risk.** When one person ends up with two records, their history is split, and a clinician looking at one file can miss allergies, results or past visits.
- **Most duplicates aren’t exact copies.** They come from small differences at registration: a typo, swapped first and last names, a guessed age, or a name spelt another way (for example “Okonkwo” / “Kwonko”).
- **O3 has no protection at registration.** O2 shows possible duplicates while a clerk types a name, with an option to review them - O3 doesn’t.

## 2. The proposed feature

Built on ideas from **PIH, KenyaEMR and AMPATH** , and reworked after feedback from the O3 squad call. The feature checks for duplicates **at registration**.

1. **A live alert, mid-form.** As soon as the name, sex and date of birth are entered, an alert appears right below them, listing the patients who may already be registered, closest match first. The clerk never has to leave the form.
2. **It stays in sight.** When the clerk scrolls further down the form, the alert collapses to a slim bar pinned at the top: “3 possible duplicates found · Review matches”.
3. **Review the matches.** The clerk can open a review page showing each match as a familiar patient banner: what matched (name, sex, date of birth), the last visit, and contact details on request.
  - **If one of them is the patient,** the clerk selects them and their existing record opens. Nothing new is created.
  - **If not,** the clerk goes **Back to form** (at the top of the list, so there’s no scrolling past every match). Nothing is ever created from the review page.

4. **A final safety check.** If an _exact_ match exists (same name, sex and date of birth), registering asks the clerk to confirm. For each identical patient the dialog shows ID, age, phone, address, relationships and last visit, with an **Open this record** option.

**Not in scope:** editing an existing patient and merging records. The squad agreed merging is a separate project.

## 3. Design principles

- **The system never chooses for the clerk.** Nothing is pre-selected.
- **Generous while typing, strict at the moment of saving.**
- **Nothing is created from the review page.** Registering always happens from the form, where the details can be completed.
- **The clerk never loses their work.** Going back from any step keeps everything typed.

## 4. Why the server can’t do this yet

OpenMRS already has matching logic in three places, but O3 can’t use any of it today:

| Existing feature | What it does | Why it doesn’t solve this |
| --- | --- | --- |
| **Core’s “find duplicate patients” report** | Lists records that are exact copies of each other across the whole database | Built for clean-up, not registration. It can’t check the person being typed in. |
| **O2’s similar-patient check** (core’s sound-alike search) | Finds similar-sounding names while registering | O3 has no way to call it. It only handles English names well, and it appears to have a birth-year bug. |
| **Registration Core module** | The strongest matching, with scores and the details that matched | Its API is switched off on current OpenMRS versions, and the module isn’t part of O3. |

Even when switched on, the server’s default matching only catches near-identical records:

| A clerk enters… | Today’s OpenMRS server | Proposed feature |
| --- | --- | --- |
| **Swapped names:** “Okonkwo Betty” | ✗ Misses Betty Okonkwo | ✓ Same name, wrong order |
| **A typo:** “Konkwo” | ✗ Names must start the same way | ✓ Catches close spellings |
| **An estimated age:** “34” | ✗ Date of birth must be within 2 weeks | ✓ Matches within ±2 years |
| **Unknown sex** | ✗ Rules the patient out | ✓ Still shown as a possible match |
| **A non-English name:** “فاطمة حسن” | ✗ Sound-alike matching is designed for English | ✓ Compares names in any script |
| **How strong is the match?** | ✗ Can’t say | ✓ Shows it: “Name”, “Name ≈”, “Age ±2” |

## 5. What’s next

1. **A stopgap:** for now the matching runs in the clerk’s browser. It works, but on large databases it can miss duplicates, and it handles more patient data in the browser than it should.
2. **Move matching to the server, building on Registration Core** (the same backend O2 uses), as agreed on the squad call.
3. **Make the matching work across cultures:**
  - Soundex-style sound-alike matching varies by culture, so it should be configurable per site.
  - Variant spellings such as “Muhammad / Mohammed / Mohamed” must be handled (an ICRC use case).
  - An exact match on a national ID should count for far more than any sound-alike name match.

4. **Performance isn’t expected to be a problem.** O2 already looks up matches live as the clerk types.
5. **Merging duplicates** will be a separate project.

## 6. Asks for the community

- **Name variants:** which spellings or naming patterns should matching handle in your context?
- **National IDs:** which IDs do your sites capture at registration, and should a match on one always be treated as near-certain?
- **Registration Core:** should it ship with O3 by default, or be an opt-in module?
- **The prototype:** please try it and share feedback: [prevent-duplicates-mockup](https://openmrs-prevent-duplicates.surge.sh/#duplicate-check)

Thanks to @ibacher @burke @dennis @dkayiwa @fanderson @jayasanka @jonathan and the entire community for the feedback on the squad call. Please share your feedback via this talk post to help us continue iterating.

---

<div class="post-metadata">

**Author:** ![jayasanka](https://talk.openmrs.org/user_avatar/talk.openmrs.org/jayasanka/32/22204_2.png) [@jayasanka](https://talk.openmrs.org/u/jayasanka)\
**Post date:** [October 9, 2026, 7:09am UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/12 "2026-10-09T07:09:26Z")

</div>

This is awesome progress @veronica! 🔥

@jofrancisco I know this is something ICRC has been looking forward to. Would love to hear your thoughts!

---

<div class="post-metadata">

**Author:** ![ibacher](https://talk.openmrs.org/user_avatar/talk.openmrs.org/ibacher/32/19751_2.png) [@ibacher](https://talk.openmrs.org/u/ibacher)\
**Post date:** [October 9, 2026, 3:33pm UTC](https://talk.openmrs.org/t/preventing-duplicates-at-registration/45821/13 "2026-10-09T15:33:50Z")

</div>

> [@veronica](#):
>
> - should it ship with O3 by default

I think this becomes part of the RefApp. Implementations, of course, will be able to opt-out, but this is the mechanism through which we can allow implementations to create their own custom matching rules.
