> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oleander.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Snowflake

> Query Snowflake tables from the lake, or register Snowflake Horizon as an Iceberg catalog.

There are two ways to bring Snowflake into oleander. A **connection** attaches your Snowflake account so its tables are queryable from the lake. **Snowflake Horizon** registers Snowflake's Iceberg catalog so your Iceberg tables are available to every engine, including Spark and Polars.

Both are managed in [Settings → Lake](https://oleander.dev/app/settings/lake).

## Connection

Authentication uses key-pair signing. No passwords are stored.

### Setup

1. Open [Settings → Lake](https://oleander.dev/app/settings/lake) and find **Snowflake connections**.
2. Fill in the required fields:

| Field                  | Description                                                                                        |
| ---------------------- | -------------------------------------------------------------------------------------------------- |
| **Name**               | A short identifier for this connection, e.g. `prod_sf`. This becomes the catalog prefix in SQL.    |
| **Account identifier** | Your Snowflake account in `orgname-accountname` format                                             |
| **Username**           | The Snowflake user to authenticate as                                                              |
| **Private key**        | RSA private key in PEM format. The user must have the matching public key registered in Snowflake. |

3. Optionally set a default **warehouse**, **database**, and **role** to scope queries.

### Generating a key pair

```bash theme={null}
# Generate an RSA key pair
openssl genrsa -out snowflake_key.pem 2048
openssl rsa -in snowflake_key.pem -pubout -out snowflake_key.pub
```

```sql theme={null}
-- Register the public key with your Snowflake user
ALTER USER my_user SET RSA_PUBLIC_KEY='<contents of snowflake_key.pub>';
```

Paste the contents of `snowflake_key.pem` into the **Private key** field. The key is stored encrypted.

### Querying

Tables are reachable as `connection_name.schema.table`:

```sql theme={null}
-- Query a Snowflake table
SELECT *
FROM prod_sf.public.orders
WHERE created_at >= '2024-01-01'
LIMIT 100;

-- Join Snowflake with your Iceberg lake
SELECT o.order_id, c.segment
FROM prod_sf.public.orders o
JOIN oleander.default.customers c ON o.customer_id = c.id;
```

<Note>
  **A Snowflake connection table selects DuckDB.** DuckDB is the only engine that attaches external connections, so the [query router](/platform/query-routing) routes any query naming a connection table here before it considers input size - leave `engine` on `auto`. Asking for Bloom, Polars, or Spark on one of these queries returns an engine capability error rather than rerouting silently.

  A Horizon catalog is different: it is a real Iceberg catalog, so DuckDB and Spark can both read it.
</Note>

***

## Snowflake Horizon

Snowflake Horizon is Snowflake's built-in Iceberg catalog, powered by [Polaris](https://www.polaris.io/). Registering it gives you full Iceberg REST catalog access against your Snowflake-managed Iceberg tables - DuckDB queries, Polars workloads, and Spark jobs alike.

Unlike a connection, a Horizon catalog is a real Iceberg catalog, so it is not limited to DuckDB.

### Setup

1. Open [Settings → Lake](https://oleander.dev/app/settings/lake) and find **External catalogs**.
2. Select **Snowflake Horizon** as the catalog type.
3. Fill in the required fields:

| Field              | Description                                                                           |
| ------------------ | ------------------------------------------------------------------------------------- |
| **Name**           | A short catalog name, e.g. `sf_horizon`                                               |
| **Catalog URI**    | Your Snowflake account URL, e.g. `https://orgname-accountname.snowflakecomputing.com` |
| **Database**       | The Snowflake database to expose as an Iceberg catalog                                |
| **Role**           | The Snowflake role used to access the catalog                                         |
| **Cloud provider** | `aws`, `gcp`, or `azure`                                                              |
| **Region**         | The cloud region your Snowflake account is in                                         |

4. Choose an authentication method:

<Tabs>
  <Tab title="Personal Access Token (PAT)">
    Generate a PAT in Snowflake and paste it into the **Secret** field. This is the simplest option.

    ```sql theme={null}
    -- Generate a PAT in Snowflake
    ALTER USER my_user ADD PROGRAMMATIC ACCESS TOKEN my_pat;
    ```
  </Tab>

  <Tab title="Key-pair">
    Use an RSA key pair for authentication. Provide:

    | Field           | Description                                  |
    | --------------- | -------------------------------------------- |
    | **Username**    | The Snowflake user                           |
    | **Private key** | RSA private key in PEM format                |
    | **Passphrase**  | Passphrase for the private key, if encrypted |

    The same key pair used for a Snowflake connection can be reused here.
  </Tab>
</Tabs>

### Querying

Once registered, the catalog is available under its name everywhere:

```sql theme={null}
-- DuckDB: query a Snowflake Horizon Iceberg table
SELECT species, COUNT(*) AS n
FROM sf_horizon.default.flowers
GROUP BY 1
ORDER BY n DESC;
```

```python theme={null}
# Polars script mode
flowers = scan("sf_horizon.default.flowers")
result = flowers.group_by("species").agg(pl.len().alias("count"))
```

<Note>
  Credential vending is handled automatically via the Iceberg REST protocol. No S3 or GCS credentials need to be configured manually.
</Note>

A catalog other than `oleander` routes to DuckDB or Spark - [Bloom](/platform/bloom) mounts only `oleander`. See [Catalogs](/platform/lake/catalogs) for how registered catalogs behave across the platform.
