All insights
Engineering·July 28, 2025·8 min

CRM integrations break in the same five places

CRM integration projects tend to get scoped as a data mapping exercise: this field goes to that field, this event triggers that update. On the whiteboard it's clean. In production it breaks in the same handful of places almost every time, regardless of which CRM is involved, because the failure modes come from how real businesses actually use these systems, not from the specific vendor.

The five recurring breakpoints

  • Duplicate records: the same contact created through two channels with slightly different data, and no clean merge key.
  • Field mismatches that only appear at scale: a picklist value that exists in one system and not the other, working fine until the first exception hits it.
  • Sync direction conflicts: two systems both trying to be the source of truth for the same field, overwriting each other in a loop.
  • Rate limits and webhooks that silently drop under load, so a burst of activity means quietly missing updates, not an obvious error.
  • Ownership drift: a custom field or workflow inside the CRM changes and nobody tells the team that built the integration.

What makes these five so consistent across different projects is that none of them are really CRM problems. They're distributed systems problems wearing a CRM costume. Any two systems that both hold a copy of the same data and both allow that data to change independently will eventually disagree, and the CRM's picklists and webhooks are just the specific surface where that disagreement becomes visible.

Design for the sync to be wrong sometimes

The mistake in most integration builds is designing for the happy path and treating failures as exceptions instead of an expected part of the system. A resilient integration assumes sync will occasionally fail, and is built to detect that and recover rather than to prevent it entirely, which isn't achievable in a system with two independently-changing sources of truth. That means idempotent writes, so replaying an event twice doesn't create a duplicate, a dead-letter queue for records that fail to sync so they're visible instead of silently dropped, and a daily reconciliation job that diffs both systems and flags drift.

Idempotency is worth dwelling on because it's the one piece most homegrown integrations get wrong first. If a webhook fires twice for the same event, which happens more often than most people expect, an integration that isn't idempotent will process it twice: two contact records, two deal updates, a duplicated calendar invite. The fix is straightforward, key every write off a stable identifier and check whether it's already been applied before applying it again, but it has to be designed in from the start. Retrofitting idempotency onto a system that's already live and already has duplicate data is a much bigger job than building it in on day one.

The question isn't whether the sync will ever be wrong. It's how fast you find out, and how easy it is to fix once you do.

One source of truth per field, always

The single decision that prevents the most pain is assigning exactly one system as the source of truth for each field before you write any sync logic. Lead status might live in the CRM, order history might live in the storefront, and both systems read the other's data but only one ever writes it. Skipping this decision is the single most common cause of the update loops and overwritten data we get called in to fix.

This decision is also the one most likely to get skipped, because it's an organizational question disguised as a technical one. Sales wants lead status editable from the CRM. Ops wants shipping status editable from the fulfillment system. Both are reasonable, but if both systems can write the same field, the sync has no way to know which write is authoritative when they disagree. Getting the relevant teams to agree on ownership before the integration is built is unglamorous, slow, and the single highest-leverage hour you'll spend on the whole project.

Build the reconciliation job before you need it

Even a well-designed integration drifts over time, because business processes change, someone adds a new picklist value, someone bulk-edits records outside the normal flow. A scheduled job that compares both systems and reports what doesn't match, run weekly at minimum, is what turns 'we think the sync is working' into 'we know exactly where it isn't.' Most teams only build this after the first bad incident. Building it before the first incident is cheap insurance that pays for itself the first time it catches something quietly wrong before a customer does.

Test with production-shaped data, not clean sample data

Integration testing done against a handful of tidy, hand-picked test records almost never surfaces the bugs that show up in production, because real CRM data is messy in ways that are hard to imagine in advance: contacts with no email, deals with negative amounts from a refund process nobody documented, custom fields left blank for years and then suddenly required. Pulling a sanitized export of real production data, stripped of anything sensitive, and testing the integration against that instead of synthetic records catches a category of bug that clean test data structurally cannot reveal, simply because real businesses are messier than anyone designing a test set from scratch tends to assume.

Engineering

Got a workflow like this?

Tell us what's eating your team's time, we'll tell you honestly whether automation is worth it.

Book a Consultation

We typically respond within 24 hours