Zoho CRM and Postgres: one source of truth
A CRM is a good interface and a bad source of truth once three systems write to it. Why AINS syncs Zoho into one Postgres table with a dedup guard instead of pointing every automation straight at the CRM API.
- · updated
- 5 min
A CRM is a good interface. It is a bad source of truth once more than one system writes to it: a website form, a phone integration, a billing tool and a spreadsheet someone still edits by hand, each with its own idea of what counts as a duplicate.
Why AINS does not wire every automation to the CRM API
Point five automations at Zoho’s API directly and all five inherit Zoho’s rate limits, its outages and its definition of a record, each on its own and with no shared memory of what the others just did. One automation retries a failed write and creates a duplicate. Another reads a record mid-update and acts on stale data. Both come from the missing layer between the CRM and the systems that talk to it.
A queue or a cache is not enough
The usual instinct is to add a queue, a retry policy or a cache in front of the CRM API. That helps with rate limits. It does nothing for the real problem: five automations still disagree about what a duplicate is, unless something outside all five defines it once.
One Postgres table, one truth
AINS mirrors the CRM into a single Postgres table, on Supabase in most builds, that every automation reads and writes. Zoho stays the interface the sales team looks at, synced in both directions. The table is what every automation treats as the record of what is true. One dedup guard protects everything that touches it, instead of five guards with five sets of bugs.
A CRM API is not built to answer “how many leads came in this month by source” quickly at scale. A Postgres table built for that purpose is, and the KPI dashboard reads from it rather than from Zoho.
The dedup guard
The guard is an idempotency-key pattern. Every write carries a key that identifies the same underlying event across retries, so a webhook that fires twice, which is normal for most third-party providers, writes once. The pattern was hardened on FORMAFORCE’s stack, dozens of n8n workflows deep, across several duplication incidents.
What feeds the table
The bridge pulls from wherever data starts: the site’s lead forms, a Google Sheet someone still uses daily, Stripe or SumUp payment events and the CRM itself. It runs both ways. A lead from the site lands in Zoho with no re-typing, and an update made in Zoho flows back into the table.
Where this shows up in a build
The same CRM bridge handles the directions automations tend to forget: site and form leads landing in Zoho, invoice stamping and lead redistribution when someone leaves. The FORMAFORCE case study shows it in production, and the KPI dashboard page shows what reads from the table.
If a CRM is starting to disagree with itself across the systems that write to it, the CRM offer on the services page covers exactly this, and the n8n automation agency page explains how the flows around it are built.