Heuristic:TobikoData Sqlmesh Execution Time Caching
| Knowledge Sources | |
|---|---|
| Domains | Plan_Building, Time_Handling |
| Last Updated | 2026-02-07 21:00 GMT |
Overview
PlanBuilder caches execution_time as a property to provide stable resolution of relative date expressions during plan construction, while allowing re-resolution at actual execution time.
Description
During plan building, SQLMesh needs to resolve relative date expressions (e.g., "1 day ago", "now()") into concrete timestamps. If execution_time were called multiple times during plan construction, each call to now() could return a different value, causing inconsistencies in the plan. The solution is to cache execution_time as a @cached_property, ensuring all relative dates resolve against the same reference point. However, the actual Plan object deliberately does NOT use this cached value - it accepts _execution_time=None so that dates can be re-resolved at actual runtime, accounting for any delay between plan building and execution.
Usage
This heuristic applies when:
- Building plans that involve relative date expressions in model logic
- Understanding why plan preview shows specific date ranges
- Debugging date-related inconsistencies between plan creation and execution
- Implementing features that need stable time references during plan construction
- Dealing with delayed plan execution (e.g., serializing a plan for later execution)
The Insight (Rule of Thumb)
- Action: Use cached execution_time during plan building for consistency, but pass uncached _execution_time to Plan for runtime re-resolution
- Value: @cached_property on PlanBuilder.execution_time, but Plan receives _execution_time parameter directly
- Trade-off: Stable plan construction vs. accurate execution time for delayed runs
Reasoning
Consider a scenario where a plan is built at 11:59 PM and some operations during plan building resolve "today" to one date, while later operations (if now() were called again) might resolve to the next day after midnight. This would create an internally inconsistent plan.
The cached_property decorator ensures that: 1. All relative date expressions during plan building resolve against the same moment 2. The plan's internal state is consistent and deterministic 3. Multiple calls to self.execution_time within PlanBuilder return the same value
However, there's a second consideration: if a plan is built but not immediately executed (e.g., saved for later, sent to a worker process, or waiting for user approval), we want the execution time to reflect when it actually runs, not when it was planned. This is why the Plan object receives the uncached _execution_time parameter - passing None allows it to re-call now() at execution time.
This two-tier approach provides both stability during construction and accuracy during execution.
Code Evidence
# sqlmesh/core/plan/builder.py:221-225
@cached_property
def execution_time(self) -> TimeLike:
# this is cached to return a stable value from now() in the places where the execution time matters for resolving relative date strings
# during the plan building process
return self._execution_time or now()
# sqlmesh/core/plan/builder.py:320-323
# this deliberately uses the passed in self._execution_time and not self.execution_time cached property
# the reason is because that there can be a delay between the Plan being built and the Plan being actually run,
# so this ensures that an _execution_time of None can be propagated to the Plan and thus be re-resolved to
Example of the issue this solves:
# Without caching - INCONSISTENT
def build_plan():
start = now() # 23:59:59
# ... do some work ...
end = now() # 00:00:01 next day - PROBLEM!
# Plan has inconsistent date range
# With caching - CONSISTENT
@cached_property
def execution_time(self):
return now()
def build_plan(self):
start = self.execution_time # 23:59:59
# ... do some work ...
end = self.execution_time # 23:59:59 - same value!
# Plan has consistent date range
Production best practice:
-- BAD: Relative dates in production
SELECT * FROM events WHERE date > current_date() - interval '7 days'
-- GOOD: Explicit dates in production
SELECT * FROM events WHERE date > '2026-01-31'