Snowflake
Snowflake is the supported way to import product usage from a data warehouse. Sonora reads a single table or view per product, joining it to your existing customers via an external ID column.
Authentication uses key-pair authentication. Sonora generates and holds the private key; you add the public key to a service user in your Snowflake account. The private key never leaves Sonora’s infrastructure.
What Sonora reads
Section titled “What Sonora reads”A Snowflake connection imports product usage only. Customer records have to come from a CRM connection (Salesforce or HubSpot) — Snowflake usage rows then match to those customers via an external ID column.
Sonora treats three columns as fixed metadata: account ID, date, and (optionally) product. Every other numeric column is imported as a usage metric.
If you need a starting point for shaping a usage table, the Product Usage Upload Template shows the expected layout.
Prerequisites
Section titled “Prerequisites”ACCOUNTADMINorSECURITYADMINprivileges in Snowflake (needed once, to provision the service role)- Network access from Sonora’s static IPs if your account uses a network policy
- A configured customer source in Sonora (Salesforce or HubSpot) to match account IDs against
1. Create the Sonora role and service user
Section titled “1. Create the Sonora role and service user”Run this in a Snowflake worksheet, replacing the database, schema, and table names with your own:
-- Read-only role for SonoraCREATE ROLE IF NOT EXISTS SONORA_SVC_ROLE;
-- Grants on the database and schemaGRANT USAGE ON DATABASE REPORTING TO ROLE SONORA_SVC_ROLE;GRANT USAGE ON SCHEMA REPORTING.ANALYTICS TO ROLE SONORA_SVC_ROLE;
-- Grants on each table you want importedGRANT SELECT ON TABLE REPORTING.ANALYTICS.USAGE_METRICS TO ROLE SONORA_SVC_ROLE;
-- Small dedicated warehouse keeps costs low and easy to attributeCREATE WAREHOUSE IF NOT EXISTS SONORA WAREHOUSE_SIZE = 'XSMALL' AUTO_SUSPEND = 60 AUTO_RESUME = TRUE;
GRANT USAGE ON WAREHOUSE SONORA TO ROLE SONORA_SVC_ROLE;
-- Service accountCREATE USER IF NOT EXISTS SONORA_SVC TYPE = SERVICE DEFAULT_ROLE = SONORA_SVC_ROLE DEFAULT_WAREHOUSE = SONORA;
GRANT ROLE SONORA_SVC_ROLE TO USER SONORA_SVC;2. Add Sonora’s public key to the service user
Section titled “2. Add Sonora’s public key to the service user”Your Sonora contact will provide a public key string. Apply it to SONORA_SVC:
ALTER USER SONORA_SVC SET RSA_PUBLIC_KEY = '<public key from Sonora>';3. Configure customer matching in Sonora
Section titled “3. Configure customer matching in Sonora”In Settings → Integrations → Snowflake → Configure, set the Customer External ID Source to whichever CRM owns the IDs in your Snowflake table:
salesforceorsalesforce_oauthif your table uses Salesforce Account IDshubspotif it uses HubSpot Company IDs
If this isn’t set, product usage imports will fail.
4. Share connection details
Section titled “4. Share connection details”Send your Sonora contact:
| Field | Example |
|---|---|
| Account | ACME-AB12345 (from your Snowflake URL) |
| User | SONORA_SVC |
| Role | SONORA_SVC_ROLE |
| Warehouse | SONORA |
| Database | REPORTING |
| Schema | ANALYTICS |
| Table | USAGE_METRICS |
Find the account identifier with SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT();, or look at your Snowflake URL: https://<account>.snowflakecomputing.com.
Troubleshooting
Section titled “Troubleshooting”“Invalid public key” — You probably introduced a line break or extra characters when copying. Re-copy the entire string from Sonora as-is.
“User does not have permission” — Run SHOW GRANTS TO ROLE SONORA_SVC_ROLE;. The role needs USAGE on the database, schema, and warehouse, plus SELECT on each table.
Connection timeout — Confirm the account identifier matches your Snowflake URL exactly. If a network policy is in place, allowlist the IPs from the IP allowlist page. Make sure AUTO_RESUME = TRUE on the warehouse.
Missing rows after sync — The most common cause is an external ID source that doesn’t match the IDs actually in your usage table. Check that the IDs in your table are the ones from the configured source, not a different identifier.