Publisher Snowflake Setup (Grants)
The one-time Snowflake grants a publisher runs so apps can read their source tables — the complete script, why each grant exists, and how to know it worked.
Before any organization can successfully run your app, the platform needs permission to read your source tables. This is a one-time setup per table: once done, every additional organization that installs your app works with zero extra Snowflake work (the platform handles per-org grants automatically). Verified end to end in production, August 2026.
The three layers (mental model)
Layer 1 lets the platform manage access on your behalf. Layer 2 is the role that actually reads your table. Layer 3 is automatic and per-org. A run fails if any layer is missing, and the error text ("does not exist or not authorized") is identical in all three cases.
Important: the sync engine grants proxy roles to app runners, but it does not create proxy roles. That is your job. This trips up every first-time publisher.
The script
For each source table your app reads, run this in a Snowflake worksheet (adjust names; role names are the table's fully qualified name with dots replaced by double underscores, plus __ROLE):
-- ============ Layer 1: let the platform manage access ============
GRANT USAGE ON DATABASE <DB> TO ROLE MTA_ADMIN_ROLE WITH GRANT OPTION;
GRANT USAGE ON SCHEMA <DB>.<SCHEMA> TO ROLE MTA_ADMIN_ROLE WITH GRANT OPTION;
GRANT SELECT ON TABLE <DB>.<SCHEMA>.<TABLE> TO ROLE MTA_ADMIN_ROLE WITH GRANT OPTION;
-- ============ Layer 2: create and equip the proxy role ============
CREATE ROLE IF NOT EXISTS <DB>__<SCHEMA>__<TABLE>__ROLE;
GRANT SELECT ON TABLE <DB>.<SCHEMA>.<TABLE> TO ROLE <DB>__<SCHEMA>__<TABLE>__ROLE;
GRANT USAGE ON DATABASE <DB> TO ROLE <DB>__<SCHEMA>__<TABLE>__ROLE;
GRANT USAGE ON SCHEMA <DB>.<SCHEMA> TO ROLE <DB>__<SCHEMA>__<TABLE>__ROLE;Worked example for a table SANDBOX_TYNA.APP.STORES:
GRANT USAGE ON DATABASE SANDBOX_TYNA TO ROLE MTA_ADMIN_ROLE WITH GRANT OPTION;
GRANT USAGE ON SCHEMA SANDBOX_TYNA.APP TO ROLE MTA_ADMIN_ROLE WITH GRANT OPTION;
GRANT SELECT ON TABLE SANDBOX_TYNA.APP.STORES TO ROLE MTA_ADMIN_ROLE WITH GRANT OPTION;
CREATE ROLE IF NOT EXISTS SANDBOX_TYNA__APP__STORES__ROLE;
GRANT SELECT ON TABLE SANDBOX_TYNA.APP.STORES TO ROLE SANDBOX_TYNA__APP__STORES__ROLE;
GRANT USAGE ON DATABASE SANDBOX_TYNA TO ROLE SANDBOX_TYNA__APP__STORES__ROLE;
GRANT USAGE ON SCHEMA SANDBOX_TYNA.APP TO ROLE SANDBOX_TYNA__APP__STORES__ROLE;Notes:
Plain SELECT to MTA_ADMIN_ROLE is not enough — WITH GRANT OPTION is required, because the platform re-grants access to app roles on your behalf.
USAGE on database and schema is required at both layers. Without it, runs fail with "Database '<DB>' does not exist or not authorized" even though the SELECT grants exist.
This applies to views as well as tables.
⚠️ Always
CREATE ROLE IF NOT EXISTS, neverCREATE OR REPLACE ROLE. Replacing a role destroys every grant to and from it, silently breaking every app that used it, while the sync engine keeps reporting those grants as healthy.
When can I run this?
Any time — before or after you build, publish, or install. Order does not matter, because runs wait on the sync engine to finish provisioning before they execute. What DOES matter is that the grants exist before a run needs them.
How the fix takes effect after a failure
If installs or runs already failed because grants were missing:
Run the script above.
Open the Sync Engine Visualizer, select the affected org, and click Retry failed resources. The retry queues behind any running sync ("Waiting for lock" is normal). Failed items turn yellow (TRANSIENT).
Rerun the variant. The run completes the remaining work; items turn green after a successful run. Transient items do not resolve on their own — they re-evaluate when the app is next touched.
Keeping grants alive
When a pipeline drops and recreates a source table, Snowflake silently removes all grants on it, and apps reading that table start failing with "does not exist or not authorized" while every platform tool still shows green. Use TRUNCATE + INSERT patterns instead of drop/recreate so grants persist.
How to verify (read-only, safe)
-- Does the proxy role have SELECT on the table?
SHOW GRANTS ON TABLE <DB>.<SCHEMA>.<TABLE>;
-- Does the proxy role exist, and when was it (re)created?
SHOW ROLES LIKE '<DB>__<SCHEMA>__%';
-- Which orgs' runners hold the proxy role? (populated automatically as orgs install)
SHOW GRANTS OF ROLE <DB>__<SCHEMA>__<TABLE>__ROLE;Error signature quick reference
Related articles
Prerequisites for App Installs (checklist)
⏭️ Next: Prerequisites for App Installs