Sync Salesforce to Snowflake
Land Salesforce accounts, opportunities, and custom objects in Snowflake on the next poll of a change using Change Data Capture, model them next to the rest of your data, and write scores and segments back to Salesforce, with every load recorded as an ordered run you can replay.
Why teams connect Salesforce and Snowflake
Salesforce is where the pipeline lives. Snowflake is where the company measures it against everything else: product usage, billing, support, marketing spend. Getting Salesforce into the warehouse usually means a managed connector you cannot see into, a nightly job that is hours stale, or a bulk export someone schedules and forgets.
- Accounts, opportunities, and custom objects land in Snowflake on the next poll using Salesforce Change Data Capture, not on a nightly cycle
- Every load is an ordered run log, so a number that looks off in a board can be traced to the exact sync and row that wrote it
- Deleted and merged Salesforce records become soft deletes, so a historical report does not silently change
- Model output, a fit score or a health segment, is written back to Salesforce on a schedule so reps see the same number as the analyst
Worked example
The load flow most teams turn on first.
Salesforce Opportunity changes into ANALYTICS.CRM.OPPORTUNITY, streamed
Change-driven through CDC, with a scheduled full reconcile so nothing drifts.
- Trigger: Salesforce
New or updated recordonOpportunityvia Change Data Capture, batched every 10 seconds. - Shape: map the CDC payload to the target column names and types using the table below, keeping the full change event in a
_RAWcolumn. - Stage: for a batch above 5,000 rows, write to a stage and
COPY INTOa scratch table. Below that, pass rows straight to the merge. - Merge:
MERGE INTO ANALYTICS.CRM.OPPORTUNITY t USING :batch s ON t.ID = s.ID, update on match, insert when not matched. - Deletes: a
Deleted recordevent setsIS_DELETED = TRUEandDELETED_AT = CURRENT_TIMESTAMP()rather than removing the row. - Watermark: write the max
SystemModstampseen to a control table, so a replay knows where to resume. - Nightly reconcile: a scheduled flow runs a bounded SOQL query and merges the result, catching anything a gap in the CDC stream dropped.
Field mapping
The starting map for the Opportunity to ANALYTICS.CRM.OPPORTUNITY step.
| Salesforce field | Snowflake column | Notes |
|---|---|---|
Id | ID VARCHAR | Match key for the merge. The 18-character ID. |
AccountId | ACCOUNT_ID VARCHAR | Foreign key to ANALYTICS.CRM.ACCOUNT, not resolved inline. |
Name | NAME VARCHAR | |
StageName | STAGE VARCHAR | Enum value kept as text. Join to a stage dimension for order and probability. |
Amount | AMOUNT NUMBER(18,2) | Record-currency amount. See CURRENCY_ISO_CODE. |
CurrencyIsoCode | CURRENCY_ISO_CODE VARCHAR | Only present if multi-currency is on. Keep a AMOUNT_USD derived column for reporting. |
CloseDate | CLOSE_DATE DATE | Date, not timestamp. |
SystemModstamp | SYSTEM_MODSTAMP TIMESTAMP_NTZ | Watermark for reconcile. UTC. |
OwnerId | OWNER_ID VARCHAR | Join to a user dimension, not resolved inline. |
| (full CDC event) | _RAW VARIANT | Keep the whole payload so a new field does not need a backfill. |
| (derived) | IS_DELETED BOOLEAN | Set by the delete and merge flow, default FALSE. |
What syncs, each direction
- Core and custom objects. Account, Contact, Opportunity, Lead, Case, and any custom object land as typed tables plus a raw VARIANT column. (Salesforce to Snowflake)
- Field history and activity. Field history, tasks, events, and email activity stream into event tables for stage-velocity and activity modeling. (Salesforce to Snowflake)
- Scores and segments. A model table of account fit, health, or propensity is written back to Salesforce custom fields on a schedule. (Snowflake to Salesforce)
- Enrichment and hygiene. Firmographic fields, deduped account hierarchies, and do-not-contact flags computed in the warehouse update the matching Salesforce records. (Snowflake to Salesforce)
Governance and audit
The same controls apply to this sync as to every other Neblex workload.
- Ordered run log. Every load is an event log with the batch, the merge statement, and row counts. Replay a run without re-reading from Salesforce.
- Approval on write-back. Reverse-ETL flows that change Salesforce data can pause for review before the first run of a changed mapping.
- Scoped access. Salesforce uses a connected app and a permission set limited to the synced objects. Snowflake uses a role with grants on the target schema only.
- Environments. Build against a Salesforce sandbox and a Snowflake scratch schema, then promote the same flow to production.
Frequently asked questions
How fresh is the data in Snowflake?
CDC-driven loads land on the next poll to a minute of the Salesforce change. A nightly reconcile catches anything a gap in the CDC stream dropped.
What if an object does not support Change Data Capture?
The connector falls back to a scheduled query on that object's SystemModstamp, so the table still stays current, just on the schedule you set.
Do we get history, or just current state?
Both. Current-state tables are merged in place, and the raw change events are appended to a history table so a record can be reconstructed at a point in time.
What happens when a Salesforce record is merged or deleted?
The delete and merge flow sets IS_DELETED = TRUE and records the surviving ID for a merge, rather than removing the row.
Is this different from Salesforce's own connector or a managed pipeline?
Managed pipelines are fine if you only need scheduled tables and never need to see inside a load. This is for teams that also want streamed changes, a readable run log, write-back, and the same governance as their other integrations.
Connectors on this page
Salesforce
CRM
- Operations
- 1,296
- Typed outputs
- 57.9%
- Change triggers
- 95 (poll)
- Authentication
- OAuth2
Snowflake
Snowflake
- Operations
- 7
- Typed outputs
- 85.7%
- Change triggers
- Poll or inbound webhook
- Authentication
- ConnectionString
Bring one real integration
We will build it with you against your own systems, with the run log open.