Home Database Snowpark for Python: DataFrame API, Stored Procedures, and App Development
Advanced 6 min · July 17, 2026

Snowpark for Python: DataFrame API, Stored Procedures, and App Development

Learn Snowpark for Python: build DataFrame pipelines, create stored procedures, and develop apps on Snowflake.

N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Drawn from code that ran under real load.

Follow
Production
production tested
2026-07-17T18:30:00
last updated
2,439
articles · all by Naren
Before you start⏱ 20-25 min read
  • Basic knowledge of Python (functions, classes, pandas)
  • Familiarity with SQL (SELECT, JOIN, GROUP BY)
  • A Snowflake account with access to a virtual warehouse
  • Python 3.8+ installed locally
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Snowpark is a Python library for Snowflake that lets you write DataFrame-based data pipelines and stored procedures.
  • The DataFrame API provides lazy evaluation and pushdown optimization, similar to PySpark but native to Snowflake.
  • Stored procedures can be written in Python and run on Snowflake's compute resources.
  • You can build full applications using Snowpark's client-side and server-side capabilities.
  • Snowpark supports UDFs, UDTFs, and vectorized UDFs for custom transformations.
✦ Definition~90s read
What is Snowpark for Python?

Snowpark for Python is a library that lets you write data pipelines, stored procedures, and applications using Python, with operations pushed down to Snowflake for execution.

Imagine you have a giant warehouse of data (Snowflake).
Plain-English First

Imagine you have a giant warehouse of data (Snowflake). Snowpark is like a smart forklift that lets you move and transform data without having to physically carry it yourself. You tell the forklift what to do (e.g., filter, group, join) using Python commands, and it does the heavy lifting inside the warehouse, only bringing back the final result. This is much faster than pulling everything out and processing it on your own computer.

Snowflake is a powerful cloud data warehouse, but traditionally you interact with it using SQL. Snowpark for Python changes the game by allowing you to write data pipelines, stored procedures, and even full applications using Python, all while leveraging Snowflake's elastic compute and storage. This is a game-changer for data engineers and data scientists who prefer Python over SQL for complex transformations.

In this tutorial, you'll learn the core concepts of Snowpark: the DataFrame API, which provides a lazy evaluation model similar to PySpark but optimized for Snowflake; stored procedures that run Python code directly on Snowflake's virtual warehouses; and how to build end-to-end applications. We'll cover real-world scenarios like incremental data loads, custom business logic, and debugging in production. By the end, you'll be able to write production-ready Snowpark code that is efficient, maintainable, and scalable.

Whether you're migrating from PySpark or starting fresh, Snowpark offers a familiar API with the benefits of Snowflake's performance and security. Let's dive in.

Setting Up Snowpark for Python

Before you can use Snowpark, you need to install the library and establish a session. Snowpark is available as a Python package that you can install via pip. It requires Python 3.8 or later. You'll also need a Snowflake account and appropriate credentials.

``bash pip install snowflake-snowpark-python ``

Then, create a session by providing your Snowflake connection details. It's best practice to use a configuration file or environment variables rather than hardcoding credentials. Here's an example using a JSON config file:

```python from snowflake.snowpark import Session import json

with open('connection_params.json') as f: connection_params = json.load(f)

session = Session.builder.configs(connection_params).create() ```

``json { "account": "your_account", "user": "your_user", "password": "your_password", "role": "your_role", "warehouse": "your_warehouse", "database": "your_database", "schema": "your_schema" } ``

Once the session is created, you can start using the DataFrame API. Always close the session when done:

``python session.close() ``

For production, consider using a connection pool or Snowflake's key-pair authentication for better security.

setup.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from snowflake.snowpark import Session
import json

# Load connection parameters
with open('connection_params.json') as f:
    connection_params = json.load(f)

# Create session
session = Session.builder.configs(connection_params).create()

# Verify connection
print(session.sql('SELECT current_version()').collect())

# Close session
session.close()
Output
[Row(CURRENT_VERSION()='8.4.1')]
💡Use Environment Variables for Credentials
📊 Production Insight
In production, use a dedicated service account with minimal privileges. Rotate credentials regularly and use network policies to restrict access.
🎯 Key Takeaway
Install Snowpark via pip, create a session with your credentials, and always close the session to free resources.

The DataFrame API: Lazy Evaluation and Pushdown

Snowpark's DataFrame API is similar to PySpark but with a key difference: all operations are lazy and pushed down to Snowflake for execution. This means you can chain multiple transformations without triggering any computation until you call an action like collect(), show(), or to_pandas(). This pushdown optimization ensures that only the necessary data is transferred over the network.

``python df = session.table('sales_data') ``

``python df = session.sql('SELECT * FROM sales_data WHERE year = 2023') ``

Now, let's perform some transformations. For example, filter, group by, and aggregate:

```python from snowflake.snowpark.functions import col, sum as sum_

result = (df .filter(col('amount') > 100) .group_by('region') .agg(sum_('amount').alias('total_sales')) .order_by('total_sales', ascending=False) )

result.show() ```

This will execute the SQL query on Snowflake and display the first 10 rows. You can also collect the results into a list of Row objects:

``python rows = result.collect() for row in rows: print(row.REGION, row.TOTAL_SALES) ``

One important aspect is that Snowpark DataFrames are immutable. Each transformation returns a new DataFrame. This allows for safe chaining and caching.

``python df1 = session.table('customers') df2 = session.table('orders') joined = df1.join(df2, df1.customer_id == df2.customer_id, join_type='inner') ``

Snowpark supports all standard join types: inner, left, right, full, cross, and semi/anti joins.

For complex expressions, use the functions module which provides SQL-like functions such as when, cast, datediff, etc.

dataframe_basics.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from snowflake.snowpark.functions import col, sum as sum_

# Read table
df = session.table('sales_data')

# Transformations (lazy)
result = (df
    .filter(col('amount') > 100)
    .group_by('region')
    .agg(sum_('amount').alias('total_sales'))
    .order_by('total_sales', ascending=False)
)

# Action: execute and show
result.show()

# Collect all rows
rows = result.collect()
for row in rows:
    print(f"Region: {row.REGION}, Total Sales: {row.TOTAL_SALES}")
Output
----------------------
|REGION |TOTAL_SALES|
----------------------
|East |50000 |
|West |45000 |
|North |30000 |
----------------------
Region: East, Total Sales: 50000
Region: West, Total Sales: 45000
Region: North, Total Sales: 30000
🔥Lazy Evaluation Benefits
📊 Production Insight
Always use explain() before running expensive operations in production. It helps you catch full table scans or inefficient joins early.
🎯 Key Takeaway
Snowpark DataFrames are lazy and push down operations to Snowflake. Use actions like show() or collect() to trigger execution.

Writing Stored Procedures with Python

Snowpark allows you to create stored procedures using Python. These procedures run on Snowflake's compute resources and can be used to encapsulate business logic, perform complex transformations, or orchestrate multiple steps. Stored procedures are created using the session.sproc.register() decorator or by calling session.sproc.create_from_function().

Here's a simple example of a stored procedure that takes a date range and returns aggregated sales:

```python from snowflake.snowpark import Session from snowflake.snowpark.functions import col, sum as sum_

def aggregate_sales(session: Session, start_date: str, end_date: str) -> list: df = session.table('sales_data') result = (df .filter(col('sale_date').between(start_date, end_date)) .group_by('region') .agg(sum_('amount').alias('total_sales')) .collect() ) return [row.as_dict() for row in result]

# Register the stored procedure session.sproc.register( func=aggregate_sales, name='aggregate_sales_proc', return_type=[] # List of dicts )

# Call the stored procedure result = session.sql("CALL aggregate_sales_proc('2023-01-01', '2023-12-31')").collect() print(result) ```

Note that the first parameter of the function must be session: Session. The return type can be a Snowpark data type or a Python type. For complex returns, you can use Variant or Array.

Stored procedures can also be created with dependencies on other Python packages. You can specify a list of packages in the packages parameter:

``python session.sproc.register( func=my_proc, name='my_proc', packages=['pandas', 'numpy'] ) ``

This is useful for data science workflows where you need libraries like scikit-learn or pandas.

Stored procedures can also be written as SQL scripts that call Python functions, but the Python approach is more flexible.

stored_procedure.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from snowflake.snowpark import Session
from snowflake.snowpark.functions import col, sum as sum_

def aggregate_sales(session: Session, start_date: str, end_date: str) -> list:
    df = session.table('sales_data')
    result = (df
        .filter(col('sale_date').between(start_date, end_date))
        .group_by('region')
        .agg(sum_('amount').alias('total_sales'))
        .collect()
    )
    return [row.as_dict() for row in result]

# Register
session.sproc.register(
    func=aggregate_sales,
    name='aggregate_sales_proc',
    return_type=[]
)

# Call
result = session.sql("CALL aggregate_sales_proc('2023-01-01', '2023-12-31')").collect()
print(result)
Output
[{'REGION': 'East', 'TOTAL_SALES': 50000}, {'REGION': 'West', 'TOTAL_SALES': 45000}, {'REGION': 'North', 'TOTAL_SALES': 30000}]
⚠ Stored Procedure Execution Context
📊 Production Insight
For production, use versioned stored procedures (e.g., my_proc_v1) to manage changes. Also, log important steps using Snowflake's event table for debugging.
🎯 Key Takeaway
Stored procedures allow you to run Python code on Snowflake. Register them with session.sproc.register() and call them via SQL.

User-Defined Functions (UDFs) and Vectorized UDFs

Snowpark supports creating Python UDFs that can be used in SQL queries or DataFrame transformations. There are two types: scalar UDFs (one row in, one row out) and vectorized UDFs (batch processing). Vectorized UDFs are more efficient because they process batches of rows using pandas DataFrames.

```python from snowflake.snowpark.types import FloatType from snowflake.snowpark.functions import udf

def discount(price: float) -> float: return price * 0.9

# Register as UDF discount_udf = udf(discount, return_type=FloatType(), input_types=[FloatType()], name='discount_udf')

# Use in DataFrame df = session.table('products') df_with_discount = df.select(col('product_id'), col('price'), discount_udf(col('price')).alias('discounted_price')) df_with_discount.show() ```

```python from snowflake.snowpark.types import FloatType, PandasSeriesType from snowflake.snowpark.functions import pandas_udf

@pandas_udf(return_type=FloatType(), input_types=[PandasSeriesType(FloatType())]) def vectorized_discount(price_series: pd.Series) -> pd.Series: return price_series * 0.9

# Use in DataFrame df_with_discount = df.select(col('product_id'), col('price'), vectorized_discount(col('price')).alias('discounted_price')) ```

Vectorized UDFs are preferred for performance because they reduce Python function call overhead.

You can also create UDFs that return tables (UDTFs) using the udtf decorator.

udf_example.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
from snowflake.snowpark.types import FloatType
from snowflake.snowpark.functions import udf, col

def discount(price: float) -> float:
    return price * 0.9

discount_udf = udf(discount, return_type=FloatType(), input_types=[FloatType()], name='discount_udf')

df = session.table('products')
df_with_discount = df.select(col('product_id'), col('price'), discount_udf(col('price')).alias('discounted_price'))
df_with_discount.show()
Output
--------------------------------------
|PRODUCT_ID | PRICE | DISCOUNTED_PRICE |
--------------------------------------
|1 | 100.0 | 90.0 |
|2 | 200.0 | 180.0 |
--------------------------------------
💡When to Use Vectorized UDFs
📊 Production Insight
Test UDFs with a small sample before deploying. Monitor resource usage; Python UDFs can be memory-intensive. Consider using Snowpark's built-in functions first.
🎯 Key Takeaway
UDFs let you extend Snowflake with custom Python logic. Use vectorized UDFs for better performance on large datasets.

Building Applications with Snowpark

Snowpark is not just for ad-hoc queries; you can build full applications that run on Snowflake. For example, you can create a data pipeline that reads from a stage, transforms data, and writes to a table. Or you can build a REST API that uses Snowpark to serve data.

Snowpark provides a client-side API that runs in your application environment (e.g., a Python script or a web server). The DataFrame operations are pushed down to Snowflake, but the orchestration logic runs locally. This is ideal for ETL jobs.

```python from snowflake.snowpark import Session from snowflake.snowpark.functions import col, max as max_

def incremental_load(session: Session, source_table: str, target_table: str, timestamp_col: str): # Get the last loaded timestamp from target last_load = session.table(target_table).select(max_(col(timestamp_col)).alias('max_ts')).collect()[0]['MAX_TS'] if last_load is None: last_load = '1900-01-01' # Read new data from source new_data = session.table(source_table).filter(col(timestamp_col) > last_load) # Write to target new_data.write.mode('append').save_as_table(target_table) print(f"Loaded {new_data.count()} rows")

# Run the pipeline incremental_load(session, 'raw_orders', 'orders', 'order_date') ```

For more complex applications, you can use Snowpark's DataFrame.save_as_table() with various modes: append, overwrite, errorifexists, etc.

You can also use Snowpark with orchestration tools like Airflow or Prefect. The Snowpark session can be created within a task and used to perform operations.

Another powerful feature is the ability to create Snowpark DataFrames from files in stages (e.g., Parquet, CSV). This allows you to process external data without loading it into a table first.

incremental_load.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
from snowflake.snowpark.functions import col, max as max_

def incremental_load(session, source_table, target_table, timestamp_col):
    last_load = session.table(target_table).select(max_(col(timestamp_col)).alias('max_ts')).collect()[0]['MAX_TS']
    if last_load is None:
        last_load = '1900-01-01'
    new_data = session.table(source_table).filter(col(timestamp_col) > last_load)
    new_data.write.mode('append').save_as_table(target_table)
    print(f"Loaded {new_data.count()} rows")

incremental_load(session, 'raw_orders', 'orders', 'order_date')
Output
Loaded 5000 rows
🔥Write Modes
📊 Production Insight
For production pipelines, implement error handling and retries. Use Snowflake's tasks and streams for scheduling and change tracking.
🎯 Key Takeaway
Snowpark can be used to build robust data pipelines and applications. Use write.save_as_table() to persist results.

Optimization and Best Practices

To get the best performance from Snowpark, follow these best practices:

  1. Use explain() to understand the query plan. This shows the SQL that will be executed. Look for full table scans, large shuffles, or inefficient joins.
  2. Filter early and often. Push filters down to reduce the amount of data processed.
  3. Use cache_result() for intermediate results that are reused. This materializes the DataFrame in Snowflake's cache, avoiding recomputation.
  4. Avoid using collect() on large DataFrames. It pulls all data to the client. Use show() for sampling or to_pandas() with limits.
  5. Use vectorized UDFs instead of scalar UDFs for better performance.
  6. Choose the right warehouse size. Larger warehouses have more parallelism. For complex transformations, a larger warehouse can significantly reduce runtime.
  7. Use partitioning and clustering keys on large tables to improve scan efficiency.
  8. Monitor query performance using Snowflake's query history and the QUERY_HISTORY view.

```python # Cache the filtered DataFrame filtered_df = df.filter(col('year') == 2023).cache_result()

# Use it multiple times without re-scanning agg1 = filtered_df.group_by('region').agg(sum_('sales')) agg2 = filtered_df.group_by('product').agg(avg_('price')) ```

Also, consider using Snowpark's DataFrame.union_all() and DataFrame.intersect() for set operations.

optimization.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
from snowflake.snowpark.functions import col, sum as sum_, avg

# Cache intermediate result
filtered_df = session.table('sales_data').filter(col('year') == 2023).cache_result()

# Use cached DataFrame
agg1 = filtered_df.group_by('region').agg(sum_('sales').alias('total_sales'))
agg2 = filtered_df.group_by('product').agg(avg('price').alias('avg_price'))

# Show results
agg1.show()
agg2.show()
Output
----------------------
|REGION |TOTAL_SALES|
----------------------
|East |50000 |
...
----------------------
-------------------------
|PRODUCT | AVG_PRICE |
-------------------------
|Widget | 19.99 |
...
-------------------------
⚠ Cache Result Limitations
📊 Production Insight
Set up alerts for long-running queries. Use Snowflake's resource monitors to control costs. Regularly review and tune your pipelines.
🎯 Key Takeaway
Optimize Snowpark by filtering early, caching reused DataFrames, and using vectorized UDFs. Monitor performance with explain() and query history.

Debugging and Logging in Snowpark

Debugging Snowpark code can be challenging because operations run remotely. Here are some techniques:

  1. Use df.explain() to see the SQL. This helps you understand what will be executed.
  2. Enable logging in stored procedures. You can use Python's logging module and write logs to a table or Snowflake's event table.
  3. Use session.sql() to run diagnostic queries. For example, check row counts or sample data.
  4. Use try-except blocks to catch exceptions and log them.
  5. For UDFs, test with small data first. You can create a temporary table with a few rows and test your UDF.

```python import logging

def my_proc(session: Session): logger = logging.getLogger('my_proc') logger.setLevel(logging.INFO) # Add a handler that writes to a table handler = logging.StreamHandler() logger.addHandler(handler) try: df = session.table('sales_data') logger.info(f"Processing {df.count()} rows") # ... transformations except Exception as e: logger.error(f"Error: {e}") raise ```

You can also use Snowflake's SYSTEM$LOG function to write logs to the event table.

For client-side debugging, use Python's debugger (pdb) or print statements. However, remember that DataFrame operations are lazy, so print statements inside transformations won't execute until an action is called.

debugging.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import logging

def my_proc(session):
    logger = logging.getLogger('my_proc')
    logger.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    logger.addHandler(handler)
    
    try:
        df = session.table('sales_data')
        logger.info(f"Processing {df.count()} rows")
        # Perform transformations
        result = df.filter(col('amount') > 100).group_by('region').count()
        result.show()
    except Exception as e:
        logger.error(f"Error: {e}")
        raise

# Call the procedure
my_proc(session)
Output
INFO:my_proc:Processing 100000 rows
----------------------
|REGION |COUNT |
----------------------
|East |20000 |
...
----------------------
💡Use Snowflake's Event Table
📊 Production Insight
In production, implement structured logging with severity levels. Monitor logs in Snowflake's event table for proactive issue detection.
🎯 Key Takeaway
Debug Snowpark by using explain(), logging, and testing with small data. Always handle exceptions in stored procedures.
● Production incidentPOST-MORTEMseverity: high

The Silent Data Skew: When Snowpark Stored Procedures Slowed to a Crawl

Symptom
A Snowpark stored procedure that processed daily sales data started timing out after 30 minutes, causing pipeline failures.
Assumption
The developer assumed the issue was due to increased data volume and tried scaling up the warehouse size, which didn't help.
Root cause
A new data source introduced a skewed join key (e.g., a default 'unknown' category with millions of rows), causing one node to handle most of the work.
Fix
The developer added a filter to exclude the skewed key before the join, then unioned it back after processing. They also used a hash join hint to redistribute the data.
Key lesson
  • Always profile your data distribution before joining on low-cardinality keys.
  • Use Snowpark's explain() method to understand the query plan and spot potential skew.
  • Consider using a salt key or pre-aggregation for skewed keys.
  • Monitor warehouse load and query performance metrics in Snowflake's query history.
Production debug guideSymptom to Action4 entries
Symptom · 01
Stored procedure times out or runs slowly
Fix
Check query history for long-running queries. Use df.explain() to see the plan. Look for full scans or large shuffles. Consider adding filters or partitioning.
Symptom · 02
Unexpected results or data corruption
Fix
Enable logging inside the stored procedure. Use session.sql() to run diagnostic queries. Validate row counts and sample data at each step.
Symptom · 03
Memory errors or 'Out of memory' exceptions
Fix
Reduce batch size in UDFs. Use vectorized UDFs instead of row-by-row. Increase warehouse size temporarily for testing.
Symptom · 04
Permission denied errors
Fix
Check that the stored procedure owner has the necessary grants on the underlying objects. Use SHOW GRANTS to verify.
★ Quick Debug Cheat SheetCommon Snowpark issues and immediate actions.
Slow DataFrame operation
Immediate action
Call `df.explain()` to see the plan.
Commands
df.explain()
df.queries['queries']
Fix now
Add a filter or use cache_result() if reused.
Stored procedure fails with 'Python error'+
Immediate action
Check the logs in Snowflake's event table.
Commands
SELECT * FROM TABLE(INFORMATION_SCHEMA.PROCEDURE_HISTORY(...))
CALL my_proc() WITH LOGGING
Fix now
Add try-except and log the error.
UDF returns wrong values+
Immediate action
Test the UDF with a small sample.
Commands
SELECT my_udf(col) FROM table LIMIT 10
CREATE OR REPLACE FUNCTION my_udf(...) RETURNS ... LANGUAGE PYTHON ...
Fix now
Add print statements and check logs.
FeatureSnowparkPySpark
Execution EngineSnowflake (pushdown)Spark cluster
LanguagePython (also Scala, Java)Python, Scala, Java, R
Lazy EvaluationYesYes
UDF SupportScalar, Vectorized, UDTFUDF, UDAF, Pandas UDF
Stored ProceduresYes (Python)No (but can run on cluster)
Setup ComplexityLow (no cluster)High (cluster management)
Cost ModelPay per warehouse usagePay per cluster (EC2)
Data SourcesSnowflake, stagesMany (HDFS, S3, etc.)
⚙ Quick Reference
7 commands from this guide
FileCommand / CodePurpose
setup.pyfrom snowflake.snowpark import SessionSetting Up Snowpark for Python
dataframe_basics.pyfrom snowflake.snowpark.functions import col, sum as sum_The DataFrame API
stored_procedure.pyfrom snowflake.snowpark import SessionWriting Stored Procedures with Python
udf_example.pyfrom snowflake.snowpark.types import FloatTypeUser-Defined Functions (UDFs) and Vectorized UDFs
incremental_load.pyfrom snowflake.snowpark.functions import col, max as max_Building Applications with Snowpark
optimization.pyfrom snowflake.snowpark.functions import col, sum as sum_, avgOptimization and Best Practices
debugging.pydef my_proc(session):Debugging and Logging in Snowpark

Key takeaways

1
Snowpark provides a Pythonic way to interact with Snowflake, with a DataFrame API that pushes down operations for performance.
2
Stored procedures and UDFs allow you to run custom Python code on Snowflake's compute, enabling complex transformations and business logic.
3
Optimization techniques like filtering early, caching, and using vectorized UDFs are crucial for production workloads.
4
Debugging Snowpark requires understanding lazy evaluation and using tools like explain(), logging, and Snowflake's event table.
5
Always follow security best practices
use environment variables for credentials, close sessions, and monitor resource usage.

Common mistakes to avoid

4 patterns
×

Calling `collect()` on a large DataFrame and pulling all data to the client.

×

Not closing the Snowpark session, leading to resource leaks.

×

Using scalar UDFs for large datasets instead of vectorized UDFs.

×

Hardcoding credentials in the code.

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is lazy evaluation in Snowpark and why is it beneficial?
Q02SENIOR
How do you create a stored procedure in Snowpark that takes a table name...
Q03SENIOR
Explain the difference between scalar UDFs and vectorized UDFs in Snowpa...
Q04SENIOR
How can you optimize a Snowpark pipeline that joins two large tables?
Q01 of 04JUNIOR

What is lazy evaluation in Snowpark and why is it beneficial?

ANSWER
Lazy evaluation means that DataFrame transformations are not executed immediately; they are recorded and optimized into a single query plan. This allows Snowflake to push down operations and minimize data movement, improving performance.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
What is the difference between Snowpark and PySpark?
02
Can I use Snowpark with other Python libraries like pandas or scikit-learn?
03
How do I handle errors in Snowpark stored procedures?
04
Is Snowpark free?
05
Can I use Snowpark to read data from external stages?
N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Drawn from code that ran under real load.

Follow
Verified
production tested
2026-07-17T18:30:00
last updated
2,439
articles · all by Naren
🔥

That's Snowflake. Mark it forged?

6 min read · try the examples if you haven't

Previous
Dynamic Tables: Declarative Data Pipelines
18 / 33 · Snowflake
Next
Monitoring: Account Usage, Query History, and Observability