Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 1)



Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 1)

In this tutorial, you’ll learn how to connect your Streamlit app to Snowflake, a cloud data warehouse built for real-time analytics.

Integrating-Streamlit-with-Snowflake-Part1_featured.png

You’ll securely configure credentials, run SQL queries from Streamlit, visualize results, and even blend Snowflake tables with local data — creating a live, interactive data explorer powered entirely by Python.

This lesson is part of a series on Streamlit Apps:

  1. Getting Started with Streamlit: Learn Widgets, Layouts, and Caching
  2. Building Your First Streamlit App: Uploads, Charts, and Filters (Part 1)
  3. Building Your First Streamlit App: Uploads, Charts, and Filters (Part 2)
  4. Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 1) (this tutorial)
  5. Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 2)

To learn how to query, visualize, and export live warehouse data from Streamlit, just keep reading.

Looking for the source code to this post?

Jump Right To The Downloads Section


Introduction: Why Connect Streamlit to Snowflake

Welcome to the final lesson in the Streamlit tutorial series — the point where your local prototype evolves into a cloud-ready data application.

In the first two lessons, you learned how to build and extend a data explorer using static CSVs. That was perfect for learning Streamlit’s reactivity model, caching, and UI widgets. But in real analytics workflows, teams don’t analyze CSVs sitting on someone’s laptop — they connect to governed, live data sources that can scale securely across users and projects.

This is where Snowflake comes in. Snowflake is a cloud-based data warehouse built to handle massive datasets, enable secure sharing, and deliver blazing-fast SQL queries. By integrating it directly into your Streamlit app, you’ll transform your simple file-based dashboard into a dynamic data experience — one that interacts with actual business data in real time.

In this lesson, you’ll learn how to:

  • Configure Snowflake credentials securely using environment variables or Streamlit’s built-in secrets.toml.
  • Create reusable connection and query helpers in a dedicated module (snowflake_utils.py).
  • Run ad-hoc (Part 1) and parameterized (Part 2) SQL queries directly from your Streamlit UI.
  • Profile, visualize, and export warehouse data without leaving the app.
  • Blend remote Snowflake tables with local data for hybrid insights.
  • Apply lightweight caching to speed up repeated queries and reduce warehouse costs.

By the end of Part 2, you’ll have a fully functional Streamlit + Snowflake dashboard that connects securely, runs live queries, visualizes patterns, and exports results — all without needing a separate backend or API.

This is the same pattern you’ll use when building internal analytics portals, model-monitoring dashboards, or MLOps (machine learning operations) pipelines powered by governed warehouse data.

Figure 1: End-to-end architecture of the Streamlit + Snowflake integration. The user interacts with Streamlit through the browser, which connects to Snowflake using the Snowflake Connector, retrieves query results, and renders interactive visualizations (source: image by the author).

What Is Snowflake (and Why It Matters)

Before diving into code, let’s take a quick look at what makes Snowflake the go-to data warehouse for modern analytics and machine learning pipelines.

At its core, Snowflake is a fully managed cloud data platform — meaning you don’t have to worry about provisioning servers, maintaining storage, or scaling infrastructure. It separates compute (the “engine” that runs your queries) from storage (where your data lives), allowing you to scale each independently. When you need to run queries, you spin up a virtual warehouse; when you’re done, you can pause it to save costs.

This elasticity makes Snowflake ideal for applications that need to handle large, unpredictable workloads, such as Streamlit dashboards or MLOps tools that query model outputs on demand.

Some key advantages:

  • Performance on demand: Queries scale automatically based on load, returning results in seconds even on massive datasets.
  • Cost efficiency: You only pay when the warehouse is active — pause it to stop billing instantly.
  • Seamless integration: Works natively with Python via the official snowflake-connector-python package and advanced frameworks (e.g., Snowpark).
  • Security and governance: Features like role-based access control (RBAC), column-level masking, and time travel make it enterprise-grade by design.
  • Collaboration and sharing: Teams can share live data securely across departments or organizations without duplicating files.

By connecting Streamlit to Snowflake, you bridge the gap between interactive data apps and enterprise-grade data infrastructure. Your app no longer relies on static uploads — it runs live SQL queries against a scalable warehouse, retrieves governed results, and displays them instantly to users.

This comparison highlights why local CSV workflows break down at scale. Snowflake replaces manual file handling with a governed, elastic, and real-time data platform that supports secure collaboration, fine-grained access control, and cost-efficient analytics.

Table 1: Comparison of local CSV workflows versus Snowflake. Snowflake offers live data access, scalable compute, governed security, and collaborative sharing — making it ideal for production-grade analytics apps (source: image by the author).

Would you like immediate access to 3,457 images curated and labeled with hand gestures to train, explore, and experiment with … for free? Head over to Roboflow and get a free account to grab these hand gesture images.


Configuring Your Development Environment

Before writing any code, let’s make sure your environment is ready to connect Streamlit with Snowflake. You’ll only need a few tools and a free Snowflake account to get started.


Step 1: Create a Snowflake Trial Account

If you don’t already have one, visit Snowflake’s free trial page and create a 30-day account.

Once signed in, open Snowsight (Snowflake’s modern web interface), where you can run SQL queries and manage compute resources.


Step 2: Resume or Create a Warehouse

  1. Go to Admin → Warehouses.
  2. Look for a default warehouse such as COMPUTE_WH. If it’s paused, click Resume.
  3. If none exists, create a new XS (Extra-Small) warehouse.
  4. Enable auto-suspend (60 seconds) to avoid unnecessary credit usage.

Step 3: Confirm Database and Schema

Snowflake trial accounts include a sample database:

SNOWFLAKE_SAMPLE_DATA → TPCH_SF1

TPCH_SF1 is Snowflake’s built-in sample schema based on the TPC-H benchmark dataset (scale factor 1), commonly used for demos and testing. You can safely query these tables without affecting your account or incurring significant costs.

Inside, you’ll find tables such as CUSTOMER, ORDERS, and LINEITEM.

We’ll use these to run test queries later in the Streamlit app.

Run this quick check in Snowsight:

USE WAREHOUSE COMPUTE_WH;
USE DATABASE SNOWFLAKE_SAMPLE_DATA;
USE SCHEMA TPCH_SF1;
SELECT CURRENT_TIMESTAMP();

If you see a UTC (Coordinated Universal Time) timestamp result, your warehouse and schema are configured correctly.


Step 4: Install Dependencies

Add the following packages to your requirements.txt (if not already present):

streamlit>=1.38,<2
pandas>=2.2,<3
snowflake-connector-python>=3.10,<4

Then install them:

pip install -r requirements.txt

Step 5: Configure Snowflake Credentials

You can store credentials as environment variables or, more conveniently, in Streamlit’s built-in secrets file.

Create a file named .streamlit/secrets.toml at your project root:

[snowflake]
user = "YOUR_USERNAME"
password = "YOUR_PASSWORD"
account = "AXOIRVL-GQ22654"
warehouse = "COMPUTE_WH"
database = "SNOWFLAKE_SAMPLE_DATA"
schema = "TPCH_SF1"
role = "ACCOUNTADMIN"

Note: Never commit this file to GitHub. It should remain private on your local system.

Once your Snowflake trial account, dependencies, and credentials are ready, you’re set to move on.

Next, let’s look at how our helper modules (i.e., config.py and snowflake_utils.py) securely handle connection logic behind the scenes.


Need Help Configuring Your Development Environment?

Having trouble configuring your development environment? Want access to pre-configured Jupyter Notebooks running on Google Colab? Be sure to join PyImageSearch University — you will be up and running with this tutorial in a matter of minutes.

All that said, are you:

  • Short on time?
  • Learning on your employer’s administratively locked system?
  • Wanting to skip the hassle of fighting with the command line, package managers, and virtual environments?
  • Ready to run the code immediately on your Windows, macOS, or Linux system?

Then join PyImageSearch University today!

Gain access to Jupyter Notebooks for this tutorial and other PyImageSearch guides pre-configured to run on Google Colab’s ecosystem right in your web browser! No installation required.

And best of all, these Jupyter Notebooks will run on Windows, macOS, and Linux!


Project Structure Recap: Extending the Foundation for Snowflake

By the end of this lesson, your Streamlit project will have evolved from a simple prototype into a live data app capable of querying cloud warehouses. The structure remains familiar — modular, organized, and easy to extend — but now includes utilities for secure credential handling and database connectivity.

Here’s the complete directory layout, with new components highlighted:

streamlit_project/
├── lesson1_main.py
├── lesson2_main.py
├── lesson3_main.py              ← New: connects to Snowflake
├── pyimagesearch/
│   ├── __init__.py
│   ├── config.py                ← Now loads Snowflake credentials
│   ├── data_loader.py
│   ├── visualization.py
│   ├── snowflake_utils.py       ← New helper for warehouse queries
├── data/
│   └── iris_sample.csv
├── .streamlit/
│   ├── config.toml              ← App theming and layout
│   └── secrets.toml             ← Stores Snowflake credentials securely
├── requirements.txt
└── README.md

New and updated modules in this lesson:

  • pyimagesearch/snowflake_utils.py: Encapsulates authentication and query execution using the official Snowflake connector.
  • pyimagesearch/config.py: Updated to read credentials from st.secrets or environment variables, and expose a snowflake_enabled flag.
  • lesson3_main.py: Your main Streamlit app that connects to Snowflake, runs SQL queries, visualizes data, blends local and remote datasets, and demonstrates caching (Part 2).
  • .streamlit/secrets.toml: Holds your private Snowflake credentials for local development.

The rest of the project (i.e., data_loader.py, visualization.py, and __init__.py) carry forward unchanged from previous lessons, reinforcing consistent structure and reusability across the entire series.


Understanding the Helper Modules

Before we connect Streamlit to Snowflake, let’s pause and look at the two backbone modules that quietly do most of the heavy lifting (i.e., config.py and snowflake_utils.py).

These modules handle credential loading, database connection creation, and returning query results as Pandas DataFrames for visualization. Getting comfortable with them now will make the rest of the lesson effortless.


config.py: Managing Configuration and Credentials

Let’s start with config.py. This file defines the global configuration that every lesson in this series relies on. It’s small, simple, and incredibly useful.

The top of the file begins with a few imports that set the foundation:

from dataclasses import dataclass
import os
from typing import Optional

try:
    import streamlit as st
except Exception:
    st = None

try:
    from dotenv import load_dotenv  # type: ignore
    load_dotenv()
except Exception:
    pass

Here’s what’s happening:

We import Python’s built-in dataclass to define a configuration container with minimal boilerplate. The os module is used to read environment variables, while Optional from typing lets us define fields that might or might not be set — handy for credentials (e.g., roles or schemas) that can sometimes be omitted.

Then we make two optional imports.

First, Streamlit: wrapped in a try block to prevent import-time failures if Streamlit isn’t installed (e.g., when running utility tests or lesson scripts outside the Streamlit runtime). If the import fails, we simply assign st = None and continue.

Next comes an optional import of dotenv. If the python-dotenv package is installed, it loads environment variables from a local .env file. This is mostly for convenience — developers often keep credentials there while experimenting locally. The script will still work fine without it.

Now we reach the heart of the file: the Settings dataclass.

@dataclass(frozen=True)
class Settings:
    app_name: str = "Streamlit Tutorial Series"
    default_sample_path: str = os.path.join("data", "iris_sample.csv")

    snowflake_user: Optional[str] = None
    snowflake_password: Optional[str] = None
    snowflake_account: Optional[str] = None
    snowflake_role: Optional[str] = None
    snowflake_warehouse: Optional[str] = None
    snowflake_database: Optional[str] = None
    snowflake_schema: Optional[str] = None

This class centralizes all configuration in one place. The frozen=True flag means that once the settings object is created, none of its values can be changed — an important safeguard when Streamlit reruns scripts automatically.

At the top are generic app-level variables (e.g., app_name and the default Iris dataset path). The rest are Snowflake credentials that start as None and are dynamically populated.

Inside the class, there’s a special method called __post_init__, which runs right after initialization. This is where the real magic happens.

    def __post_init__(self):
        """Load Snowflake credentials from Streamlit secrets or environment variables."""
        # Load from Streamlit secrets first
        snowflake_secrets = {}
        if st is not None:
            try:
                snowflake_secrets = st.secrets["snowflake"]
            except Exception:
                pass

When Streamlit is available, it first looks for credentials stored in st.secrets["snowflake"], which is how Streamlit Cloud securely manages secrets. If those aren’t found, it falls back to reading from environment variables (e.g., SNOWFLAKE_USER, SNOWFLAKE_ACCOUNT, and so on).

This layered approach is designed to support both cloud and local development environments

        # Fallback to environment variables if secrets missing
        def get_value(key: str, env_key: str) -> Optional[str]:
            return snowflake_secrets.get(key) or os.getenv(env_key)

Next comes a small helper function called get_value().

Its purpose is simple: try to fetch a value from Streamlit secrets first, and if that fails, fall back to the corresponding environment variable. This pattern makes the configuration portable — it works the same way whether you’re deploying in the cloud or testing locally on your machine.

        object.__setattr__(self, "snowflake_user", get_value("user", "SNOWFLAKE_USER"))
        object.__setattr__(self, "snowflake_password", get_value("password", "SNOWFLAKE_PASSWORD"))
        object.__setattr__(self, "snowflake_account", get_value("account", "SNOWFLAKE_ACCOUNT"))
        object.__setattr__(self, "snowflake_role", get_value("role", "SNOWFLAKE_ROLE"))
        object.__setattr__(self, "snowflake_warehouse", get_value("warehouse", "SNOWFLAKE_WAREHOUSE"))
        object.__setattr__(self, "snowflake_database", get_value("database", "SNOWFLAKE_DATABASE"))
        object.__setattr__(self, "snowflake_schema", get_value("schema", "SNOWFLAKE_SCHEMA"))

With the get_value() helper in place, we can now populate all the Snowflake fields in the frozen dataclass. Because Settings is immutable, normal assignment isn’t allowed — instead, the code uses object.__setattr__() to set each attribute safely within the __post_init__ scope.

This section is the real heart of the configuration system. It ensures that even though the Settings object is frozen, all your credentials are loaded once — right when it’s created — and remain constant throughout the app’s lifecycle. Streamlit’s rerun model won’t reset or mutate these values, keeping your environment predictable and reducing accidental mutation.

At the end of the file, there’s one more useful property: snowflake_enabled.

    @property
    def snowflake_enabled(self) -> bool:
        """Return True if all required Snowflake credentials are available."""
        required = [
            self.snowflake_user,
            self.snowflake_password,
            self.snowflake_account,
            self.snowflake_warehouse,
            self.snowflake_database,
            self.snowflake_schema,
        ]
        return all(bool(x) for x in required)

This property is intended to be used by the app to decide whether to attempt a live Snowflake connection.

Finally, at the bottom, the file creates a single global instance of this dataclass:

settings = Settings()

This way, every script can import the same configuration with one line:

from pyimagesearch import settings

and immediately access values such as:

settings.snowflake_user
settings.snowflake_enabled
Figure 2: How config.py loads credentials. Streamlit first reads secrets, then falls back to environment variables, constructs a settings object, and exposes it to the Streamlit app (source: image by the author).

snowflake_utils.py: Handling Connection and Query Logic

Now that credentials are loaded, we need a way to connect to Snowflake and run queries. That’s where snowflake_utils.py comes in.

Like config.py, it starts with a few critical imports:

from dataclasses import dataclass
from typing import Optional
import pandas as pd

try:
    import snowflake.connector  # type: ignore
except Exception:
    snowflake = None

The imports here mirror the same philosophy: minimal, intentional, and safe.

We use dataclass again to structure our credentials cleanly. Optional lets us mark the role parameter as non-essential. Pandas is used because the Snowflake connector can return query results directly as a Pandas DataFrame, which is perfect for Streamlit.

Finally, the try/except around snowflake.connector prevents import errors in environments where Snowflake dependencies aren’t installed yet. Instead of breaking the whole app, it simply sets snowflake = None. Later, the app can catch this error and inform the user gracefully.

Next comes the SnowflakeCredentials dataclass:

@dataclass
class SnowflakeCredentials:
    user: str
    password: str
    account: str
    warehouse: str
    database: str
    schema: str
    role: Optional[str] = None

This class is a neat container for everything needed to connect to Snowflake. Without it, we’d have to pass 7 parameters into every connection call. The dataclass groups them neatly and provides type hints for clarity.

The real star of the module is the run_query function:

def run_query(creds: SnowflakeCredentials, query: str) -> pd.DataFrame:
    if "snowflake" not in globals() or snowflake is None:  # type: ignore
        raise RuntimeError("snowflake-connector-python is not installed.")
    ctx = snowflake.connector.connect(
        user=creds.user,
        password=creds.password,
        account=creds.account,
        warehouse=creds.warehouse,
        database=creds.database,
        schema=creds.schema,
        role=creds.role,
    )
    try:
        cs = ctx.cursor()
        try:
            cs.execute(query)
            df = cs.fetch_pandas_all()
        finally:
            cs.close()
    finally:
        ctx.close()
    return df

Let’s walk through it.

The function begins with a quick check to ensure the Snowflake connector is available. If not, it raises a clear error instead of failing later during connection.

The connection itself is straightforward: it uses the credentials stored in the SnowflakeCredentials dataclass to create a context (ctx). Inside that context, a cursor executes the SQL query. Once the data is retrieved, it’s fetched directly into a Pandas DataFrame using fetch_pandas_all(), which is one of the most convenient features of Snowflake’s Python connector.

Finally, both the cursor and connection are closed in a finally block — this ensures resources are cleaned up properly even if something goes wrong mid-query.

Together, config.py and snowflake_utils.py form a small but powerful foundation.

The first ensures credentials are loaded securely and predictably. The second provides a clean, reusable way to query Snowflake without scattering connection logic throughout your codebase.

Figure 3: Streamlit data pipeline. The app loads Snowflake credentials from config.py, executes queries via snowflake_utils.py, and converts results into DataFrames for visualization (source: image by the author).

Next, we’ll put these modules to work by building our Snowflake-connected Streamlit app, starting with how to check the connection and run your first live query.

This lesson is to be completed in Part 2.


What’s next? We recommend PyImageSearch University.

Course information:
86+ total classes • 115+ hours hours of on-demand code walkthrough videos • Last updated: January 2026
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled

I strongly believe that if you had the right teacher you could master computer vision and deep learning.

Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?

That’s not the case.

All you need to master computer vision and deep learning is for someone to explain things to you in simple, intuitive terms. And that’s exactly what I do. My mission is to change education and how complex Artificial Intelligence topics are taught.

If you’re serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to successfully and confidently apply computer vision to your work, research, and projects. Join me in computer vision mastery.

Inside PyImageSearch University you’ll find:

  • &check; 86+ courses on essential computer vision, deep learning, and OpenCV topics
  • &check; 86 Certificates of Completion
  • &check; 115+ hours hours of on-demand video
  • &check; Brand new courses released regularly, ensuring you can keep up with state-of-the-art techniques
  • &check; Pre-configured Jupyter Notebooks in Google Colab
  • &check; Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
  • &check; Access to centralized code repos for all 540+ tutorials on PyImageSearch
  • &check; Easy one-click downloads for code, datasets, pre-trained models, etc.
  • &check; Access on mobile, laptop, desktop, etc.

Click here to join PyImageSearch University


Citation Information

Singh, V. “Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 1),” PyImageSearch, P. Chugh, S. Huot, A. Sharma, and P. Thakur, eds., 2026, https://pyimg.co/hwmqa

@incollection{Singh_2026_Integrating-Streamlit-with-Snowflake,
  author = {Vikram Singh},
  title = {{Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 1)}},
  booktitle = {PyImageSearch},
  editor = {Puneet Chugh and Susan Huot and Aditya Sharma and Piyush Thakur},
  year = {2026},
  url = {https://pyimg.co/hwmqa},
}

To download the source code to this post (and be notified when future tutorials are published here on PyImageSearch), simply enter your email address in the form below!

Download the Source Code and FREE 17-page Resource Guide

Enter your email address below to get a .zip of the code and a FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning. Inside you’ll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!

The post Integrating Streamlit with Snowflake for Live Cloud Data Apps (Part 1) appeared first on PyImageSearch.

Liked Liked