Understanding dynamic table target lag¶
Dynamic table refresh is triggered by the data’s target lag, which determines how outdated it can be. You can set a fixed target lag or set the dynamic table to DOWNSTREAM, making its refresh timing depend on the dynamic tables that depend on it.
The target lag for a dynamic table is measured relative to the dynamic tables at the root of the graph, not the dynamic tables directly upstream. To see the graph of tables connected to your dynamic table, see View the graph of tables connected to your dynamic tables.
Snowflake schedules refreshes to keep the actual lag of your dynamic tables below their target lag. The duration of each refresh depends on the query, data pattern, and warehouse size. When choosing a target lag, consider the time needed to refresh each dynamic table in a chain to the root. If you don’t, some refreshes might be skipped, leading to a higher actual lag.
Note
For dynamic tables with the SCHEDULER attribute explicitly set to DISABLE, target lag doesn’t apply and automatic refreshes
are disabled. These dynamic tables can only be refreshed manually. For more information, see
Manual refresh of dynamic tables with the scheduler disabled.
Types of target lag¶
You specify target lag in one of the following ways. Target lag is inversely proportional to the dynamic table’s refresh frequency: frequent refreshes imply a lower lag.
-
Measure of freshness: Defines the maximum amount of time that the dynamic table’s content should lag behind updates to the base tables. The following example sets
my_dynamic_tableto refresh and maintain freshness within every hour: -
Downstream: Specifies that the dynamic table should refresh on demand when downstream tables (tables that depend on this table) refresh. This refresh can be triggered by initialization at creation, manual refresh, or scheduled refresh of a downstream table.
When
refresh_modeis set todownstream, the refresh schedule of a dynamic table is driven by the most demanding (shortest) lag of its downstream dependents. For example, if one downstream dependent table requires data that is no older than 10 minutes and another downstream dependent table requires data that is no older than 1 hour, the refresh schedule of this dynamic table will be every 10 minutes because that is the shortest lag of its downstream dependents.In the following example,
my_dynamic_tableis set to refresh based on the target lag of its downstream dynamic tables. Ifmy_dynamic_tabledoesn’t have any dynamic tables that depend on it, then it won’t refresh.For more examples of downstream target lag, see Example: Target lag for dynamic table chains.
How Snowflake schedules refreshes¶
Snowflake schedules refreshes slightly earlier than the target lag to allow time for the refresh to complete. For example, if you set the target lag to 5 minutes, the table might refresh more frequently than every five minutes. Actual refresh intervals are often shorter than the specified lag.
Note
Target lag is a target, not a guarantee. Snowflake attempts to keep data within the target lag, but actual lag may exceed the target because of factors such as warehouse size, data volume, and query complexity.
For guidance on adjusting target lag for your workload, see Alter the warehouse or target lag for dynamic tables. For information about optimizing your target lag, see Identify the right target lag.
How upstream and downstream relationships affect target lag¶
The following diagram illustrates suspend, resume, and manual refresh operations in the context of upstream and downstream relationships to other dynamic tables.

The diagram depicts a simple declarative data pipeline built with dynamic tables:
DT2is described as downstream ofDT1because it depends on that dynamic table, and as upstream ofDT3, which depends on it.DT3is downstream of bothDT2andDT1because it depends onDT2directly and onDT1indirectly.DT1is directly or indirectly upstream of the other dynamic tables.
Example: Target lag for dynamic table chains¶
Consider the following example where a dynamic table (DT2) reads from another dynamic table (DT1) to materialize its contents. In
this scenario, a report consumes DT2’s data via a query.

The following results are possible, depending on how each dynamic table specifies its lag:
DT1 | DT2 | Refresh results |
|---|---|---|
TARGET_LAG = DOWNSTREAM | TARGET_LAG = 10minutes | DT2 is updated at least every 10 minutes. DT1 infers its lag from DT2 and is updated every time DT2 requires updates. |
TARGET_LAG = 10minutes | TARGET_LAG = DOWNSTREAM | This scenario should be avoided. The report query will not receive any data. DT1 is frequently refreshed and DT2 is not refreshed because there’s no dynamic table that’s based on DT2. |
TARGET_LAG = 5minutes | TARGET_LAG = 10minutes | DT2 is updated approximately every 10 minutes with data from DT1 that’s at most 5 minutes old. |
TARGET_LAG = DOWNSTREAM | TARGET_LAG = DOWNSTREAM | Neither DT1 nor DT2 is refreshed periodically because both of them have a downstream lag, and neither has a downstream consumer with a defined lag. |
Manually refresh dynamic tables¶
Manual refresh of dynamic tables with the scheduler enabled¶
You can manually refresh a dynamic table to include the latest data without waiting for the next scheduled refresh. This is useful for one-time updates or when a table has a large target lag and the next refresh occurs much later.
Tip
Avoid frequent manual refreshes on dynamic tables with downstream dynamic tables that are expected to refresh according to target lag. These kinds of manual refreshes can cause scheduled refreshes to skip and prevent downstream tables from updating.
To manually refresh, use the ALTER DYNAMIC TABLE … REFRESH command or Snowsight as shown in the following steps:
- Sign in to Snowsight.
- Select Monitoring » Dynamic Tables.
- In the list, find your dynamic table, and then select
» Refresh Manually.
For situations that require precise refresh timing, such as aligning refreshes with external system schedules or batch processing windows, you can use a task with a CRON expression to trigger the refresh.
For example:
For most cases, Snowflake recommends using target lag, which optimizes refresh frequency and can reduce costs compared to fixed CRON schedules that might run unnecessarily.
Manual refresh of dynamic tables with the scheduler disabled¶
Dynamic tables with the SCHEDULER attribute set to DISABLE can only be refreshed manually.
This type of manual refresh refreshes only that dynamic table. It doesn’t cascade to any upstream dynamic tables, regardless of their scheduler state.
In the DYNAMIC_TABLE_REFRESH_HISTORY output, the REFRESH_TRIGGER value for these refreshes is
MANUAL. No SCHEDULED entries are generated for dynamic tables with SCHEDULER set to DISABLE.
This behavior allows external orchestrators, such as dbt, to issue one manual refresh per dynamic table without triggering upstream refreshes.
To disable the scheduler and then manually refresh a dynamic table, use the ALTER DYNAMIC TABLE command as shown in the following steps:
-
Disable the scheduler:
-
Manually refresh the dynamic table:
- Sign in to Snowsight.
- Select Monitoring » Dynamic Tables.
- In the list, find your dynamic table, and then select
» Refresh Manually.