Point-in-time correct training joins
Reconstruct eligible feature observations using both event time and actual availability, without leaking later corrections into past decisions.
On this page
The question for today
What you’ll understand
- Distinguish event-time history from as-known-at-decision history.
- Apply eligibility before deterministic latest-row selection.
- Explain the scope of created-timestamp filtering in a pinned Feast API.
A historical row can describe an old event while becoming known only much later. Joining it to a past prediction merely because its event time precedes the label can leak information the serving system did not possess. Point-in-time feature retrieval must first declare its question: corrected historical truth or the values available to a decision at that time. Those are useful but different datasets.
Track two temporal dimensions explicitly
Event time identifies when an observation happened or the interval it describes. Availability or knowledge time identifies when the chosen serving path could use that particular version. An ingestion timestamp can approximate availability only when the pipeline contract makes that true; a record entering a warehouse at noon may not reach the online store until several minutes later. Corrections add another distinction: the effective event can remain yesterday while a revised value becomes available today. Retain the earlier version if historical serving reconstruction needs it.
For each training entity row, choose a decision timestamp with the same interpretation as the production decision. Filter candidate features by entity identity, valid event-time range, and the required availability cutoff before selecting the latest eligible version. Do not filter using the time a delayed label was finalized if the real prediction occurred earlier. A snapshot query against a warehouse today can provide a consistent database view while still including information unavailable at the historic prediction; transactional consistency alone is not an anti-leakage policy.
Apply tie and correction rules after eligibility
Within eligible candidates, select the newest event time and a documented revision order for equal event times. A later correction with the same event timestamp must not win an as-known join when its availability lies after the decision. Duplicate physical rows representing the same revision need deterministic deduplication. Missing created or availability timestamps require an explicit policy; treating unknown time as negative infinity silently upgrades uncertainty into historical knowledge. Preserve enough provenance that a reviewer can explain why one row was eligible and another was excluded.
Feast v0.66.0 exposes get_historical_features with filter_by_created_timestamp, defaulting to false. The referenced documentation explains that default joins constrain event timestamps, while created timestamps ordinarily help deduplicate equal-event-time rows. Enabling the supported filter adds the created-time cutoff and excludes null created timestamps; unsupported offline stores reject it. This implements as-known behavior only if that field actually represents the required availability and is populated correctly. It cannot recover overwritten historical versions, infer delayed online publication, or compensate for a transformation that used future inputs before producing its row.
Test leakage with adversarial temporal fixtures
Build fixtures containing a late event, a same-event-time correction, an event after the decision, an observation beyond the horizon, and two entities with similar keys. Verify selected values and rejected candidates explicitly. Keep corrected-truth evaluation separate from serving reconstruction so a desirable backfill is not mislabeled as historical online parity. A dataset release should record the retrieval policy, source snapshot, transformation revision, decision-time column, and availability assumptions. Without those details, rerunning the same SQL months later may answer a different temporal question.
The modular instrument illustrates that a later state is not an earlier observation. Reset, set both m=12 and a=1, predict residue two, then Step twice. Separately Reset, set both m=12 and a=1, predict residue five, then Step five times. Selecting the later value does not reconstruct the earlier position. This exact cyclic counter stores no historical rows, availability dimension, TTL, or join logic. It supports the limited distinction between the current state and the state associated with a specified earlier execution position.
Work it through
Exclude a late-known observation
A decision occurs at 12:00 UTC with a thirty-minute lookup horizon. Candidate A has event time 11:40, availability 11:41, and value 4. B has event time 11:55, availability 12:05, and value 9. C has event time 12:01, availability 12:01, and value 12.
A is eligible: its event age is twenty minutes, within the horizon, and it was available nineteen minutes before the decision. Its value can represent the declared as-known lookup.
B has an event age of five minutes but becomes available five minutes after the decision, so it is excluded. C is excluded because its event and availability are after 12:00.
The selected value is 4 from A. An event-time-only latest lookup would choose B’s value 9, introducing late-known information under this contract even though B’s event timestamp is before the prediction.
Filtering by availability changes the candidate set before latest-row selection. Event time alone cannot establish what a serving decision could know.
The living notebook
Explore the model
Interactive lab · modular
Current state is not a historic observation
Reset, set both m=12 and a=1, predict residue two, then Step twice. Separately Reset, set both m=12 and a=1, predict residue five, then Step five times. This additive orbit illustrates execution positions only; it performs no temporal join or reconstruction of feature availability.
- Residue r0
- 0
- Orbit period · m/gcd(m,a)
- 12
- Distinct residues visited
- 1 of 12
Addition modulo m starts at zero: rₙ = na mod m. Playback advances two additions per second. The orbit has period m/gcd(m,a), including period one for a = 0. This is not a cryptographic security test or a primality algorithm. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forDeclare the time being reconstructed instead of substituting the latest available value.
Pause & reason
Check your understanding
Your turn
Try it yourself
A prediction is at 10:00 with a twenty-minute horizon. One row has event time 09:35 and availability 09:36; another has event time 09:50 and availability 09:58. Which can qualify under the stated two-time rule?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Check the event-age horizon and availability independently.
Compare with the solution
The first row is twenty-five minutes old and fails the twenty-minute horizon despite early availability. The second is ten minutes old and was available two minutes before the prediction, so it qualifies. A separate deterministic latest/version rule still applies if other eligible records exist.
Keep the idea
Take it with you
- Separate event time, revision knowledge, and actual serving availability.
- Filter temporal eligibility before latest-version selection.
- Verify the pinned API and backend, and test explicit leakage fixtures.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.