Salesforce to PostgreSQL: How to Replicate Your Data

Replicate Salesforce into PostgreSQL with Airbyte. Why syncs end early reporting success, tuning the lookback window, and the formula field trap.

Summarize with AI:

Replicating Salesforce to PostgreSQL is the pipeline where a green sync does not mean a finished sync, and understanding that one behaviour will save you more time than anything else in this guide.

Salesforce enforces a daily API request limit on your org. When the Airbyte connector reaches it, it does not fail. It ends the sync early, reports success, and starts the next sync from where it stopped. That is sensible behaviour, and it has one condition attached: resuming from where it left off only works for incremental sync. Run this connector in full refresh against a large org and every sync will truncate somewhere arbitrary and start over from the beginning next time, forever.

CapabilitySupportedWhat it means for this pipeline
Daily API limitHandledThe sync ends early reporting success, then resumes next run
Resuming a partial syncIncremental onlyAppend and Deduped is effectively required on large orgs
Deleted recordsOn supported streamsRecycle bin records arrive marked with isDeleted true
Formula fieldsOutputs onlyA changed formula needs a stream reset and a backfill
Bulk API null handlingConfigurableLiteral NA and N/A become null unless you preserve them

Pick the sync mode first, not last

Incremental Sync with Append and Deduped is the recommended mode for this connector, and the rate limit behaviour is why. It also solves a second problem you will meet regardless: the lookback window.

Salesforce's API is eventually consistent, so a record modified moments before a sync may not appear in the results for that sync. The connector compensates by re-reading a short window behind the last cursor position. The default is ten minutes, expressed as an ISO 8601 duration, and if you see records missing in PostgreSQL the first thing to try is raising it to thirty minutes or an hour. Because deduplication happens on the way in, re-reading overlapping data does not produce duplicate rows in the destination. Without dedupe, that same overlap becomes duplicate records you have to clean up downstream.

Formula fields drift silently

The connector syncs the output of a formula field, not the formula itself. That is the right choice, and it has a consequence worth writing down somewhere your admins will see it.

If someone edits the formula in Salesforce and nothing else on the record changes, the record's modification timestamp does not move. Incremental sync therefore never sees it, and PostgreSQL keeps serving values calculated under the old formula, indefinitely, with no error anywhere. The fix is manual: reset the stream and run a historical backfill. The prevention is procedural: whoever owns Salesforce admin needs to know that changing a formula means telling the data team.

Bulk API, REST API, and the NA problem

Salesforce allows extraction through either the Bulk API or the REST API, and the choice has a side effect that catches people. Bulk API results are delivered as CSV, and CSV has no way to distinguish an empty cell from the literal string it contains. By default the connector treats values like NA, N/A, NULL, None and NaN as null.

For most orgs that is what you want. If your data legitimately contains those strings, a country code, a status value, a category someone named NA years ago, enable the option to preserve them. It applies only to Bulk API streams, since REST-synced streams keep the values as they are. Also worth knowing: deleted records can be retrieved from the recycle bin on streams that support it, arriving with isDeleted set to true rather than disappearing, which means your PostgreSQL tables can reflect deletions if you filter on that column downstream.

Frequently asked questions

Why did my Salesforce sync report success but move less data than expected?

It almost certainly hit your org's daily API limit. The connector stops there, reports success, and resumes from that point on the next run. On incremental sync this is fine and self-correcting.

Records are missing from PostgreSQL. What should I change?

Increase the lookback window from the ten minute default to thirty minutes or an hour. Salesforce's API is eventually consistent and a longer window catches records that were not visible when the sync ran.

Why are my formula field values out of date?

The formula changed but the records did not, so incremental sync never re-read them. Reset the stream and run a historical backfill to pull the recalculated values.

My NA values turned into nulls. Can I stop that?

Yes. Enable the option to preserve NA and similar string values. It affects Bulk API streams only, because REST-synced streams already keep them.

Get your Salesforce data into PostgreSQL

Three decisions carry this pipeline. Use incremental append and deduped so partial syncs resume. Tune the lookback window when records go missing rather than assuming the connector is broken. And write down somewhere visible that changing a Salesforce formula requires a stream reset, because nothing in the system will tell you.

For the same destination fed by an API you configure yourself, see REST API to PostgreSQL. For the equivalent pipeline out of Microsoft's CRM stack, which uses genuine change tracking rather than a timestamp cursor, see Microsoft Dataverse to BigQuery.

Start syncing now →

Integrate with 600+ apps using Airbyte

Move data from 600+ sources into warehouses, lakes, and beyond. Set up pipelines in minutes with pre-built connectors and the Connector Builder.