Understanding costs for dynamic tables¶
This page explains the three cost components of dynamic tables (virtual warehouse compute, Cloud Services compute, and storage), how to estimate and monitor those costs with SQL, and the common patterns that cause unexpected charges.
To find how much a specific dynamic table costs, start with this query. It summarizes refresh activity by table and refresh type, showing how many refreshes ran and how many rows were processed.
Three cost components¶
Every dynamic table incurs costs in three categories. The relative weight of each depends on how often refreshes run, warehouse size, and data volume.
| Component | What drives cost | How it is billed |
|---|---|---|
| Virtual warehouse compute | Refresh queries that run on the assigned warehouse. Larger warehouse or more frequent refreshes increase cost. | Per-second credits based on warehouse size. For details, see Understanding compute cost. |
| Cloud Services compute | Metadata checks that detect upstream changes and decide whether a warehouse refresh is needed. Runs on every refresh cycle, even when no data has changed. | Billed daily, but only when Cloud Services credits exceed 10% of that day’s total warehouse credits. For details, see Cloud Services billing. |
| Storage | Materialized results, Time Travel data, and fail-safe copies. Incremental refresh adds a small per-row metadata column. | Standard Snowflake storage rates. For details, see Understanding storage cost. Dynamic Apache Iceberg tables use external storage and don’t incur Snowflake storage costs. |
Virtual warehouse compute costs¶
Virtual warehouse compute is the primary cost for most dynamic table workloads. Each dynamic table uses its assigned warehouse to run refreshes. The cost per refresh depends on the warehouse size, the complexity of the definition, and the volume of data processed. For complete details on how warehouse billing works (including per-second billing and the 60-second minimum), see Understanding compute cost.
Key behaviors:
- If Snowflake detects no upstream changes, the warehouse stays suspended and no compute credits are consumed.
- If base tables have changes, the warehouse resumes and runs a refresh even if the refresh produces no output rows after filtering.
- You can assign separate warehouses for regular refreshes (WAREHOUSE) and reinitialization (INITIALIZATION_WAREHOUSE). For more information, see Choose and size warehouses for dynamic tables.
To check warehouse credit consumption for a specific dynamic table, query DYNAMIC_TABLE_REFRESH_HISTORY and join with QUERY_HISTORY:
Tip
To isolate dynamic table costs during testing, use a dedicated warehouse. This lets you attribute all credits on that warehouse to dynamic table refreshes. After you establish a cost baseline, you can move dynamic tables to a shared warehouse. For more information, see Choose and size warehouses for dynamic tables.
Cloud Services costs and the 10% billing threshold¶
Cloud Services credits cover metadata operations (change detection, query compilation, and scheduling) that run on every refresh cycle regardless of whether data has changed. Each active dynamic table incurs this overhead independently.
How the 10% threshold works¶
Cloud Services credits are billed only when the daily total exceeds 10% of that day’s warehouse compute credits. This is an account-level daily calculation in UTC, not per-warehouse or per-dynamic-table. For the full billing formula and examples, see Understanding billing for cloud services usage.
Short target lag amplifies Cloud Services costs
Cloud Services costs scale with the number of active dynamic tables, the target lag, and pipeline depth. Each dynamic table independently performs change-detection checks on every refresh cycle. With many dynamic tables at short target lag, Cloud Services charges can exceed the 10% threshold and result in direct charges.
A pipeline of 200 dynamic tables with a 1-minute target lag generates approximately 288,000 change-detection checks per day (200 tables x 1,440 cycles). Even when no data has changed, these checks accumulate Cloud Services credits.
To reduce Cloud Services costs:
- Increase target lag where near-real-time freshness isn’t required.
- Use
TARGET_LAG = DOWNSTREAMfor intermediate dynamic tables in a pipeline so they refresh only when needed. - Suspend dynamic tables outside business hours in non-production environments.
- Monitor Cloud Services consumption with METERING_HISTORY view.
For general patterns that drive Cloud Services costs, see Optimizing cloud services for cost.
Check whether your account is exceeding the 10% threshold:
Storage costs¶
Dynamic tables store materialized results and incur standard Snowflake storage costs. For general information about how storage is billed, see Understanding storage cost. Several factors affect the total storage footprint for dynamic tables specifically:
- Time Travel and fail-safe. Frequent refreshes increase the buildup of Time Travel data. Fail-safe provides additional data protection. To reduce storage costs from fail-safe, create a transient dynamic table.
- Incremental refresh metadata. Dynamic tables using incremental refresh maintain an internal metadata column per row for change tracking. This adds a constant amount of storage per row, independent of the number of columns. On narrow tables (few columns), this overhead can be significant relative to the actual data.
- Replication. Dynamic tables that participate in cross-region replication incur replication costs. For more information, see Share dynamic tables with other accounts.
- Suspended dynamic tables. A suspended dynamic table doesn’t consume compute credits, but still incurs storage fees for its materialized data, Time Travel history, and fail-safe copies. Time Travel data from pre-suspension refreshes ages out normally based on DATA_RETENTION_TIME_IN_DAYS. If a dynamic table stays suspended longer than the base table’s DATA_RETENTION_TIME_IN_DAYS setting, the change-tracking window expires and the dynamic table must reinitialize when resumed. For details on retention, see Understanding data retention.
- Storage lifecycle policies. Attach a storage lifecycle policy to delete or archive expired rows asynchronously, reducing the dynamic table’s storage footprint. For more information, see Use storage lifecycle policies with dynamic tables.
Note
Dynamic Apache Iceberg tables don’t incur Snowflake storage costs. For more information, see Iceberg table billing.
Common cost patterns¶
Check whether any of these patterns apply to your pipelines.
AUTO mode selects full refresh without a warning¶
AUTO resolves the refresh mode once at creation time. If it resolves to FULL when you expected INCREMENTAL, refresh costs may increase because every refresh reprocesses the entire table instead of only changed rows. For details on how AUTO works and how to verify the resolved mode, see Dynamic table refresh modes.
Short target lag amplifies Cloud Services on idle tables¶
Setting a short target lag (for example, 1 minute) on dynamic tables with infrequent upstream changes causes repeated change-detection checks that produce NO_DATA results. Each check still incurs Cloud Services credits.
Find dynamic tables with a high proportion of NO_DATA refreshes:
If a dynamic table has a high NO_DATA percentage, consider increasing its target lag or using
TARGET_LAG = DOWNSTREAM so it refreshes only when a downstream consumer triggers it.
TRUNCATE followed by COPY INTO generates outsized change events¶
When an upstream base table is loaded using a TRUNCATE followed by COPY INTO pattern, each cycle generates DELETE events for every existing row plus INSERT events for every loaded row. If dynamic table refreshes fail or fall behind, these change events accumulate. A single recovery refresh then processes the entire backlog.
To avoid this pattern:
- Use INSERT-only or MERGE patterns for upstream loading instead of TRUNCATE followed by COPY INTO.
- Add a PRIMARY KEY with RELY to base tables loaded with full-replacement patterns (TRUNCATE followed by COPY INTO, or INSERT OVERWRITE). Snowflake compares key values before and after the load and processes only rows that actually changed. For details, see best practice 4.
- Monitor for failed refreshes so backlogs don’t accumulate. For more information, see Troubleshoot dynamic table refresh issues.
Monitor dynamic table costs¶
Use these queries to track costs across your dynamic table pipelines.
Credit consumption by warehouse over the past 7 days¶
To find which warehouses are consuming the most credits, query WAREHOUSE_METERING_HISTORY. If you use dedicated warehouses for dynamic tables, this query shows their total cost.
Refresh activity per dynamic table¶
To see how each dynamic table contributes to overall refresh volume, query DYNAMIC_TABLE_REFRESH_HISTORY. Look for dynamic tables with high refresh counts or long average durations as candidates for optimization.
Identify dynamic tables running full refresh unexpectedly¶
A REINITIALIZE action fully reprocesses the dynamic table and costs significantly more than an incremental refresh.
If a dynamic table shows frequent REINITIALIZE actions, check for upstream DDL changes or policy changes that trigger reinitialization. For more information, see Evolve dynamic table pipelines.
What’s next¶
- To choose the right warehouse size and configuration, see Choose and size warehouses for dynamic tables.
- To reduce refresh cost through query optimization, see Optimize queries for incremental refresh.
- To set up monitoring dashboards and alerts, see Monitor dynamic tables.