TL;DR
Snowflake tasks are built-in objects that run SQL or a stored procedure for you, on a schedule or when new data arrives. You create one with CREATE TASK, and it stays suspended until you resume it. A schedule is either a fixed interval or a CRON expression with a time zone. Related tasks can be chained into a task graph, where one root task starts the others in order. Compute comes from serverless resources that Snowflake sizes, or from a warehouse you manage. For production, add timeouts, retries, a final alert step, and a daily check of task history.
Key Takeaways A Snowflake task runs one SQL statement, a procedure call or a scripting block, and every new task starts suspended. Schedules use a fixed interval or CRON with a time zone, while triggered tasks wait for a stream to report new rows. Serverless tasks suit short, steady jobs, and warehouse tasks suit busy shared warehouses or jobs larger than XXLARGE. Task graphs chain up to 1,000 tasks with AFTER, run siblings in parallel and can close with a finalizer. Timeouts, failure limits, automatic retries and RETRY LAST decide how a failed night recovers. TASK_HISTORY, COMPLETE_TASK_GRAPHS and SERVERLESS_TASK_HISTORY show what ran, what failed and what it cost. Watch on YouTube
Snowflake CoCo 2026: How It Transforms Enterprise Data Engineering
Kanerika walks through how Snowflake’s AI coding assistant helps data teams write, test and maintain the SQL pipelines that tasks schedule.
The 2 A.M. Page About a Stale Revenue Dashboard At 2:07 a.m. the on-call data engineer’s phone lights up. The nightly load behind the finance dashboard failed at 1:40, and the 7 a.m. revenue review will open on yesterday’s numbers. In Snowsight she finds the root task marked FAILED, three child tasks never started, and not a single alert in the team channel.
Nothing about the failure was exotic. A source table landed late and a MERGE timed out.
On top of that, the graph had no retry, no final alert step and no owner on a notification list. Snowflake tasks handle every one of those problems natively, as long as the graph is designed for the bad night rather than the good one.
What Are Snowflake Tasks? A task is a Snowflake object that runs a piece of work for you on a timetable or when an event occurs. Snowflake’s introduction to tasks describes them as the built-in way to automate data processing inside the platform. The task stores its schedule, its compute choice, its owner and its code in one schema object.
That makes Snowflake tasks the native answer to an old warehouse question. Who runs the SQL at 2 a.m. when nobody is logged in?
In practice, teams use them for incremental loads into reporting tables, nightly aggregates, reconciliation queries and data quality checks in Snowflake . They also handle housekeeping, such as purging old staging rows.
What a Task Can Run Each task holds exactly one piece of executable code after its AS keyword. That can be a single SQL statement such as an INSERT or MERGE, or a CALL to a stored procedure. It can also be an anonymous Snowflake Scripting block wrapped in BEGIN and END.
Procedures open the door to Python, Java, Scala and JavaScript logic, which our guide to Snowflake stored procedures covers in depth. When a job needs several statements, a scripting block keeps them together, and a procedure keeps them reusable and testable.
Standalone Tasks vs Task Graphs A standalone task has its own schedule and runs alone. A task graph links several tasks so that a root task starts the run and child tasks follow in dependency order. Snowflake also calls this a DAG, short for directed acyclic graph , because work only flows forward and never loops back.
A practical rule helps when deciding how to split work. If two steps share a failure fate and a retry policy, keep them in one task. If one step can fail without poisoning the others, or could run in parallel, give it its own task inside a graph.
Where Tasks Sit Next to Streams, Snowpipe, and Dynamic Tables Tasks schedule and orchestrate, but they do not capture changes or load files. Change capture belongs to streams, explained in our guide to Snowflake streams , and continuous file loading belongs to Snowpipe . Declarative pipelines that refresh to a freshness target belong to Snowflake dynamic tables .
In a typical design these pieces meet at the task. Snowpipe lands files, a stream records what changed, and a task decides when to process that change. For the wider pattern, see our overview of Snowflake data engineering .
Kanerika Service
Snowflake Implementation and Optimization
Kanerika, a Snowflake Select Tier Partner, designs Snowflake platforms, pipelines and task orchestration that hold up in production.
Explore Snowflake Services How to Create a Snowflake Task Creating a task takes one statement, but three decisions come first. You need a role with the right privileges, a choice of compute, and a schedule or trigger. Settle those and the CREATE TASK statement almost writes itself.
Privileges to Sort Out First Snowflake checks privileges twice, once when you create the task and again when you resume or run it. The owner role needs USAGE on the database and schema, plus CREATE TASK on the schema. Serverless tasks also need the account-level EXECUTE MANAGED TASK privilege, while warehouse tasks need USAGE on the warehouse.
Privilege Granted on Needed for USAGE Database and schema Creating and running any task CREATE TASK Schema Creating the task EXECUTE TASK Account Letting the owner role run tasks at all EXECUTE MANAGED TASK Account Serverless tasks only USAGE Warehouse User-managed tasks only OPERATE Task Letting another role suspend, resume or run it
The privilege people forget is EXECUTE TASK on the account. Without it, CREATE TASK still succeeds, but resuming or running the task fails the privilege check. Revoking it later stops every task that role owns from starting.
By default a task runs as a Snowflake system service with the owner role’s privileges. That way it keeps running after the engineer who built it moves on.
Some masking or row access policies, however, depend on the querying user. In that case the EXECUTE AS USER option runs the task on behalf of a named service user. Read it alongside our notes on Snowflake security .
Writing Your First CREATE TASK Here is a small, realistic task, which refreshes a daily sales summary at 1:15 a.m. Pacific on a small warehouse. It also gives up after 30 minutes and suspends itself after three straight failures.
CREATE OR REPLACE TASK analytics.ops.refresh_daily_sales
WAREHOUSE = transform_wh
SCHEDULE = 'USING CRON 15 1 * * * America/Los_Angeles'
USER_TASK_TIMEOUT_MS = 1800000 -- 30 minutes
SUSPEND_TASK_AFTER_NUM_FAILURES = 3
COMMENT = 'Nightly sales summary for the finance dashboard'
AS
MERGE INTO analytics.marts.daily_sales t
USING (
SELECT order_date, region, SUM(amount) AS revenue
FROM analytics.staging.orders
WHERE order_date >= DATEADD(day, -3, CURRENT_DATE())
GROUP BY order_date, region
) s
ON t.order_date = s.order_date AND t.region = s.region
WHEN MATCHED THEN UPDATE SET t.revenue = s.revenue
WHEN NOT MATCHED THEN INSERT (order_date, region, revenue)
VALUES (s.order_date, s.region, s.revenue);One choice in that script matters more than it looks. The MERGE reprocesses a three-day window, so a rerun after a failure corrects rows instead of duplicating them. The full parameter list lives in the CREATE TASK reference , and we would skim it before anything goes to production.
Resume, Suspend, and Run It on Demand Every new task starts suspended, and so does every task you replace with CREATE OR REPLACE. Nothing runs until you resume it.
-- Run once now to test, without waiting for the schedule
EXECUTE TASK analytics.ops.refresh_daily_sales;
-- Start following the schedule
ALTER TASK analytics.ops.refresh_daily_sales RESUME;
-- Pause it for maintenance
ALTER TASK analytics.ops.refresh_daily_sales SUSPEND;
-- Check state, schedule and owner
SHOW TASKS LIKE 'refresh_daily_sales' IN SCHEMA analytics.ops;
DESCRIBE TASK analytics.ops.refresh_daily_sales;EXECUTE TASK is the safest first test because it uses the real owner role and the real compute. If the manual run fails on privileges, the scheduled run would have failed the same way at 1:15 a.m., only with nobody watching.
Scheduling Snowflake Tasks: Intervals, CRON, and Triggers A task starts in one of three ways. It follows a fixed interval, follows a CRON expression, or waits for a stream to report new data. A fourth path, EXECUTE TASK, covers manual runs and calls from outside tools.
Fixed Intervals An interval schedule such as SCHEDULE = ’15 MINUTES’ fits jobs where only frequency matters, like polling a staging table or purging logs. When a run has to land at a particular clock time, use CRON instead.
Snowflake also runs only one instance of a scheduled task at a time. If a run is still going when the next slot arrives, that slot is skipped rather than stacked on top.
CRON Expressions and Time Zones CRON schedules pin a run to the clock. The expression has five fields for minute, hour, day of month, month and day of week, followed by a time zone.
For example, ‘0 6 * * 1-5 America/New_York’ means 6 a.m. Eastern on weekdays, and the standard cron format explains the field order.
Two habits save pain later. First, use the time zone the business thinks in, and test any schedule that sits close to a daylight saving change.
Second, copy a habit from Snowflake’s own examples, which schedule on off-the-hour minutes such as :18 or :37 instead of :00. That way jobs do not all start at the top of the hour.
Triggered Tasks and the WHEN Clause A triggered task has no schedule. It runs when a stream has data, using WHEN SYSTEM$STREAM_HAS_DATA(‘stream_name’), and skips without using compute when nothing changed. As a result, it is a cheap fit for data that arrives at unpredictable times.
The triggered task documentation says these tasks run at most every 30 seconds by default, and one parameter can lower that to 10 seconds. Serverless triggered tasks also need a TARGET_COMPLETION_INTERVAL. A WHEN clause can sit beside a schedule too, so an hourly task only does work when the stream holds rows.
CREATE TASK analytics.ops.apply_order_changes
TARGET_COMPLETION_INTERVAL = '15 MINUTES'
WHEN SYSTEM$STREAM_HAS_DATA('analytics.staging.orders_stream')
AS
CALL analytics.ops.apply_order_changes_proc();How streams track offsets is a topic for the streams guide. For scheduling, though, one rule matters. The task that consumes a stream advances its offset, so a second task reading it would find nothing left.
Triggered tasks also work on streams over data a provider shares with you, a setup covered in our guide to Snowflake data sharing .
Choosing a Start Method Each start method suits a different kind of job, and the table below sums up when to reach for which one.
Start method How you set it Runs when Good fit Interval SCHEDULE = ’30 MINUTES’ A fixed gap has passed Frequent polling, housekeeping CRON SCHEDULE = ‘USING CRON 7 1 * * * UTC’ The clock matches the expression Business reports, daily cutoffs Triggered WHEN SYSTEM$STREAM_HAS_DATA(…) A stream has new rows Unpredictable arrivals, low latency Schedule plus WHEN Both clauses The schedule fires and the stream has rows Hourly work that is often empty Manual EXECUTE TASK A person or tool calls it Tests, backfills, outside schedulers
Most production estates end up mixing all five. CRON drives the business-facing graphs, and triggered tasks handle the trickle of change between them. EXECUTE TASK then covers backfills when a source system replays a week of data.
Serverless vs User-Managed Warehouse Tasks Every task needs compute, and the choice shapes both cost and how well the job keeps its schedule. Leave out the WAREHOUSE parameter and the task is serverless. Name a warehouse and the task is user-managed.
How Serverless Tasks Size Themselves With serverless tasks, Snowflake studies recent runs of the same task and picks a compute size it expects to finish on time. Two parameters set the floor and ceiling, and the largest serverless run equals an XXLARGE warehouse. If a run overshoots its interval, Snowflake sizes the next one up.
Billing follows the compute actually used, so a short job does not pay for a warehouse idling afterward. One catch matters in practice. CREATE OR REPLACE TASK throws away the run history Snowflake uses for sizing, so prefer ALTER TASK for small changes to a serverless task.
When a Dedicated Warehouse Wins User-managed tasks run on a warehouse you size and pay for by the second, with a 60-second minimum each time it resumes. Snowflake’s own guidance favours them when a warehouse is already busy with several concurrent tasks. They also suit unpredictable loads and jobs that need more than an XXLARGE.
Shared warehouses bring one side effect. A task scheduled on a busy warehouse can queue behind dashboards and ad hoc queries, so its schedule slips even though the SQL is fast. Our explainer on Snowflake architecture covers how warehouses share and isolate compute.
Factor Serverless tasks User-managed warehouse tasks Who sizes compute Snowflake, from recent runs Your team Billing Compute actually used Warehouse time per second, 60-second minimum per resume Best fit Short, steady jobs on an under-used warehouse Busy warehouses with many concurrent tasks Size ceiling XXLARGE equivalent Any warehouse size Keeping to schedule Sizes up when a run overshoots its interval Depends on warehouse load and queueing Extra privilege EXECUTE MANAGED TASK USAGE on the warehouse
Mixing Compute Models Inside One Graph The compute choice is made per task, not per graph. A heavy MERGE can run on a dedicated LARGE warehouse while the small audit and notification tasks around it stay serverless. That split keeps the expensive warehouse busy only for the step that needs it.
Whatever you pick, measure it. Compare credits per successful run for a week under each model before settling, and use our Snowflake cost optimization playbook for the wider warehouse picture.
Checklist
Snowflake Performance Optimization Checklist
Check warehouse sizing, query patterns and credit use before you settle on serverless or warehouse compute for your tasks.
Get the Checklist → Building Task Graphs That Hold Up in Production Task graphs are where native scheduling turns into orchestration. One schedule drives many steps, independent steps run side by side, and a cleanup step still runs whatever happened along the way.
Root Tasks, Child Tasks, and AFTER The root task carries the schedule. Each child names its parents with AFTER, and Snowflake starts it once every parent has finished successfully. The task graph documentation allows up to 1,000 tasks in one graph and up to 100 parents and 100 children per task.
All tasks in a graph must share one owner role and live in one schema. That rule surprises teams who organise code by layer across schemas, so choose the graph’s home schema before writing the first task.
Fan-Out and Fan-In Fan-out happens when several children share a parent, because Snowflake runs them in parallel. Fan-in happens when one child lists several parents, because it waits for all of them. Together they model the usual nightly build, where staging finishes, two marts load side by side, and a summary waits for both.
CREATE TASK ops.nightly_root
SCHEDULE = 'USING CRON 7 1 * * * America/Chicago'
AS SELECT 1;
CREATE TASK ops.load_sales AFTER ops.nightly_root AS CALL ops.load_sales_mart();
CREATE TASK ops.load_inventory AFTER ops.nightly_root AS CALL ops.load_inventory_mart();
CREATE TASK ops.build_summary
AFTER ops.load_sales, ops.load_inventory
AS CALL ops.build_exec_summary();Note that parallel siblings on one user-managed warehouse compete for it. Size that warehouse for the concurrent load, or give the heavier sibling a warehouse of its own.
Finalizer Tasks for Cleanup and Alerts A finalizer is an optional last task, attached to the root with FINALIZE, that runs after every other task completes or fails. It is the right home for dropping temporary tables and for posting a run summary to the team.
CREATE TASK ops.nightly_finalizer
FINALIZE = ops.nightly_root
AS CALL ops.send_run_summary();Each root can have one finalizer, and a finalizer cannot have children. It also will not start when the root itself is skipped, for example because the previous run was still going.
Passing Config and Return Values Graphs can carry context. For instance, the root’s CONFIG parameter stores JSON that any task reads with SYSTEM$GET_TASK_GRAPH_CONFIG. For a single run, such as a backfill, EXECUTE TASK with USING CONFIG overrides it. A parent can also hand a value to a child: the parent calls SYSTEM$SET_RETURN_VALUE, and the child reads it with SYSTEM$GET_PREDECESSOR_RETURN_VALUE.
Used sparingly, this keeps environment paths and date windows out of hard-coded SQL. Used heavily, it turns the graph into a program nobody can read. Keep logic in procedures and pass only parameters between tasks.
Changing a Live Graph Without Surprises To change any task in a graph, suspend the root first. A run already in flight finishes on the old version, and the new version takes effect when the root is resumed or run by hand.
ALTER TASK ops.nightly_root SUSPEND;
ALTER TASK ops.build_summary MODIFY AS CALL ops.build_exec_summary_v2();
-- Resume every task in the graph in one call
SELECT SYSTEM$TASK_DEPENDENTS_ENABLE('ops.nightly_root');A suspended child does not stop the graph. Snowflake treats it as if it succeeded and moves on, which is handy for skipping a step and dangerous if someone forgets to resume it. Editing a task in Snowsight also suspends and resumes it automatically, so treat UI edits like a deployment.
Overlapping Runs and the OVERLAP_POLICY Setting By default a graph never overlaps itself. Snowflake schedules the next root run only after every task in the current run has finished. So a graph that takes 70 minutes on an hourly schedule skips runs without raising any error.
The OVERLAP_POLICY parameter on the root changes that behaviour. NO_OVERLAP, the default, keeps runs strictly in sequence. ALLOW_CHILD_OVERLAP lets a new run start while children of the last one are still busy, though the root itself never overlaps. ALLOW_ALL_OVERLAP lets whole runs, root included, stack on top of each other.
Overlap is only safe when concurrent runs cannot write conflicting or duplicate rows. Before switching it on, try the plain fixes first. Widen the schedule, move heavy steps to bigger compute, or tune the slowest statements with the help of our guide to Snowflake query optimization .
Error Handling, Retries, and Recovery Failures are certain, so the useful question is what the graph does next. Snowflake gives you five levers, and a production graph usually needs all of them.
Timeouts and Automatic Suspension USER_TASK_TIMEOUT_MS limits a single run. The default is one hour and the maximum is seven days. Set on the root, it covers the whole graph, while a value on a child applies to that child alone.
SUSPEND_TASK_AFTER_NUM_FAILURES stops a task or graph after a streak of failed runs, and it defaults to 10. Skipped, cancelled and system-error runs do not count toward it. The setting protects credits from a task that fails every five minutes all weekend.
Automatic Retries TASK_AUTO_RETRY_ATTEMPTS is off by default. Set it on the root task, and a failed graph run is retried straight away instead of waiting for the next schedule. You choose the number of attempts, up to a maximum of 30.
Because the retries are immediate, two or three attempts absorb brief problems such as a lock conflict or a passing service error. They will not wait out a source table that lands 40 minutes late. A real bug simply fails a few more times before the alert goes out.
Manual Retries With RETRY LAST After you fix the cause, EXECUTE TASK with RETRY LAST restarts the graph from the failed tasks instead of from the top. Completed steps are not repeated, which matters when the first half of the graph took an hour.
EXECUTE TASK ops.nightly_root RETRY LAST;
-- Retry an older failed run by its group id
EXECUTE TASK ops.nightly_root RETRY GRAPH RUN GROUP '<graph_run_group_id>';The EXECUTE TASK reference sets three conditions. The last graph run must have ended FAILED or CANCELED, and nobody may have modified the graph since. That run’s first attempt must also fall within the past 14 days. The second condition is the one that bites. Fix data problems in the data, not in the task definition, or the retry will be refused.
Alerts and Notifications There are two routes. ERROR_INTEGRATION and SUCCESS_INTEGRATION push each failure, or each successful graph run, to Amazon SNS, Azure Event Grid or Google Pub/Sub. For email or webhooks, Snowflake points you to task alerts, which watch the error rate across tasks.
Task alerts only work when task events are logged. Set LOG_EVENT_LEVEL to INFO on the tasks you watch, because the default of OFF records nothing and the alert never fires. A finalizer that posts a run summary covers the gap for teams without cloud messaging set up.
Writing Retry-Safe SQL Retries are only safe when running a step twice gives the same result as running it once. Engineers call that idempotence .
In Snowflake that usually means MERGE on a business key or DELETE then INSERT for a bounded date window. INSERT OVERWRITE also works when a step rebuilds a whole table.
Plain INSERT with SELECT is the usual offender. One retry and the finance table holds two copies of Tuesday, which is worse than a missing Tuesday because nobody notices. If a bad run does slip through, Snowflake Time Travel can restore the table to its state before the run.
Checklist
Data Engineering Checklist for Enterprise Teams
Review retry safety, monitoring, ownership and testing for every production pipeline before it runs unattended.
Get the Checklist → Monitoring Snowflake Tasks and Their Cost A task you cannot see is a task you cannot trust. Snowflake exposes run history, graph status and credit use through SQL. Snowsight draws the same graph visually and adds a retry button for failed runs.
TASK_HISTORY and SHOW TASKS SHOW TASKS answers what exists and whether it is started or suspended. The TASK_HISTORY table function answers what ran. It covers the past seven days plus the next scheduled run. It returns 100 rows unless you raise RESULT_LIMIT, which goes up to 10,000.
SELECT name, state, scheduled_time, completed_time, error_code, error_message
FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY(
SCHEDULED_TIME_RANGE_START => DATEADD('hour', -24, CURRENT_TIMESTAMP()),
ERROR_ONLY => TRUE))
ORDER BY scheduled_time DESC;For longer trends, the TASK_HISTORY view in the ACCOUNT_USAGE schema keeps a year of runs, with up to 45 minutes of delay. Our walkthrough of Snowflake query history shows how to connect task runs to the queries they issued.
Graph-Level Views CURRENT_TASK_GRAPHS shows graph runs in progress or scheduled within the next eight days. COMPLETE_TASK_GRAPHS shows runs that succeeded, failed or were cancelled in the past 60 minutes, and its Account Usage view keeps the longer record. Comparing SCHEDULED_TIME with COMPLETED_TIME there gives the true length of a graph run, queueing included.
Tracking Serverless Credits Serverless tasks bill under their own service type. The SERVERLESS_TASK_HISTORY view lists credits per task, and METERING_HISTORY filtered on SERVERLESS_TASK gives the account total.
SELECT task_name,
SUM(credits_used) AS credits_7d
FROM SNOWFLAKE.ACCOUNT_USAGE.SERVERLESS_TASK_HISTORY
WHERE start_time >= DATEADD('day', -7, CURRENT_TIMESTAMP())
GROUP BY task_name
ORDER BY credits_7d DESC;Warehouse tasks appear in warehouse metering instead, so give pipelines their own warehouse if you want clean attribution. A Datadog and Snowflake integration or a similar tool can bring both into one on-call view.
Five Numbers Worth a Dashboard Success rate per graph over the last seven days. Lag between scheduled time and query start, which exposes queueing. Graph duration compared with its schedule interval. Retry attempts and tasks that suspended themselves. Credits per successful run. Watched together, these five numbers turn task monitoring from log reading into trend spotting. They also pair well with wider data observability checks on the tables the tasks produce. For alerting options, see our review of data pipeline monitoring tools .
Worked Example: A Nightly Reporting Graph Built for Failure Back to 2:07 a.m. This is the same finance pipeline, rebuilt so that a late table becomes an early, reported error rather than a silent one.
The graph runs at 1:07 a.m. Central, loads two marts in parallel, builds a summary, and always reports what happened.
-- Root task: schedule, retries, failure limit, shared config
CREATE OR REPLACE TASK finance.ops.nightly_root
SCHEDULE = 'USING CRON 7 1 * * * America/Chicago'
TASK_AUTO_RETRY_ATTEMPTS = 2
SUSPEND_TASK_AFTER_NUM_FAILURES = 3
USER_TASK_TIMEOUT_MS = 5400000 -- 90 minutes for the whole graph
CONFIG = '{"lookback_days": 3}'
AS
CALL finance.ops.check_sources_ready(); -- raises an error if upstream is late
-- Two marts in parallel (fan-out); the heavy one gets its own warehouse
CREATE OR REPLACE TASK finance.ops.load_revenue
WAREHOUSE = finance_transform_wh
AFTER finance.ops.nightly_root
AS
CALL finance.ops.merge_revenue_mart();
CREATE OR REPLACE TASK finance.ops.load_costs
AFTER finance.ops.nightly_root -- serverless
AS
CALL finance.ops.merge_cost_mart();
-- Summary waits for both (fan-in)
CREATE OR REPLACE TASK finance.ops.build_pnl_summary
AFTER finance.ops.load_revenue, finance.ops.load_costs
AS
CALL finance.ops.build_pnl_summary();
-- Finalizer: always runs, reports status, drops temp tables
CREATE OR REPLACE TASK finance.ops.nightly_finalizer
FINALIZE = finance.ops.nightly_root
AS
CALL finance.ops.post_run_summary_and_cleanup();
-- Resume the whole graph in one call
SELECT SYSTEM$TASK_DEPENDENTS_ENABLE('finance.ops.nightly_root');Each part answers a failure from that night. A readiness check in the root turns a late source table into an early error, before any mart is touched. Two automatic retries cover brief glitches. If the feed is genuinely late, the readiness check keeps failing, the finalizer reports it, and the engineer runs RETRY LAST once the table lands.
Inside their procedures, both marts use MERGE, so a retry corrects rows instead of doubling them. The finalizer posts a summary whether the run succeeded or not. So the on-call engineer hears about trouble from the graph rather than from the CFO.
To test it, break it on purpose in a zero-copy clone of the schema. Rename a source table and run EXECUTE TASK on the root. Confirm in TASK_HISTORY that the graph failed at the readiness step and the finalizer still reported, then restore the table and run RETRY LAST.
Talk to Kanerika
Want a Second Pair of Eyes on Your Task Graphs?
Talk to Kanerika’s Snowflake engineers about schedules, retries, alerts and cost for the pipelines you run every night.
Book a Meeting → Why a Snowflake Task Is Not Running: Seven Causes and Fixes When a task seems to do nothing, the cause is almost always on a short list. Check these in order, because the early ones take seconds to rule out.
It is still suspended. New and replaced tasks start suspended. Run SHOW TASKS, then resume the task or call SYSTEM$TASK_DEPENDENTS_ENABLE for a whole graph.The owner role lacks EXECUTE TASK. The task exists but can never start. Grant EXECUTE TASK on the account, plus EXECUTE MANAGED TASK for serverless tasks.The root is suspended. Children only run when a root run reaches them, so resuming children alone does nothing. Resume children first and the root last.The WHEN condition is false. A triggered task skips without an error when its stream is empty, and TASK_HISTORY shows those runs as skipped, not failed.The previous run is still going. Under NO_OVERLAP, Snowflake skips a slot while the last run continues. Compare graph duration with the interval.It suspended itself. Repeated failures can trip SUSPEND_TASK_AFTER_NUM_FAILURES. Fix the error in TASK_HISTORY before resuming, or it will stop again.The warehouse is queued. A task on a busy warehouse waits its turn. Compare scheduled time with query start time, then resize the warehouse or move the task.If all seven check out, read the error message of the last failed run and run the task body by hand as the owner role. Snowflake recommends exactly that test before any statement goes into a task.
When Native Tasks Are Enough and When to Add an Orchestrator Snowflake tasks cover most pipelines whose work lives inside Snowflake. They schedule, chain, retry and report without another server to patch. The useful question is where their edges are.
Situation Do Snowflake tasks handle it? What to add, if anything Every step is SQL or a procedure in one account Yes, this is the native fit Nothing The graph fits one schema and one owner role Yes Nothing Work must wait for new data in a stream Yes, with triggered tasks Nothing Steps call outside systems such as a SaaS API Partly, through procedures and external access Consider an outside scheduler for those steps One timetable must coordinate Snowflake and other platforms Tasks still run the Snowflake part An orchestrator above that calls EXECUTE TASK
When an outside tool does join, it works best as the layer above. For example, Apache Airflow DAGs or a similar scheduler can call EXECUTE TASK on a Snowflake root. The task graph then keeps ordering, retries and the finalizer.
Our roundups of data orchestration tools and workflow orchestration tools cover the outside options.
Kanerika’s work for a financial services client shows the outside layer at work, on a different platform. The client’s KPI reporting ran three days behind. So the team built Airflow 2.0 pipelines that moved data from S3 into Databricks on a fixed schedule. Data lag from source to consumption fell 90%. That project did not run on Snowflake. The same split carries over, with the outside scheduler owning cross-system timing and the task graph owning the warehouse steps.
Case Study
90% Less Data Lag in Financial Services Reporting
Scheduled pipelines with automated data quality rules took fraud and settlement KPIs from a three-day lag to near real time, with 96% lower reporting latency.
Read the Case Study → How Kanerika Builds and Runs Snowflake Task Pipelines Kanerika is a Snowflake Select Tier Partner , and its engineers build task-driven pipelines as part of Snowflake implementation and migration work. The approach follows the same five stages on every project, because a skipped stage is how 2 a.m. pages happen.
Assess. Inventory every scheduled job, its owner, its runtime and what breaks when it is late. Then map legacy SQL Agent, cron and SSIS schedules to tasks, procedures or dynamic tables.Design. Draw the graph before writing SQL, choose compute per task, and set timeouts, retries and overlap policy from the business deadline.Build. Write retry-safe SQL, keep logic in version-controlled procedures, and deploy graphs from scripts rather than UI edits.Prove. Break each graph on purpose in a test environment and confirm that the finalizer, alerts and RETRY LAST path all work.Run. Hand over dashboards for success rate, lag and credits per run, plus a runbook for the seven not-running causes above.Two habits matter most in practice. Every production graph gets a named owner role and its own notification route. Credits per successful run get a monthly review, because a task whose cost doubles unnoticed is as much a failure as one that stops.
Teams planning similar work can start with Kanerika’s data engineering services or its data integration services .
Kanerika Service
Data Engineering Services
Kanerika builds, tests and runs production data pipelines, from task graphs in Snowflake to cross-platform orchestration.
Explore Data Engineering Wrapping Up Snowflake tasks give the warehouse its own scheduler. Create the task, choose an interval, CRON or a trigger, and pick serverless or warehouse compute by measured cost. Chain related steps into a graph with AFTER, close it with a finalizer, and decide in advance how it times out, retries and alerts.
Then watch TASK_HISTORY and credits per run like any other production system. Do that, and the 2 a.m. failure becomes a retried run and a short summary in the morning inbox.
Frequently Asked Questions
What are Snowflake tasks used for? Snowflake tasks run SQL statements, stored procedure calls or Snowflake Scripting blocks automatically. Teams use them for incremental loads, nightly aggregates, reconciliation queries, data quality checks and housekeeping such as purging staging rows. A task can run on a fixed schedule, on a CRON expression, or when a stream reports new data, with no outside scheduler required.
How do you create a task in Snowflake? Use CREATE TASK with a name, a WAREHOUSE or no warehouse for serverless compute, a SCHEDULE or WHEN condition, and the SQL after AS. The owner role needs CREATE TASK on the schema and EXECUTE TASK on the account. New tasks start suspended, so run EXECUTE TASK to test once, then ALTER TASK RESUME.
How do you schedule a Snowflake task with CRON? Set SCHEDULE to USING CRON followed by five fields and a time zone, for example USING CRON 0 6 * * 1-5 America/New_York for 6 a.m. Eastern on weekdays. The fields are minute, hour, day of month, month and day of week. Choose the business time zone and test schedules near daylight saving changes.
What is the difference between serverless and warehouse tasks in Snowflake? Serverless tasks omit the WAREHOUSE parameter, and Snowflake sizes compute from recent runs, up to the equivalent of XXLARGE, billing only what is used. Warehouse tasks run on a warehouse you size, billed per second with a 60-second minimum per resume. Serverless suits short steady jobs, while busy shared warehouses suit user-managed tasks.
How do you build a task graph in Snowflake? Create a root task with a schedule, then create child tasks that name their parents with AFTER. Children sharing a parent run in parallel, and a child with several parents waits for all of them. Add an optional finalizer with FINALIZE for cleanup, then resume everything with SYSTEM$TASK_DEPENDENTS_ENABLE on the root task.
What happens when a Snowflake task fails? The run is recorded as failed in TASK_HISTORY, and by default the whole task graph counts as failed. TASK_AUTO_RETRY_ATTEMPTS can retry the graph immediately, SUSPEND_TASK_AFTER_NUM_FAILURES stops it after repeated failures, and EXECUTE TASK with RETRY LAST restarts from the failed step once the cause is fixed. A finalizer can report the outcome.
How do you check task status and history in Snowflake? Run SHOW TASKS to see whether each task is started or suspended. Query the INFORMATION_SCHEMA.TASK_HISTORY table function for runs from the past seven days, with ERROR_ONLY to list failures. For a year of history, use the ACCOUNT_USAGE TASK_HISTORY view. Snowsight also shows task graphs visually and lets you retry failed runs.
Why is my Snowflake task not running? The usual causes are a task still suspended, an owner role missing EXECUTE TASK, a suspended root task, a WHEN condition that evaluates false, or a previous run still in progress. Tasks can also suspend themselves after repeated failures or wait in a busy warehouse queue. TASK_HISTORY and SHOW TASKS reveal which case applies.
How much do Snowflake tasks cost? Tasks have no separate license fee. Warehouse tasks consume warehouse credits while they run, with a 60-second minimum each time the warehouse resumes. Serverless tasks bill the compute actually used under their own service type. Track credits per task in the SERVERLESS_TASK_HISTORY view and compare credits per successful run before choosing a compute model.
Can a Snowflake task run multiple SQL statements? A task holds one piece of code, but that code can be a Snowflake Scripting block with several statements between BEGIN and END, or a CALL to a stored procedure. Split steps into separate tasks in a graph when they should run in parallel, retry independently, or be monitored as separate units of work.
What is a finalizer task in Snowflake? A finalizer is an optional task attached to a root task with FINALIZE. It runs after every other task in the graph completes or fails, which makes it the natural place for cleanup and run summaries. Each root has at most one finalizer, it cannot have child tasks, and it does not start when the root is skipped.