Home Database Streams and Tasks: Automate Real-Time Data Pipelines
Intermediate 4 min · July 17, 2026
Streams and Tasks: Automated Real-Time Data Pipelines

Streams and Tasks: Automate Real-Time Data Pipelines

Learn to build automated real-time data pipelines using Snowflake streams and tasks.

N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Everything here is grounded in real deployments.

Follow
Production
production tested
July 17, 2026
last updated
2,439
articles · all by Naren
Before you start⏱ 15-20 min read
  • Basic SQL knowledge (SELECT, INSERT, UPDATE, DELETE).
  • A Snowflake account with access to create streams and tasks.
  • Familiarity with Snowflake warehouses and roles.
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Streams capture CDC (Change Data Capture) on tables.
  • Tasks schedule SQL statements, including DML on streams.
  • Combine streams and tasks for automated incremental processing.
  • Use tasks with schedules or DAG dependencies.
  • Monitor with TASK_HISTORY and stream offsets.
✦ Definition~90s read
What is Streams and Tasks?

Snowflake streams and tasks are features that enable automated, incremental data pipelines by capturing changes (streams) and scheduling SQL execution (tasks) without external tools.

Think of a stream as a security camera that records every change (insert, update, delete) on a table.
Plain-English First

Think of a stream as a security camera that records every change (insert, update, delete) on a table. A task is like a robot that checks the camera feed every minute and processes only the new changes. Together, they automate data movement without manual intervention.

In modern data platforms, real-time data processing is critical for timely insights. Snowflake provides two powerful features—streams and tasks—that enable automated, incremental data pipelines without external tools. Streams track changes (inserts, updates, deletes) on a table, while tasks execute SQL statements on a schedule or based on dependencies. Together, they allow you to build event-driven workflows that process data as it arrives, reducing latency and manual effort.

Imagine you have a raw sales table that receives thousands of new records every minute. You need to transform and load that data into a reporting table. Without automation, you'd run periodic batch jobs, which could miss recent changes or overload the system. With streams and tasks, you can capture only the new or changed rows and process them immediately, keeping your reporting table up-to-date with minimal overhead.

This tutorial will guide you through creating streams and tasks, writing efficient DML statements, handling common pitfalls, and debugging production issues. By the end, you'll be able to build robust, automated pipelines that scale with your data.

What are Snowflake Streams?

A Snowflake stream is an object that records data manipulation language (DML) changes made to a table, including inserts, updates, and deletes. It provides a change data capture (CDC) mechanism that tracks row-level changes with before and after images. Streams are append-only and store the change records for a configurable retention period (default 14 days).

When you create a stream on a table, it captures all DML changes that occur after the stream is created. You can query the stream like a table to see the changes. Each row in the stream includes metadata columns: METADATA$ACTION (INSERT, DELETE, UPDATE), METADATA$ISUPDATE (true for updates), and METADATA$ROW_ID.

Streams are ideal for incremental processing because they only show new or changed rows since the last time the stream was consumed. Consumption happens when you execute a DML statement that reads from the stream (e.g., INSERT INTO target SELECT ... FROM stream). After consumption, the stream offset advances, and the next query will show only subsequent changes.

Key points
  • Streams are free to create; you pay only for the storage of change records.
  • Streams do not affect the performance of the source table.
  • You can create multiple streams on the same table.
  • Streams can be created on standard tables, views (with caveats), and shared tables.
create_stream.sqlSQL
1
2
3
4
5
6
7
8
-- Create a stream on the raw_sales table
CREATE STREAM raw_sales_stream ON TABLE raw_sales;

-- Query the stream to see changes
SELECT * FROM raw_sales_stream;

-- Check the stream offset timestamp
SELECT SYSTEM$STREAM_GET_TABLE_TIMESTAMP('raw_sales_stream');
Output
METADATA$ACTION | METADATA$ISUPDATE | METADATA$ROW_ID | SALE_ID | AMOUNT | SALE_DATE
INSERT | false | abc123 | 1001 | 250.00 | 2025-03-01
INSERT | false | def456 | 1002 | 150.00 | 2025-03-01
💡Stream Retention
📊 Production Insight
In production, always ensure your task consumes the stream within the retention window. If your pipeline has downtime, you may need to recreate the stream or handle backfill separately.
🎯 Key Takeaway
Streams capture DML changes and provide a way to process only new or modified rows incrementally.

What are Snowflake Tasks?

A Snowflake task is a scheduled object that executes a single SQL statement or a call to a stored procedure. Tasks can be used to automate data transformation, loading, and other maintenance operations. They support scheduling using cron expressions or simple intervals (e.g., '5 MINUTE'). Tasks can also be chained together in a DAG (Directed Acyclic Graph) using task dependencies.

When you create a task, you define its schedule and the SQL to execute. The task runs as the role that owns it (or the role specified with EXECUTE AS). You can also set a task to run after another task completes, enabling complex workflows.

Tasks are commonly used with streams to create automated pipelines: a task runs on a schedule, reads from a stream, and performs DML to consume the stream and load data into target tables.

Key points
  • Tasks are charged per execution based on warehouse usage.
  • Tasks can be suspended and resumed.
  • You can monitor task history using TASK_HISTORY function.
  • Tasks support error handling with AFTER_FAILURE and conditional execution.
create_task.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
-- Create a task that runs every 5 minutes
CREATE TASK process_sales_task
  WAREHOUSE = my_wh
  SCHEDULE = '5 MINUTE'
AS
  INSERT INTO sales_report (sale_id, amount, sale_date)
  SELECT sale_id, amount, sale_date
  FROM raw_sales_stream;

-- Resume the task to start execution
ALTER TASK process_sales_task RESUME;
Output
Task created and resumed successfully.
🔥Task Scheduling
📊 Production Insight
Always specify a warehouse for your task. If you omit it, the task will use the warehouse of the session that created it, which may not be available when the task runs.
🎯 Key Takeaway
Tasks automate SQL execution on a schedule or after other tasks, enabling hands-off data pipelines.

Combining Streams and Tasks for Incremental Processing

The real power of Snowflake comes from combining streams and tasks. A typical pattern is: 1. Create a stream on a source table. 2. Create a task that runs on a schedule (e.g., every minute). 3. The task executes a DML statement that reads from the stream and writes to a target table. 4. The DML consumes the stream, advancing its offset.

This pattern enables near-real-time data pipelines without external orchestration. For example, you can process sales data as it arrives, transform it, and load it into a reporting table.

To handle updates and deletes, use MERGE instead of INSERT. MERGE can insert new rows, update existing ones, and delete rows based on the stream's METADATA$ACTION.

Example: A task that runs every minute to process changes from raw_sales_stream into sales_report, handling all three DML operations.

merge_task.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- Create a task that uses MERGE to handle all changes
CREATE TASK merge_sales_task
  WAREHOUSE = my_wh
  SCHEDULE = '1 MINUTE'
AS
  MERGE INTO sales_report t
  USING (
    SELECT 
      sale_id,
      amount,
      sale_date,
      METADATA$ACTION AS action,
      METADATA$ISUPDATE AS is_update
    FROM raw_sales_stream
  ) s ON t.sale_id = s.sale_id
  WHEN MATCHED AND s.action = 'DELETE' THEN DELETE
  WHEN MATCHED AND s.is_update = 'TRUE' THEN UPDATE SET t.amount = s.amount, t.sale_date = s.sale_date
  WHEN NOT MATCHED AND s.action = 'INSERT' THEN INSERT (sale_id, amount, sale_date) VALUES (s.sale_id, s.amount, s.sale_date);

ALTER TASK merge_sales_task RESUME;
Output
Task created and resumed.
⚠ MERGE and Streams
📊 Production Insight
When using MERGE, be careful with the ON clause. If the source has multiple rows for the same key (e.g., multiple updates), MERGE may produce non-deterministic results. Use a subquery with ROW_NUMBER() to deduplicate if needed.
🎯 Key Takeaway
Use MERGE in tasks to handle inserts, updates, and deletes from a stream in a single atomic operation.

Task Dependencies and DAGs

Snowflake tasks can be organized into a DAG (Directed Acyclic Graph) where one task runs after another. This allows you to build multi-step pipelines. For example, Task A loads raw data, Task B transforms it, and Task C loads the final report.

To create a dependency, use the AFTER keyword when creating a task. The dependent task will start automatically after the predecessor task completes successfully. You can also specify conditions using WHEN to control execution.

DAGs are useful for complex workflows where each step depends on the previous one. However, they can be harder to debug because failures cascade.

Example: Two tasks where the second runs after the first.

task_dag.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- Create first task
CREATE TASK load_raw_task
  WAREHOUSE = my_wh
  SCHEDULE = '5 MINUTE'
AS
  INSERT INTO raw_sales SELECT * FROM staging_table;

-- Create second task that runs after first
CREATE TASK transform_task
  WAREHOUSE = my_wh
  AFTER load_raw_task
AS
  MERGE INTO sales_report ...;

-- Resume both tasks
ALTER TASK load_raw_task RESUME;
ALTER TASK transform_task RESUME;
Output
Tasks created and resumed.
💡DAG Execution Order
📊 Production Insight
In production, use conditional expressions in the WHEN clause to skip tasks if there is no new data. For example: WHEN SYSTEM$STREAM_HAS_DATA('my_stream')
🎯 Key Takeaway
Task dependencies allow you to build multi-step pipelines that execute in a defined order.

Monitoring and Debugging Streams and Tasks

Monitoring is crucial for production pipelines. Snowflake provides several views and functions to track task execution and stream status.

  • TASK_HISTORY: Shows task runs, including start time, end time, state (SUCCEEDED, FAILED, SKIPPED), and error messages.
  • STREAM_HISTORY: Shows stream consumption events.
  • SYSTEM$STREAM_GET_TABLE_TIMESTAMP: Returns the timestamp of the last change captured by the stream. If NULL, the stream has no data.
  • SYSTEM$STREAM_HAS_DATA: Returns TRUE if the stream has unprocessed changes.

You can also query the stream directly to see pending changes.

Common debugging steps: 1. Check if the stream has data: SELECT SYSTEM$STREAM_HAS_DATA('stream_name'); 2. Check task history: SELECT * FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY()) WHERE TASK_NAME = 'my_task' ORDER BY SCHEDULED_TIME DESC; 3. If task fails, examine the error message in TASK_HISTORY. 4. If stream is stale, recreate it.

monitoring.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
-- Check if stream has data
SELECT SYSTEM$STREAM_HAS_DATA('raw_sales_stream');

-- View recent task history
SELECT *
FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY())
WHERE TASK_NAME = 'MERGE_SALES_TASK'
ORDER BY SCHEDULED_TIME DESC
LIMIT 10;

-- Check stream offset timestamp
SELECT SYSTEM$STREAM_GET_TABLE_TIMESTAMP('raw_sales_stream');
Output
SYSTEM$STREAM_HAS_DATA('raw_sales_stream'): TRUE
SCHEDULED_TIME | STATE | ERROR_MESSAGE
2025-03-01 10:05:00 | SUCCEEDED | NULL
2025-03-01 10:00:00 | SUCCEEDED | NULL
SYSTEM$STREAM_GET_TABLE_TIMESTAMP('raw_sales_stream'): 2025-03-01 10:05:00.000
🔥Task History Retention
📊 Production Insight
Set up alerts for failed tasks using Snowflake's notification integration (e.g., email, webhook) to respond quickly to issues.
🎯 Key Takeaway
Regularly monitor task history and stream status to ensure your pipeline is healthy.

Best Practices for Production Pipelines

  1. Use MERGE for idempotency: If a task runs multiple times (e.g., due to retries), MERGE ensures no duplicates.
  2. Set appropriate schedule: Choose a schedule that balances latency and cost. For near-real-time, use 1 minute; for batch, use longer intervals.
  3. Handle stream staleness: If a stream becomes stale, recreate it and backfill missing data.
  4. Use conditional tasks: Add a WHEN clause to skip execution if the stream has no data, saving warehouse credits.
  5. Monitor costs: Tasks consume warehouse credits. Use auto-suspend and appropriate warehouse size.
  6. Test in a development environment: Before deploying to production, test the pipeline with sample data.
  7. Document your pipeline: Keep track of stream and task definitions, dependencies, and schedules.
conditional_task.sqlSQL
1
2
3
4
5
6
7
8
CREATE TASK conditional_merge_task
  WAREHOUSE = my_wh
  SCHEDULE = '1 MINUTE'
  WHEN SYSTEM$STREAM_HAS_DATA('raw_sales_stream')
AS
  MERGE INTO sales_report ...;

ALTER TASK conditional_merge_task RESUME;
Output
Task created with condition.
⚠ Conditional Tasks and Stream Consumption
📊 Production Insight
Always include error handling in your tasks. Consider using a stored procedure with try-catch logic for complex transformations.
🎯 Key Takeaway
Use conditional tasks to avoid unnecessary executions and reduce costs.
● Production incidentPOST-MORTEMseverity: high

The Stale Stream That Broke the Pipeline

Symptom
The target table had duplicate rows and the task ran longer each time.
Assumption
The developer assumed streams automatically advance offsets after each task execution.
Root cause
The task used a SELECT from the stream inside a transaction but didn't consume the stream (no DML). The stream offset never advanced, so the same changes were reprocessed.
Fix
Changed the task to perform a DML operation (e.g., INSERT INTO target SELECT ... FROM stream) to consume the stream and advance the offset.
Key lesson
  • Always consume a stream with a DML statement (INSERT, UPDATE, DELETE, MERGE) to advance its offset.
  • Avoid reading from a stream multiple times without consuming it.
  • Use MERGE to handle inserts, updates, and deletes in one statement.
  • Monitor stream offset using SYSTEM$STREAM_GET_TABLE_TIMESTAMP.
  • Test tasks in a development environment before production.
Production debug guideSymptom to Action4 entries
Symptom · 01
Task runs but no rows processed
Fix
Check if the stream has data: SELECT SYSTEM$STREAM_GET_TABLE_TIMESTAMP('stream_name'); if NULL, no changes. Also verify the task's SQL logic.
Symptom · 02
Duplicate rows in target table
Fix
Check if the stream offset is advancing. Ensure the task uses a DML statement that consumes the stream. Use MERGE with a unique key to avoid duplicates.
Symptom · 03
Task fails with 'Stream offset is stale'
Fix
The stream has been open too long without consumption. Recreate the stream or ensure the task runs frequently enough. Increase task schedule frequency.
Symptom · 04
Task not running at scheduled time
Fix
Check if the task is suspended: SHOW TASKS; if suspended, resume with ALTER TASK ... RESUME. Also verify the schedule syntax (e.g., '5 MINUTE').
★ Quick Debug Cheat SheetCommon issues and immediate actions for Snowflake streams and tasks.
Stream has data but task does nothing
Immediate action
Verify task SQL includes DML on the stream
Commands
SELECT * FROM stream_name;
SELECT SYSTEM$STREAM_GET_TABLE_TIMESTAMP('stream_name');
Fix now
Rewrite task to use INSERT INTO target SELECT ... FROM stream
Task fails with 'Stream offset is stale'+
Immediate action
Recreate the stream
Commands
DROP STREAM IF EXISTS stream_name;
CREATE STREAM stream_name ON TABLE source_table;
Fix now
Recreate stream and ensure task consumes it within the retention period
Duplicates in target table+
Immediate action
Switch to MERGE statement
Commands
SELECT COUNT(*), key_column FROM target GROUP BY key_column HAVING COUNT(*) > 1;
DELETE FROM target WHERE ...;
Fix now
Use MERGE with a unique key to upsert
Task not running+
Immediate action
Check task state and schedule
Commands
SHOW TASKS LIKE '%task_name%';
SELECT * FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY()) WHERE STATE = 'SCHEDULED';
Fix now
ALTER TASK task_name RESUME;
FeatureStreamsTasks
PurposeCapture DML changes (CDC)Schedule SQL execution
ConsumptionConsumed by DML statementsExecuted on schedule or after other tasks
StateAppend-only, offset advances on consumptionSuspended or resumed
Retention14 days default (up to 90)N/A
CostStorage for change recordsWarehouse usage per execution
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
create_stream.sqlCREATE STREAM raw_sales_stream ON TABLE raw_sales;What are Snowflake Streams?
create_task.sqlCREATE TASK process_sales_taskWhat are Snowflake Tasks?
merge_task.sqlCREATE TASK merge_sales_taskCombining Streams and Tasks for Incremental Processing
task_dag.sqlCREATE TASK load_raw_taskTask Dependencies and DAGs
monitoring.sqlSELECT SYSTEM$STREAM_HAS_DATA('raw_sales_stream');Monitoring and Debugging Streams and Tasks
conditional_task.sqlCREATE TASK conditional_merge_taskBest Practices for Production Pipelines

Key takeaways

1
Streams capture DML changes incrementally and are consumed by DML statements.
2
Tasks automate SQL execution on a schedule or after other tasks.
3
Combine streams and tasks with MERGE for idempotent, near-real-time pipelines.
4
Monitor task history and stream status to detect issues early.
5
Use conditional tasks and proper error handling to build robust production pipelines.

Common mistakes to avoid

4 patterns
×

Reading from a stream without consuming it (e.g., SELECT without DML).

×

Using INSERT instead of MERGE when the source has updates or deletes.

×

Forgetting to resume a task after creation.

×

Setting a task schedule too frequently (e.g., every 10 seconds) without considering warehouse startup time.

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is a Snowflake stream and how does it work?
Q02SENIOR
How would you design a near-real-time pipeline using streams and tasks?
Q03SENIOR
What happens if a task that consumes a stream fails? Does the stream off...
Q01 of 03JUNIOR

What is a Snowflake stream and how does it work?

ANSWER
A Snowflake stream is an object that records DML changes (inserts, updates, deletes) on a table. It provides a CDC mechanism. When you query a stream, you see the changes since the last consumption. Consuming the stream (via DML) advances its offset.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I create multiple streams on the same table?
02
What happens if a task fails?
03
How do I backfill data if a stream becomes stale?
04
Can tasks run stored procedures?
05
What is the difference between a stream and a materialized view?
N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Everything here is grounded in real deployments.

Follow
Verified
production tested
July 17, 2026
last updated
2,439
articles · all by Naren
🔥

That's Snowflake. Mark it forged?

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

Previous
Time Travel, Zero-Copy Cloning, and Data Restoration
8 / 33 · Snowflake
Next
Data Sharing, Listings, and the Marketplace