Destination guide · PostgreSQL
Salesforce data in Postgres, without treating it like a nightly export.
The useful pattern is not “copy every CRM field somewhere.” It is a deliberately scoped application mirror: selected objects, a stable local schema, event-driven updates, and a recovery path when the happy path breaks.
Choose the data shape your application needs.
Start from the query your product cannot run reliably today. A support portal may need Account, Contact, Case, and a custom entitlement object. A billing service may need Opportunity, Contract, and product metadata. That is a much better starting point than “mirror the entire org.”
For every selected Salesforce object, define a local table name, primary key, the fields your application may read, and how deleted records should appear. Keep the Salesforce record ID in the local table. It makes upserts, traceability, and support conversations straightforward.
Do not quietly turn a CRM mirror into a new source of truth. A local schema can be optimized for your application, but the sync contract should make ownership, field mapping, and deletion behavior explicit.
Build a backfill-first, event-driven flow.
A reliable mirror has two jobs: create a complete initial state, then apply changes without losing its place. The initial job is a backfill; the continuous job is a Change Data Capture subscription.
- Backfill the selected objects. Read a consistent-enough initial copy in batches and write it with deterministic keys.
- Subscribe to Change Data Capture. Receive create, update, delete, and undelete events for the objects you explicitly enabled.
- Fetch or apply the authoritative change. Preserve the source record ID and use an idempotent database write so retries do not create duplicate rows.
- Checkpoint only after the transaction succeeds. The replay position should never move ahead of the local data it represents.
Design for a missed event before one happens.
CDC reduces normal latency; it does not remove failure modes. Processes restart, credentials rotate, schemas evolve, and a service can be down longer than an event-retention window. The operational answer is not blind trust—it is replay plus reconciliation.
Persist the last successfully committed replay position with the same durability as the row write. After a short interruption, resume from it. Separately, run a scheduled reconciliation that compares selected source records with the local copy and repairs drift. The reconciliation job is also where you surface mismatched field mappings, unexpected deletes, and source-permission changes.
Idempotency key: unique local identity anchored to the Salesforce record ID.
Checkpoint: advance it only after a committed Postgres write.
Dead-letter visibility: retain failed records and the error context for an operator to inspect.
Reconciliation: validate counts and fields on a schedule that matches the business risk.
Make the Postgres copy easy to use.
The mirror earns its keep when engineers can query it as ordinary application data. Use predictable schemas and explicit names, index the Salesforce ID, and add the indexes that match the product’s read patterns. Keep sync metadata—last source modification, sync timestamp, or deletion flag—separate from the business fields your app queries.
For example, an application table might hold salesforce_id, account_id, stage_name, amount, source_modified_at, and synced_at. The goal is not to expose every Salesforce implementation detail; it is to give local code a dependable relational boundary.
Implementation checklist
Define scope: objects, fields, deletion policy, and data owner for the first use case.
Use a least-privilege integration user: validate object and field access in a sandbox before production.
Choose write semantics: idempotent inserts/updates, clear transaction boundaries, and a durable replay store.
Plan observability: event lag, applied writes, failed records, reconciliation differences, and API headroom.
Test recovery: stop the worker, replay, and prove a reconciliation job finds deliberate drift.
Have a Postgres mirror to ship?
Bring the object list and the query your app needs to run. We’ll help validate the architecture before you wire another brittle job.