This guide will show you how to securely connect Coalesce Quality to your Snowflake instance.
We need this information so we collect metadata about your tables.To be able to finish this guide, you’ll need the following:
→ Access to modify your Snowflake configuration as account admin⏱️ Estimated time to finish: 10 minutes.
→ Access to modify your Snowflake configuration as account admin⏱️ Estimated time to finish: 10 minutes.
Data we collect
We read metadata from your Snowflake account using the dedicated role described below. Depending on which features you enable in the integration, we ingest:- Catalog — databases, schemas, tables, views, materialized views, dynamic tables, semantic views, streams, comments, column types, tags.
- Stages (opt-in grant) —
SHOW STAGESfor each named stage the role can see: its type, URL, cloud, region and storage integration. With query logs enabled, theCOPY INTOstatements that load a table from a stage or unload one to it become lineage between the stage and the table. - Apps, notebooks, warehouses and pipes (opt-in) —
SHOW STREAMLITS,SHOW NOTEBOOKS,SHOW PIPES,SHOW CORTEX SEARCH SERVICESandSHOW WAREHOUSESfor each object the role can see: a Streamlit app’s title and warehouse, a notebook’s warehouses, a pipe’sCOPYstatement and the stage it loads from, a Cortex Search service’s query and warehouse, and a warehouse’s size, type and auto-suspend. - SQL definitions —
GET_DDLoutput for tables, views, materialized views, dynamic tables, semantic views, streams, stored procedures, and user-defined functions. Used for lineage and to detect references between objects. - Constraints — primary keys (via
SHOW PRIMARY KEYS) and clustering keys. Foreign keys, uniques, and checks are read fromGET_DDLwhen present. - Table metrics (opt-in) — row counts and last-modified timestamps for anomaly detection.
- Query logs (opt-in) —
SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORYfor performance, cost, and lineage signals. - Tasks (opt-in) —
SHOW TASKSplusTASK_HISTORYfor execution outcomes. - Stored procedures and UDFs —
SHOW PROCEDURES/SHOW USER FUNCTIONSplusGET_DDLfor SQL, JavaScript, Python, Java, and Scala languages (automatic when the role hasUSAGEon them). - Table-level lineage (opt-in) — via
SNOWFLAKE.CORE.GET_LINEAGEon Enterprise+ editions.
Metadata vs. data access. The baseline grants below give Coalesce Quality access to your schema and DDL, never to row data. The
SELECT privileges on tables/views/etc. are required so the role can call SHOW and GET_DDL (Snowflake gates object visibility behind any object privilege), but Coalesce Quality only issues data-reading queries when you enable the corresponding opt-in feature in the integration UI — Fetch table metrics, Fetch query logs, Fetch table lineage, or SQL test execution against the audit table. With every opt-in disabled, the integration runs metadata commands only.Before you execute your scripts you will need several key variables:
warehouse_name— the name of the warehouse you will create (e.g.SYNQ_WH)database_nameas an identifier of database (or multiple) you want to monitor
- It creates a dedicated
usernameandrolefor Coalesce Quality - It creates
xsmalldata warehouse that we can use to query your metadata - Grant necessary privileges to the dedicated user and role so we can pull query history and monitor the target database
Setup a user and warehouse
As a super user, execute the following SQL commands to create a read-only role, a user assigned to that role, and a warehouse for that role. We recommend creating a dedicated user name and warehouse.Key-pair authentication
For more details on Snowflake’s key-pair authentication, see the official Snowflake documentation.
- Managed Key-pair: The key pair is generated and managed for you
- User Managed Key-pair: You generate and provide your own private key (supports both encrypted and unencrypted keys)
Option A: Managed Key-pair
When configuring the integration, select “Managed Key-pair” and save it. Coalesce Quality then generates the key pair and shows the public half under Key pair authentication at the bottom of the integration’s page. Copy it and use it in the setup below. In the code, remember to replace:<rsa_public_key>with the key generated in the previous step<warehouse_name>with the name you want the dedicated warehouse to have
CREATE USER IF NOT EXISTS leaves an existing user untouched, public key included. If the user already exists, attach the key with ALTER USER instead — see moving an existing user to key-pair.Option B: User Managed Key-pair
Both encrypted and unencrypted private keys in PKCS#8 PEM format are supported. If you use an encrypted key, you’ll need to provide the passphrase when configuring the integration.
Generate a new key pair
Snowflake requires a minimum 2048-bit RSA private key in PKCS#8 PEM format. Generate an unencrypted private key:Extract the public key
After generating your private key, extract the public key:Configure Snowflake with your public key
Remove the header and footer from the public key file (-----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----), then use the remaining content as <rsa_public_key> in the setup script:
Configure the integration
In the integration settings:- Select “User Managed Key-pair” as the authentication method
- Paste your private key (including the
-----BEGIN PRIVATE KEY-----and-----END PRIVATE KEY-----headers) - If your key is encrypted (starts with
-----BEGIN ENCRYPTED PRIVATE KEY-----), provide the passphrase
Rotating a managed key pair
A managed key pair (Option A) is replaced from Settings → Integrations → (your Snowflake integration) → Key pair authentication, at the bottom of the page. Generating a replacement changes nothing until you activate it, so the integration keeps connecting with the key in use meanwhile.- Press Generate a new key pair. The new public key appears under New public key, waiting to be used.
- Add that public key to the Snowflake user the integration connects as, without replacing the key in use. Follow Snowflake’s key-pair rotation guide.
- Press Start using the new key pair.
- Remove the old public key from the Snowflake user, as the same guide describes.
Password authentication (deprecated)
In the code, remember to replace:<user_password>with a password that meets your account’s password policy<warehouse_name>with the name you want the dedicated warehouse to have
Password authentication is deprecated by Snowflake
If the integration stops connecting, or a new one never does, with394509, 390197, 250001 Multi-factor authentication is required for this account), Snowflake has enforced its single-factor password deprecation on the user the integration signs in as. Every human user (TYPE = PERSON, or no type) must now present a second factor, and password authentication is being removed from LEGACY_SERVICE users. Coalesce Quality connects unattended and cannot enter a TOTP code, so no password will work. Being able to log into Snowflake yourself does not help: your own login satisfies MFA interactively, the integration cannot.
Service users (TYPE = SERVICE) are exempt from MFA and authenticate with a key pair. The fix is to move the integration’s user to key-pair authentication; it does not need to be recreated.
Move an existing user to key-pair
- In Coalesce Quality, open Settings → Integrations → (your Snowflake integration), set Authentication method to Coalesce Quality managed key-pair and save. The public key appears under Key pair authentication at the bottom of the page; copy it. (To bring your own key instead, pick User managed key-pair and generate one as in Option B.)
-
In Snowflake, as
ACCOUNTADMINor a role withOWNERSHIPon the user, attach the key to the existing user: -
Back in Coalesce Quality, press Test connection. Once it succeeds, remove the password and mark the user as a service user so it stays outside MFA enforcement:
If the integration signs in as a person
If the integration was set up with someone’s own Snowflake login rather than a dedicated user, do not try to exempt that login from MFA. Create a dedicated service user with the key-pair setup above, grant it the integration’s role, and update the Username on the integration to the new user.Grant access to monitored database
We recommend setting access on Schema level, as long as it is aligned with your permissions management strategy.Option 1 (Recommended): Grant access to all schemas
The following stored procedure iterates through each schema in a given database, then grants access to each table in a given schema. This stored procedure should be run as follows each time a new schema is created. Run it in the same Worksheet as the Setup a user and warehouse step above so the$role_name session variable is still set.
Replace <database_name> with the name of your database.
MATERIALIZED VIEW, STREAM, and SELECT ON DYNAMIC TABLE grants are silently ignored on Snowflake editions that do not support those object types — the grant statements still succeed, so the procedure is safe to run on Standard edition.Semantic views need both
SELECT and REFERENCES. SELECT lets the role list them via SHOW SEMANTIC VIEWS and query them via SEMANTIC_VIEW(sv DIMENSIONS … METRICS …). REFERENCES is required separately so GET_DDL('SEMANTIC_VIEW', …) returns the body — without it, the catalog scrape can see the asset but cannot read its definition. Snowflake gates this differently from every other object kind, where SELECT / USAGE cover both visibility and GET_DDL.Option 2: Grant access to a database
Run this in the same Worksheet as the Setup a user and warehouse step above. Replace<database_name> with the name of your database.
Grant access to Snowflake tasks (Optional)
If you want to monitor Snowflake tasks, you need to grant MONITOR privileges on the specific tasks you want to observe. This allows us to collect task execution history and metadata. Replace<database_name>, <schema_name>, and <task_name> with your actual database, schema, and task names before running:
The MONITOR privilege on tasks allows viewing task execution history, status, and metadata but does not allow executing or modifying the tasks. This is required for task monitoring and anomaly detection.After granting these privileges, you must also enable task monitoring in the integration settings. In the integration configuration screen, make sure to enable “Fetch tasks and their executions” to start collecting task data.
Grant access to Snowflake tags (Optional)
If your Snowflake objects use tags and you want Coalesce Quality to read them (e.g. to filter tables or deploy monitors based on tag values), you need to grant theAPPLY TAG privilege. Without this privilege, Snowflake’s GET_DDL function replaces tag names and values with #UNKNOWN_TAG='#UNKNOWN_VALUE' placeholders.
This grant is only needed if you use Snowflake tags on your tables/views and want Coalesce Quality to use them for filtering or monitor rules. Coalesce Quality will show a warning during ingestion if it detects unknown tag placeholders in your metadata, so you can decide at that point whether to apply this grant.The
APPLY TAG privilege allows reading tag assignments but does not grant the ability to modify data or other security policies. See the Snowflake GET_DDL documentation for more details.Grant access to stages (Optional)
Coalesce Quality shows each named stage as an asset, with the location it points at, and the lineage between the stage and the tablesCOPY INTO loads from it or unloads to it (this needs query logs enabled). Snowflake lists a stage only to a role holding a privilege on it, so stages need a grant of their own:
USAGE applies to external stages only. An internal stage is listed only to a role with READ on it, which is read access to its files, and it has no external location to show, so we do not ask for it. The user stage (@~) and table stages (@%table) are not objects of their own and never appear.If your schemas use schema-level future grants (Option 1 above), use GRANT USAGE ON FUTURE STAGES IN SCHEMA … per schema instead, for the reason explained there.Grant access to apps, notebooks, warehouses and pipes (Optional)
With Fetch apps, notebooks, warehouses and pipes enabled, Coalesce Quality shows each Streamlit app, notebook, warehouse, pipe and Cortex Search service as an asset: an app under its title, with the warehouse it runs on; a pipe with the stage it reads and the table it loads; a Cortex Search service with the tables its query reads. Snowflake lists each of them only to a role holding a privilege on it:MONITOR lets the role see a pipe’s status and a warehouse’s load, not change them. USAGE on a Streamlit app lets the role open the app, and on a Cortex Search service lets it query the service; Coalesce Quality only lists them.Snowflake takes no grant on a notebook, so a notebook is listed only when the integration’s role owns it.If your schemas use schema-level future grants (Option 1 above), use the … IN SCHEMA … form of the future grants per schema instead, for the reason explained there.Stored procedures and user-defined functions
Coalesce Quality automatically discovers stored procedures and UDFs usingSHOW PROCEDURES IN DATABASE / SHOW USER FUNCTIONS IN DATABASE and fetches each object’s DDL via GET_DDL. All languages are supported (SQL, JavaScript, Python, Java, Scala). The grants in Option 1 / Option 2 above already include the required USAGE on procedures and functions — no extra steps are needed.
Procedures and UDFs show up as first-class assets in Coalesce Quality and participate in lineage whenever they are referenced by tables, views, or tasks.
Personal access (user OAuth)
In addition to the workspace credentials above, you can let each Coalesce Quality member authenticate as themselves against Snowflake. Queries then run under the member’s own Snowflake account and respect the grants, masking policies, and row-level security configured on that user. See Data Warehouse Access for the full model and when to enable it. To enable personal access, an account admin creates a Snowflake security integration of typeOAUTH once, then pastes the client ID and secret into the Snowflake integration’s edit page in Coalesce Quality.
Create the security integration
https://app.synq.io, the US app is https://app.us.synq.io and the AU app is https://app.au.synq.io — pass one as OAUTH_REDIRECT_URI and any others in OAUTH_ALTERNATE_REDIRECT_URIS. No trailing slash.
BLOCKED_ROLES_LIST prevents members from minting OAuth tokens for high-privilege account roles. Add any other roles your security policy reserves for break-glass use.
Fetch the client credentials
OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, and OAUTH_CLIENT_SECRET_2 (the second secret exists for rotation; either can be used). Paste the client ID and one of the secrets into Settings → Integrations → (your Snowflake integration) → Warehouse access → Personal credentials in Coalesce Quality.
No user mapping is required. When a member consents, they sign in to Snowflake on the standard authorize page, and the access token is issued for that Snowflake user. If your account uses SSO/SAML, the consent page transparently redirects through the IdP. Coalesce Quality stores per-user access/refresh tokens; queries from that member then run as the Snowflake user they signed in as.
Optional: restrict which roles members can request
Each member can pass arole parameter when consenting (Coalesce Quality forwards it as scope=session:role:<role>). If you want to constrain the set of roles reachable through this OAuth app, use ALLOWED_ROLES_LIST:
ALLOWED_ROLES_LIST is a whitelist that complements BLOCKED_ROLES_LIST (blacklist) above. Leave it empty to allow any role the member is granted on Snowflake, minus the blocked ones.
Databases from shares
When an account creates a database from a share (CREATE DATABASE … FROM SHARE), Snowflake records only the share it came from, not the database in the account that provides it. To link the tables of such a database to their source tables, Coalesce Quality needs to know which database each share was made from. You give it that in the integration of the account that receives the share, under Advanced → Databases from shares.
The values come from SHOW SHARES, run in the account that provides the share:
OUTBOUND. Each one gives the three values the integration asks for:
The easiest way is Fill from SHOW SHARES: paste the whole result, as copied from Snowsight, SnowSQL or the Snowflake CLI, and Coalesce Quality suggests the shares it found in it. Check each suggestion, correct anything it read wrong, and untick the shares this account doesn’t import. Nothing is saved until you save the integration. You can also add each share by hand.
The integration role cannot run
SHOW SHARES for you. Snowflake lists outbound shares only to a role with the IMPORT SHARE privilege, and then only the shares that role owns, so ACCOUNTADMIN is usually the only role that sees all of them. Running it from a stored procedure with owner’s rights is not allowed either. That’s why the values are entered in the integration rather than read by it.Network Configuration
If your Snowflake instance is behind a firewall or has network access controls, you may need to whitelist our IP addresses. See IP Whitelist for the complete list of IP addresses by region.
Input data in the UI
Integration name
For example,snowflake
Account name
You can find it underAdmin > Accounts when you highlight the link icon (🔗). Both formats work:
<orgname>-<accountname>(preferred, e.g.acme-prod1)<locator>.<region>(legacy, e.g.xy12345.eu-west-1)
https:// or a trailing slash. A trailing .snowflakecomputing.com is stripped and the value is lowercased automatically, so either acme-prod1 or acme-prod1.snowflakecomputing.com will work.

Databases
The names of the databases you granted access to earlier in the guide. You can monitor multiple databases with the same integration.Role, username, and authentication
The role name and username you created earlier in the guide, and the authentication method that matches how you set the user up: a key pair (recommended), or the password for aLEGACY_SERVICE user while your Snowflake account still permits one.
Warehouse
The name of the warehouse you created earlier in the guide.Audit table FQN (optional)
Fully-qualified table name (e.g.MY_DB.PUBLIC.QUALITY_SQL_TEST__AUDIT) where Coalesce Quality will write SQL test execution results. The integration creates the table automatically if it does not yet exist. Leave empty if you do not run SQL tests.
ACCOUNT_USAGE database name (optional)
Defaults toSNOWFLAKE. Override only if your account has the SNOWFLAKE share imported under a non-default name.
Optional flags
- Fetch query logs — enables query history ingestion from
SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY. You can optionally restrict the set of source databases. - Fetch Snowflake tasks — discovers Snowflake Tasks (
SHOW TASKS). Select a subset of databases or leave empty for all. - Fetch task executions from
ACCOUNT_USAGE.TASK_HISTORY— when on, centralized task history is used (up to 45-minute lag). When off,INFORMATION_SCHEMA.TASK_HISTORYis queried per database (lower lag, more warehouse time). - Task execution fetch interval (minutes) — minimum 5.
- Fetch table lineage — uses
SNOWFLAKE.CORE.GET_LINEAGEfor table-level lineage (Enterprise+). Optionally restrict to a subset of databases. - Fetch apps, notebooks, warehouses and pipes — with every catalog refresh, also lists Streamlit apps, notebooks, warehouses, pipes and Cortex Search services. Needs the grants in Grant access to apps, notebooks, warehouses and pipes.
- Don’t use GET_DDL for table schema collection — enable only if
GET_DDLcauses warehouse pressure; Coalesce Quality will fall back to parsing query logs.