Connect HubSpot to Snowflake
Why teams connect HubSpot and Snowflake
HubSpot is where marketing and sales work. Snowflake is where the company answers questions about revenue. Getting HubSpot data into the warehouse usually means a managed pipeline you cannot see into, a nightly job that is hours stale, or an export someone runs by hand.
- Contacts, companies, deals, and engagements land in Snowflake within minutes, not on a nightly cycle
- Every load is a run you can inspect, so a row that looks wrong in a dashboard can be traced to the exact sync that wrote it
- Deleted and merged HubSpot records are handled as soft deletes, so history is not silently rewritten
- Model output, a fit score or a churn segment, is written back to HubSpot on a schedule, so the same numbers show up for reps
Worked example
The load flow most teams turn on first.
HubSpot contacts and deals into RAW.HUBSPOT.*, within a polling interval
Change-driven, with a scheduled full reconcile so nothing drifts.
- Trigger: HubSpot
New or updated contactandNew or updated dealtriggers, polled on the schedule you set; each delivers the changed record. - Shape: flatten the HubSpot
propertiesobject to typed columns using the map below, keeping the raw JSON in a_rawcolumn. - Merge:
Execute Snowflake SQLwithMERGE INTO RAW.HUBSPOT.CONTACT t USING (SELECT ...) s ON t.HS_OBJECT_ID = s.HS_OBJECT_ID. - Associations: upsert contact-to-company and contact-to-deal links into a
CONTACT_ASSOCIATIONtable. - Nightly reconcile: a scheduled flow pages the full HubSpot list and merges it, catching anything a poll missed.
Field mapping
The starting map for the HubSpot contact to RAW.HUBSPOT.CONTACT step.
| HubSpot property | Snowflake column | Notes |
|---|---|---|
hs_object_id | HS_OBJECT_ID NUMBER | Match key for the merge. |
email | EMAIL VARCHAR | Lowercased on write. Not unique in HubSpot, do not use as a key. |
lifecyclestage | LIFECYCLE_STAGE VARCHAR | Enum value, kept as text. |
hs_lead_status | LEAD_STATUS VARCHAR | |
createdate | CREATED_AT TIMESTAMP_NTZ | HubSpot sends epoch milliseconds, cast on write. |
lastmodifieddate | UPDATED_AT TIMESTAMP_NTZ | Also used as the watermark for reconcile. |
hubspot_owner_id | OWNER_ID NUMBER | Join to an OWNER dimension, not resolved inline. |
properties (full object) | _RAW VARIANT | Keep the whole payload so a new property does not need a backfill. |
| (derived) | IS_DELETED BOOLEAN | Set by the delete and merge flow, default FALSE. |
What syncs, each direction
- Core objects. Contacts, companies, deals, tickets, and their property history land as typed tables plus a raw VARIANT column. (HubSpot to Snowflake)
- Engagements. Meetings, calls, emails, notes, and tasks recorded in the CRM load into an engagements table for activity reporting. (HubSpot to Snowflake)
- Scores and segments. A model table of fit scores, churn risk, or account tier is written back to HubSpot custom properties on a schedule. (Snowflake to HubSpot)
- Suppression and enrichment. Do-not-contact lists and firmographic fields computed in the warehouse update the matching HubSpot records. (Snowflake to HubSpot)
Governance and audit
The same controls apply to this sync as to every other Neblex workload.
- Run history. Every load is a run with the batch, the merge statement, and row counts. A failed run can be replayed from the step that failed.
- Approval on write-back. Reverse-ETL flows that change HubSpot data can include a Wait for form step, so a person reviews the changes before they are written.
- Scoped access. HubSpot uses a private app token limited to the needed scopes. Snowflake uses a role with grants on the target schema only.
- Environments. Build against a HubSpot test account and a Snowflake scratch schema, then promote the same flow to production.
Frequently asked questions
How fresh is the data in Snowflake?
Change-driven loads land within one polling interval of the HubSpot change. A nightly reconcile catches anything a poll missed.
Do we get history, or just the current state?
Both. The current-state tables are merged in place, and property-change events are appended to a history table so you can reconstruct a record at a point in time.
What happens when a HubSpot contact is merged or deleted?
The delete and merge flow marks the losing record IS_DELETED = TRUE and records the surviving ID, rather than removing the row.
Can we write model output back to HubSpot?
Yes. A scheduled flow reads a model table in Snowflake and updates HubSpot custom properties, with an optional approval step before the write.
Is this different from HubSpot's own data-sync or a managed pipeline?
Managed pipelines are a fine choice if you only need tables in a warehouse on a schedule and never need to see inside a load. This is for teams that also want short polling intervals, a readable run history, write-back, and the same governance as the rest of their integrations.
Connectors used
HubSpot
CRM & Sales
- Operations
- 336
- Operations with typed output
- 81.5%
- Change triggers
- 46 (poll)
- Signs in with
- API token
Snowflake
Databases & Data Warehouses
- Operations
- 7
- Operations with typed output
- 85.7%
- Change triggers
- Poll or inbound webhook
- Signs in with
- Connection details
Bring one real integration
We will build it with you against your own systems, with the run log open.