HubSpot + Snowflake integration
Snowflake holds the accounts, usage and revenue a seller cannot see. HubSpot's own share moves data out, and the return trip is where the work sits.
Native app- Into HubSpot
- Out of HubSpot
Is there a native Snowflake + HubSpot integration?
Yes, and HubSpot builds it. HubSpot publishes Snowflake Data Share in the HubSpot App Marketplace as of September 2026, and it sends HubSpot data one way into Snowflake for querying. Coming back the other way is the harder half: a beta direct sync on Data Hub Enterprise maps tables onto objects and their associations, and anything needing timeline events, write-back or per-record rules is a 70 to 150 hour build.
- Recommended route
- Custom middleware
- Build effort
- 70 to 150 hours
- In the HubSpot App Marketplace?
- Yes, Snowflake Data Share by HubSpot
- Typical elapsed time
- 4 to 8 weeks
Marketplace checked September 2026.
Why teams connect Snowflake to HubSpot
A warehouse team and a revenue team usually meet over the same complaint from opposite directions. The warehouse holds the truth about accounts, usage and revenue, and nobody in sales can see it without asking. Sales holds the truth about who said what and when, and nobody in analytics can join it to anything without an export. Both teams have been promised a single view for years.
The outbound half of that is solved and costs nothing to run. HubSpot’s own Snowflake share puts CRM data in the warehouse for querying, which answers the analyst’s question and none of the seller’s. What a seller needs instead is the account’s health score on the company record, the open renewal as a deal, and a workflow that raises a task when usage drops.
That is the inbound half, and it is where the work is. Warehouse rows have to land on the right HubSpot record without creating duplicates, associate to records that may not exist yet, and repeat every hour without eating the portal’s request budget. None of it is difficult, but all of it is exacting, and a scheduled table load leaves that part to you.
The decision worth making early is which fields the warehouse owns. A property written by a pipeline should be read-only for humans in the CRM, and a property humans edit should never be in the pipeline’s mapping. Where both sides write the same field, the sync becomes an argument that runs hourly.
What syncs
Four inbound streams cover most of what revenue teams ask for. Accounts become companies, keyed on the warehouse account identifier held in a unique HubSpot property. Users or contacts become contacts, keyed on a source identifier with email only as a tie breaker. Subscriptions or orders become deals, one way. Usage and health metrics become numeric properties on the company, rather than a custom object, because properties are what workflows and lists can act on.
Product events are the fifth, and they are different in kind. They belong on the timeline as custom behavioural events, deduplicated against a ledger of what has already been sent, and they count against the account’s monthly event allowance, so the pipeline filters to events a human would care about.
In the other direction, the HubSpot tables inside the share are read only. They are excellent for joining CRM history to warehouse facts, and they are not a write path.
| | | Direction | Match key | Notes |
|---|---|---|---|---|
| Account table | Company | Into HubSpot | Account identifier in a custom HubSpot property | The warehouse account identifier, never the company domain. |
| User or contact table | Contact | Into HubSpot | Source contact identifier, with email as a tie breaker | |
| Subscription or order table | Deal | Into HubSpot | Source order identifier | One way. The warehouse stays the system of record for revenue. |
| Usage or health metric view | Company | Into HubSpot | Account identifier, written to numeric company properties | Properties, not a custom object, so workflows can read them. |
| Product event table | Engagement | Into HubSpot | Event identifier, recorded in a sent ledger | Custom behavioural events, capped by the account's monthly limit. |
| HubSpot object tables in the share | Deal | Out of HubSpot | HubSpot record identifier, carried by the share | Read only inside Snowflake. Nothing written there reaches the CRM. |
Architecture
The shape is polling on a watermark. A scheduled job asks the warehouse for rows changed since a stored position, either by reading a stream or by filtering on a modified timestamp, then batches the results into HubSpot upserts of a hundred records, then runs associations as a separate pass once the parents exist.
State lives in two places. The watermark, which says where each stream has read up to, and a ledger of what was sent, which makes a replay idempotent rather than duplicative. Both sit in the warehouse, because that is the platform the data team already backs up and monitors.
Failures are expected rather than exceptional. A batch that fails goes to a dead letter table with its payload and the API response, an operations endpoint replays a window on demand, and a reconciliation step compares row counts on both sides after each run and alerts when they disagree.
-
Warehouse
-
Snowflake Accounts, usage and revenue
- Watermark and sent ledger Kept in the warehouse
-
-
Sync job
- Scheduled job Reads rows changed since the watermark
- Batched upserts A hundred records at a time
- Associations pass Once the parent records exist
- Reconciliation Row counts compared after each run
-
CRM
-
HubSpot Companies, contacts, deals, events
-
What the API allows
- API style
- SQL database
- Authentication
- OAuth 2.0
- Webhooks
- No
- Changed-since filter
- Yes
- Sandbox
- Yes
- Rate limit
- Not documented
Developer documentation docs.snowflake.com
Three ways to connect
Start with the mapping, not the tool. A table or view that maps straight onto HubSpot objects, even several of them with associations defined in the mapping, is what HubSpot’s beta direct sync covers on Data Hub Enterprise, and buying a build for that is waste. Add a rule that decides which rows qualify, and the direct sync, which cannot filter, needs warehouse views that exist only to feed it. Add timeline events or a write-back, and it is out of the picture.
Volume decides as much as shape does. Tens of thousands of changed rows an hour is comfortable for any route. Millions is a conversation about batching and about the daily request budget, which every private app in the account shares, while the 10 second burst limit is counted per app.
Ownership is the part people forget. A reverse ETL subscription needs an owner as much as a service does, and it bills by the row while it waits.
-
Custom middleware
RecommendedA keyed service reads changed rows on a stream or a watermark, batches upserts into HubSpot, runs associations as a separate pass, and applies the per-record rules a scheduled table sync cannot.
-
Native app
PossibleHubSpot's outbound share plus its beta Snowflake direct sync cover a lot on Data Hub Enterprise: a table or view mapped onto one or more objects, with associations defined in the mapping, on a schedule. It applies no per-record rules and sends nothing back out of HubSpot.
-
Automation platform
PossibleA reverse ETL product does the same scheduled load with no build and bills per synced row, which suits a stable mapping and gets expensive as the warehouse grows.
What breaks and how we prevent it
Stream offsets and failed pushes
Streams surprise people. A stream’s offset only advances when a transaction consumes it, so a job that reads the stream in a plain query and then crashes before writing has not lost anything, while a job that consumes it inside a transaction and then fails to reach HubSpot has. We consume into a staging table first, then push from the staging table, so the two failures are independent.
A daily budget shared across private apps
HubSpot counts the burst limit per app and the daily limit per account. A private app on Professional or Enterprise gets 190 requests per 10 seconds, and the daily total, 625,000 requests on Professional and 1,000,000 on Enterprise, is shared by every private app in the account. A marketplace app is held to 110 requests per 10 seconds in each account that installs it. A warehouse backfill will take that budget from the rest of the business unless it is throttled deliberately and scheduled outside business hours.
Deleted rows a timestamp read misses
Deletes vanish quietly. A row removed from a table is invisible to a timestamp-based read, so the record stays in HubSpot forever. Either use a stream, which records deletes, or reconcile counts and flag the difference for a human decision, because deleting CRM records automatically is rarely what anyone wants.
Warehouse values that do not fit
Type mismatches are the last one. A warehouse number with more precision than a HubSpot property accepts, a date without a time zone, an enumerated value that does not match a dropdown. We map every field to a HubSpot type during discovery and send anything that does not fit to a conflict table rather than dropping it.
Our approach
- Scope. We profile the tables, count changed rows per day, and check each one for a stream or a reliable modified timestamp.
- Architect. We agree which side owns each field, the unique identifier property on each object, and where the watermark and ledger will live.
- Build. A scheduled job with batched upserts, a separate associations pass, a dead letter table and a replay endpoint.
- Validate. A full load into a HubSpot sandbox portal from a warehouse clone, with counts compared object by object.
- Operate. Reconciliation after every run, alerts on a count difference, and a quarterly review of the mapping as warehouse models change.
Common questions
Is there a HubSpot app for Snowflake?
Yes. HubSpot publishes Snowflake Data Share itself, and it is listed in the HubSpot App Marketplace alongside third-party reverse ETL apps that appear in the same search. Installing the share needs a Data Hub Enterprise subscription and either super admin rights or app marketplace permissions in the portal.
Which direction does the HubSpot Snowflake Data Share move data?
Out of HubSpot and into Snowflake, and only that way. It puts your HubSpot data in your Snowflake account for querying beside everything else you hold there. Nothing you write in Snowflake travels back through the share, so reporting is what it is for, and operational sync is not.
Can Snowflake push a change to HubSpot the moment a row lands?
No. Snowflake's webhook notifications go to a fixed set of destinations, Slack, Microsoft Teams, PagerDuty, Jira and ServiceNow, and there is no row-level event feed to an arbitrary endpoint. Anything reaching HubSpot is pulled on a schedule, either by reading a stream or by filtering on a modified timestamp.
How do we load Snowflake rows into HubSpot without creating duplicates?
Upsert on a unique identifier property that holds the warehouse key, in batches of a hundred, then run associations as a separate pass once the parent records exist. Matching on email or company name looks fine on the first load and produces duplicates on the second, when somebody in the warehouse corrects a name.
What does the Snowflake direct sync beta not cover?
It runs one way, from a table or view into HubSpot objects on a schedule, and one table can feed several objects with associations defined in the mapping, up to 10 GB, 200 columns and 30 million records a run, in create and update, create only or update only mode. It cannot filter rows, apply per-record business rules, write timeline events, or carry anything back out of HubSpot. It also needs Data Hub Enterprise.
Do we need Data Hub Enterprise to query HubSpot data in Snowflake?
Yes for the share itself, which HubSpot documents as a Data Hub Enterprise feature, and an account with HIPAA enabled needs a Snowflake Business Critical account on the other side. Below that tier the routes into a warehouse are an export, a third-party pipeline, or a service that reads the CRM API on a schedule.
How do we test a Snowflake to HubSpot sync before it touches production?
Against a separate database or schema in the warehouse and a HubSpot sandbox portal, with the production cutover being a credential swap and nothing else. Snowflake also offers a free trial account for 30 days, which is enough to prove the shape of a pipeline when a second environment is not available yet.
How does a Snowflake sync know which rows changed?
Either a stream, which records inserts, updates and deletes against an offset and only advances when a transaction consumes it, or a modified timestamp column read against a stored watermark. Streams are stronger because they catch deletes. Watermarks are simpler and survive a pipeline being rebuilt from scratch.
Also in Data and sync platforms
Related reading
Partnerships and accreditations
HubSpot accreditations
Industry specializations
Partnerships
Scope a Snowflake integration
Send the systems, the direction and the record volume. We reply with a scope and an effort band within one business day.
Thanks, we will reply within one business day
Prash or Sean reads every one of these and comes back with a scope, or with the one question we need answered first.
Where these facts come from
- Snowflake SQL API docs.snowflake.com
- Introduction to streams docs.snowflake.com
- Sending webhook notifications docs.snowflake.com
- Trial accounts docs.snowflake.com
- Connect HubSpot and Snowflake Data Share knowledge.hubspot.com
- Sync Snowflake data to HubSpot knowledge.hubspot.com
- API usage guidelines and limits developers.hubspot.com