Integration guides
How do I sync data between two apps without creating duplicates?
Flow Mesh · · 6 min read
You connect your form to your CRM, or your CRM to your accounting package, and within a month the same client exists three times. One record has a typo, one has a different email, and one was created twice in the same minute. Reports stop adding up and someone spends Friday merging records by hand.
The short answer: duplicates almost never come from a bug in the tools. They come from an automation that creates a record without first checking whether it already exists, or that checks using a field that is not truly unique. The fix is a small set of design rules: pick one reliable key, search before you create, store each system's ID in the other, stop two-way syncs from echoing, and make retries safe. None of them needs a developer.
Why syncs create duplicates
Most duplicates trace back to one of five causes:
- A plain "create" step. The automation adds a new record every time it runs, with no lookup first.
- Matching on a weak field. "Smith & Co", "Smith and Co" and "Smith & Co Ltd" are three different values to a computer, so a name search misses the existing record.
- The same event arriving twice. Two automations listen to the same form, or the same webhook fires twice, and both runs search before either has written anything. Both find nothing and both create.
- Two-way sync echoing. App A updates App B, App B reports the change back as new, and App A treats it as fresh input.
- Retries after a partial failure. A step that created the record succeeded, a later step failed, and the rerun creates the record again.
Each one has a specific fix.
Fix 1: choose one unique key per record type
Before building anything, decide which field identifies a record. Good keys are values that never change and never repeat: an email address for a person, a client or matter number, a tax or company registration number, or a system ID. Names are poor keys. Phone numbers are risky because people share office lines.
Check what each app already treats as unique, because it will enforce that rule whether you plan for it or not:
- HubSpot deduplicates contacts by email and companies by domain, according to its knowledge base. It also lets you mark a custom text or number property as requiring unique values, but only when the property is created, and up to ten per object, according to its property validation guide.
- QuickBooks Online requires a customer display name to be unique across customers, vendors and employees, according to Intuit's Customer API documentation, so a second create with the same name fails with an error rather than a duplicate.
If two apps disagree on what is unique (one is keyed on people, the other on companies), write down which record in one maps to which record in the other. That mapping decision is covered in our guide on integrating a CRM with accounting software.
Fix 2: search before you create
Every step that creates a record should be preceded by a search on your unique key. Then branch: if found, update it; if not found, create it.
- In Zapier, many apps offer a search action with a "create if not found" option, which Zapier describes as a hybrid search and write step in its guide to search steps. Where an app has no such option, add a search, then a filter or paths step that only creates when the search found nothing.
- In Make, the usual pattern is a search module followed by a router: one route updates the record found, the other creates a new one. Some app modules offer an upsert (update or insert) directly.
- In n8n or custom code, the same logic applies; many APIs offer an upsert by a unique field.
Normalize the key before searching. Trim spaces and lowercase email addresses, and strip formatting from registration numbers. A search for "Jane@Firm.com " will not find "jane@firm.com", and the automation will happily create a second record.
Also decide what happens when the search returns more than one match. Stopping the run and alerting someone is usually safer than picking the first result and updating the wrong client.
Fix 3: store each system's ID in the other
Searching by email or name works for the first match. After that, the most reliable link is the record's ID. When your automation creates a customer in the accounting system, write the new accounting ID back into a field on the CRM record. Every later step (an invoice, a payment update, a name change) looks up by that stored ID instead of searching again.
This also protects you when someone changes the email address or the company name. The ID never changes, so the link survives.
Fix 4: stop two-way syncs from echoing
Two-way sync is where duplicates and overwrite loops multiply. Most apps cannot tell an edit made by a person from an edit made by your integration, so every write can bounce back as a "new" change.
Practical guards:
- Prefer one-way flows. Decide which app owns each record and which fields, and sync from owner to copy. Use two-way only for fields both teams genuinely edit.
- Tag your own writes. Add a field such as "Last updated by sync" and have the automation ignore changes where that field shows it made the change itself.
- Filter on what changed. Trigger only when a field you care about changes, not on any update to the record.
- Never let two tools write the same record. If a native connector already creates customers, your Zapier or Make automation should only look them up.
Fix 5: make reruns and retries safe
Automation platforms retry failed runs, and you will sometimes replay a run by hand. Make, for example, reruns an incomplete execution starting from the module that caused the error, according to its help center on automatic retries. Zapier lets you replay failed runs too.
That is helpful as long as every create step is protected by Fix 2. A rerun then finds the record that the first attempt already created and updates it instead of adding another. Steps that cannot be undone, such as sending an email or creating an invoice, deserve an extra check: store a "sent" flag or the invoice number on the source record, and skip the step if it is already set.
On the trigger side, Zapier's polling triggers only run for item IDs they have not seen before, which it calls deduplication; for actions, the outcome depends on the app, which may create a duplicate, return an error or update the existing record, according to Zapier's help center. So do not rely on the platform to protect your action steps for you.
Clean up what is already there
New rules do not fix old duplicates. Before switching on a sync:
- Export the records from both apps into one spreadsheet.
- Match them on your chosen key and merge duplicates in each app, using its built-in merge where it has one.
- Fill in the key field on every active record, so the first search has something to find.
- Write the matching IDs into both systems.
- Run the automation on a handful of test records and check exactly what was created and updated.
If duplicates keep appearing after launch, check the run history for the same trigger firing twice, and look for a second automation listening to the same event. Our article on why Zapier automations keep breaking covers the other usual suspects.
How Flow Mesh helps
Our stack audit reviews the apps you sync and the automations between them, gives each tool a verdict (keep, configure, consolidate or replace), and sets out in writing which system owns each record and how records are matched. If you want the fixes built, the integration work is scoped and quoted in writing after the audit and done inside your own accounts.
Key takeaways
- Duplicates come from creating without checking, weak matching fields, double triggers, echoing two-way syncs and unsafe retries.
- Pick one unique, unchanging key per record type and normalize it before every search.
- Search before every create, and store each system's ID in the other once the link exists.
- Prefer one-way flows, and never let two tools write the same record.
- Merge existing duplicates and fill in the key field before the first sync.