# Snowflake

Use Snowflake as the warehouse foundation for DinMo. Once connected, DinMo can query governed customer data from Snowflake to power models, segments, Customer Hub, predictions, and Identity Resolution, while writing DinMo-generated technical tables back to a dedicated Snowflake database.

## Overview

A Snowflake source has two responsibilities:

* read the business data that DinMo users can model and activate
* store DinMo technical outputs such as segment snapshots, statistics, predictions, and Identity Resolution tables

This keeps customer data in Snowflake and makes DinMo activity easy to audit through Snowflake roles, warehouses, query history, and dedicated schemas.

## Recommended setup

For new Snowflake sources, we recommend using:

* a dedicated service user for DinMo
* a dedicated Snowflake role with only the permissions DinMo needs
* key pair authentication
* a dedicated warehouse for DinMo workloads
* a dedicated internal database such as `DINMO_DB`

The role needs `USAGE` on the warehouse, `SELECT` access to the business schemas DinMo should read, and write access to DinMo's internal schemas. Password authentication should only be used for existing setups that have not migrated yet.

{% hint style="info" %}
Snowflake supports service users for non-human access and key pair authentication for programmatic connections. See the Snowflake documentation for [user types](https://docs.snowflake.com/en/sql-reference/sql/create-user) and [key pair authentication](https://docs.snowflake.com/en/user-guide/key-pair-auth).
{% endhint %}

## Create a dedicated warehouse

Create a warehouse for DinMo workloads so you can monitor credit usage, tune sizing, and avoid impacting other workloads.

```sql
CREATE WAREHOUSE IF NOT EXISTS IDENTIFIER('DINMO_WAREHOUSE')
  WAREHOUSE_SIZE = XSMALL
  WAREHOUSE_TYPE = STANDARD
  AUTO_SUSPEND = 60
  AUTO_RESUME = TRUE
  INITIALLY_SUSPENDED = TRUE;
```

You can start with `XSMALL` and increase the size if queries queue or previews become slow.

## Create the DinMo role, user, and internal database

Run the script below from a Snowflake role that can create users, roles, warehouses, databases, schemas, and grants. Update the values between `< >` before running it.

```sql
-- Edit these values before running the script.
SET INPUT_ROLE = 'ACCOUNTADMIN';
SET DINMO_SERVICE_USER = 'DINMO_SERVICE_USER';
SET DINMO_ACCESS_ROLE_NAME = 'DINMO_ACCESS_ROLE';
SET DINMO_WAREHOUSE = 'DINMO_WAREHOUSE';
SET DATA_MODEL_DATABASE = '<business_database>';
SET DEFAULT_NAMESPACE = '<business_database.schema>';
SET DINMO_INTERNAL_DATABASE = 'DINMO_DB';

USE ROLE IDENTIFIER($INPUT_ROLE);

-- Create the role used by DinMo.
CREATE ROLE IF NOT EXISTS IDENTIFIER($DINMO_ACCESS_ROLE_NAME);

-- Give DinMo compute access.
GRANT USAGE ON WAREHOUSE IDENTIFIER($DINMO_WAREHOUSE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);

-- Give DinMo read access to the business data database.
GRANT USAGE ON DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT USAGE ON ALL SCHEMAS IN DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT SELECT ON ALL TABLES IN DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT SELECT ON ALL VIEWS IN DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT USAGE ON FUTURE SCHEMAS IN DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT SELECT ON FUTURE TABLES IN DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT SELECT ON FUTURE VIEWS IN DATABASE IDENTIFIER($DATA_MODEL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);

-- Create the internal database and schemas used by DinMo.
CREATE DATABASE IF NOT EXISTS IDENTIFIER($DINMO_INTERNAL_DATABASE);
USE DATABASE IDENTIFIER($DINMO_INTERNAL_DATABASE);

CREATE SCHEMA IF NOT EXISTS DINMO_DELTA_STORAGE;
CREATE SCHEMA IF NOT EXISTS DINMO_SEGMENTS;
CREATE SCHEMA IF NOT EXISTS DINMO_STATS;
CREATE SCHEMA IF NOT EXISTS DINMO_PREDICTIONS;
CREATE SCHEMA IF NOT EXISTS DINMO_IDENTITY;

-- Give DinMo write access only to its internal database and schemas.
GRANT USAGE ON DATABASE IDENTIFIER($DINMO_INTERNAL_DATABASE)
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT ALL PRIVILEGES ON SCHEMA DINMO_DELTA_STORAGE
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT ALL PRIVILEGES ON SCHEMA DINMO_SEGMENTS
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT ALL PRIVILEGES ON SCHEMA DINMO_STATS
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT ALL PRIVILEGES ON SCHEMA DINMO_PREDICTIONS
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);
GRANT ALL PRIVILEGES ON SCHEMA DINMO_IDENTITY
  TO ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME);

-- Create the DinMo service user.
CREATE USER IF NOT EXISTS IDENTIFIER($DINMO_SERVICE_USER)
  TYPE = SERVICE
  DEFAULT_ROLE = $DINMO_ACCESS_ROLE_NAME
  DEFAULT_WAREHOUSE = $DINMO_WAREHOUSE
  DEFAULT_NAMESPACE = $DEFAULT_NAMESPACE;

GRANT ROLE IDENTIFIER($DINMO_ACCESS_ROLE_NAME)
  TO USER IDENTIFIER($DINMO_SERVICE_USER);
```

`DINMO_IDENTITY` is required when Identity Resolution is enabled. `DINMO_PREDICTIONS` is required when AI Predictions is enabled. The other internal schemas are used for segments, statistics, and snapshot storage.

## Restrict access to selected schemas

The setup script above grants read access to every current and future schema in the business database. This is convenient for a first setup, but some security teams prefer schema-level grants.

To restrict access, replace the business database grants with grants like these, and repeat them for each schema DinMo should read:

```sql
GRANT USAGE ON DATABASE <business_database> TO ROLE DINMO_ACCESS_ROLE;
GRANT USAGE ON SCHEMA <business_database>.<schema> TO ROLE DINMO_ACCESS_ROLE;
GRANT SELECT ON ALL TABLES IN SCHEMA <business_database>.<schema> TO ROLE DINMO_ACCESS_ROLE;
GRANT SELECT ON ALL VIEWS IN SCHEMA <business_database>.<schema> TO ROLE DINMO_ACCESS_ROLE;
GRANT SELECT ON FUTURE TABLES IN SCHEMA <business_database>.<schema> TO ROLE DINMO_ACCESS_ROLE;
GRANT SELECT ON FUTURE VIEWS IN SCHEMA <business_database>.<schema> TO ROLE DINMO_ACCESS_ROLE;
```

If dbt or another transformation tool drops and recreates tables, keep the `FUTURE` grants in place on every schema DinMo needs to read.

## Configure the source in DinMo

1. In DinMo, go to the workspace settings.
2. Open the **Sources** tab.
3. Click **Add New Source**.
4. Select **Snowflake**.
5. Fill in the Snowflake connection fields.

<figure><img src="/files/ncSQHrIQUTUMN7LAJRdM" alt="Snowflake source configuration form in DinMo"><figcaption><p>Configure the Snowflake source with the service user, role, warehouse, business database, and internal database.</p></figcaption></figure>

Use the values from the script:

* **Account identifier**: the account identifier from your Snowflake URL. See Snowflake's [account identifier documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier#finding-the-organization-and-account-name-for-an-account).
* **Database**: the business database that contains the source data DinMo can read.
* **Internal database**: the database where DinMo stores technical data. If you kept the script default, use `DINMO_DB`.
* **Warehouse**: the warehouse DinMo should use. If you kept the script default, use `DINMO_WAREHOUSE`.
* **Role**: the role assigned to the DinMo service user. If you kept the script default, use `DINMO_ACCESS_ROLE`.
* **Username**: the DinMo service user. If you kept the script default, use `DINMO_SERVICE_USER`.
* **Authentication method**: choose **Key Pair**.
* **Source name**: the display name shown in DinMo.

If your account URL is `https://xxx.europe-west2.gcp.snowflakecomputing.com/`, enter `xxx.europe-west2.gcp` as the account identifier. Do not include `https://` or `.snowflakecomputing.com`.

## Configure key pair authentication

After choosing **Key Pair** in DinMo, click **Generate a Public Key** and run the generated SQL in Snowflake.

<figure><img src="/files/Yh8Y6fQ2lF2bvomP2Jzh" alt="Generated Snowflake public key SQL in DinMo"><figcaption><p>Run the generated SQL in Snowflake to attach the public key to the DinMo service user.</p></figcaption></figure>

The generated SQL updates the DinMo service user with the public key used for authentication. Do not modify the generated key value.

If your security team generates the public key before the source is configured in DinMo, you can set it directly on the service user with `RSA_PUBLIC_KEY`.

{% hint style="warning" %}
Password authentication is not recommended for new Snowflake sources. Use it only for existing setups that have not migrated to key pair authentication yet.
{% endhint %}

## Test the connection

Click **Save & Test** in DinMo. If the test succeeds, the Snowflake source is ready to use.

If the test fails, check the troubleshooting section below before changing the connection configuration.

## Troubleshooting

**Connection test fails**

Check that the account identifier, warehouse, database, role, username, and authentication method match the Snowflake objects created for DinMo. If you use key pair authentication, confirm that the public key generated by DinMo was assigned to `DINMO_SERVICE_USER`.

**The user cannot assume the role**

Confirm that the role was granted to the service user:

```sql
GRANT ROLE DINMO_ACCESS_ROLE TO USER DINMO_SERVICE_USER;
```

**DinMo cannot see source tables**

Confirm that `DINMO_ACCESS_ROLE` has `USAGE` on the relevant database and schemas, plus `SELECT` on current and future tables or views. If tables are recreated by dbt or another tool, verify the `FUTURE TABLES` and `FUTURE VIEWS` grants on each relevant schema.

**DinMo cannot create technical tables or views**

Confirm that the internal database and schemas exist and that `DINMO_ACCESS_ROLE` has write access to them:

```sql
GRANT USAGE ON DATABASE DINMO_DB TO ROLE DINMO_ACCESS_ROLE;
GRANT ALL PRIVILEGES ON SCHEMA DINMO_DB.DINMO_DELTA_STORAGE TO ROLE DINMO_ACCESS_ROLE;
GRANT ALL PRIVILEGES ON SCHEMA DINMO_DB.DINMO_SEGMENTS TO ROLE DINMO_ACCESS_ROLE;
GRANT ALL PRIVILEGES ON SCHEMA DINMO_DB.DINMO_STATS TO ROLE DINMO_ACCESS_ROLE;
GRANT ALL PRIVILEGES ON SCHEMA DINMO_DB.DINMO_PREDICTIONS TO ROLE DINMO_ACCESS_ROLE;
GRANT ALL PRIVILEGES ON SCHEMA DINMO_DB.DINMO_IDENTITY TO ROLE DINMO_ACCESS_ROLE;
```

**You use several databases**

Create one DinMo source per Snowflake database, or make sure models use fully qualified table names such as `database.schema.table`.

If you still encounter an issue, contact your account manager or <support@dinmo.com>.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dinmo.io/integrations/data-sources/snowflake.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
