How is point-in-time correctness enforced in feature retrieval?
Point-in-time correctness means each historical training example receives only feature values that were valid—and, where the use case requires it, actually available—at the moment its prediction would have been made. This prevents *future-data leakage*, where a model appears excellent in training because it sees information that production could not have known.
Step-by-step numerical example
A delivery company wants to predict a late delivery for restaurant R10 at 10:00 AM. Its feature is restaurant_avg_delay_minutes. A two-hour feature TTL is configured.
Historical feature records for R10:
- 8:30 AM event time, available 8:32 AM, feature value 5 minutes.
- 9:40 AM event time, available 9:45 AM, feature value 7 minutes.
- 9:55 AM event time, available 10:20 AM (late arrival), feature value 9 minutes.
- 10:15 AM event time, available 10:17 AM, feature value 12 minutes.
Step 1: Match entity. Only records for restaurant R10 qualify.
Step 2: Apply the prediction timestamp. For the 10:00 AM prediction, no feature with an event timestamp after 10:00 AM is eligible; the 10:15 AM value 12 is excluded.
Step 3: Apply the two-hour TTL. Eligible event times must be within 8:00–10:00 AM. The 8:30 AM, 9:40 AM, and 9:55 AM events pass this *event-time* age test.
Step 4: Account for actual availability. The 9:55 AM event was not processed until 10:20 AM, so a real 10:00 AM inference service could not have used its value 9. Under a strict availability-aware historical reconstruction, exclude it.
Step 5: Choose the newest remaining eligible value. The 9:40 AM event, available at 9:45 AM, is the most recent admissible record. The correct feature value is 7 minutes.
What would go wrong? A naïve event-time-only join could select 9 (9:55 AM event), overstating information the live model actually possessed. A current-value lookup might select 12, which is outright future leakage.
Two clocks: event time and availability time
- Feature event time: When the represented event happened or its feature value was measured.
- Availability/ingestion time: When the information became accessible to the relevant production feature pipeline.
- Entity timestamp: The historical decision/prediction moment for the example, sometimes called
event_timestampin the entity DataFrame. - Created timestamp: In feature pipelines, often used for record creation and deduplication. It is not automatically equivalent to production availability time.
A sound rule for strict production replay is:
feature.entity_key = example.entity_key
feature.event_time <= example.prediction_time
feature.event_time >= example.prediction_time - TTL
feature.available_at <= example.prediction_timeChoose the most recent admissible feature, with a deterministic revision tie-break. In some systems the production cutoff includes upstream data latency or a fixed feature publication delay; reconstruct the exact policy used at serving time.
Feast point-in-time joins
Feast's get_historical_features matches feature values to historical entity rows. For each entity timestamp, its offline retrieval searches backward for the latest matching feature event time, bounded by the FeatureView's TTL. Feast documentation explicitly notes the TTL is measured relative to each entity timestamp, not relative to the current query execution time.
PYTHONfrom datetime import timedelta import pandas as pd from feast import FeatureStore store = FeatureStore(repo_path=".") entities = pd.DataFrame({ "restaurant_id": ["R10", "R10"], "event_timestamp": pd.to_datetime([ "2026-10-10T10:00:00Z", "2026-10-10T11:00:00Z", ], utc=True), }) training_features = store.get_historical_features( entity_df=entities, features=["restaurant_stats:avg_delay_minutes"], ).to_df() print(training_features)
This is illustrative: restaurant_stats must be an existing configured FeatureView with an entity join key, event timestamp column, source and an appropriately configured TTL; the offline data must be accessible. No fictional output is asserted.
FeatureView TTL is typically defined using ttl=timedelta(hours=2). Source rows and timestamps determine the actual results.
Important limitation: Feast's documented point-in-time join protects against using a feature event timestamp after the entity timestamp, and may use created timestamps to deduplicate duplicate feature rows. It does not by itself guarantee that late-arriving historical records are excluded according to a production availability clock. If that distinction is critical, capture available_at or ingestion/publication metadata and use versioned snapshots, availability-aware filtering, or a custom offline retrieval process validated against serving history. Do not claim the default Feast join solves all forms of late-arrival leakage.
Why TTL matters
TTL limits how far backward a join searches. For a prediction at 10:00 AM and TTL of two hours, a feature event from 7:45 AM is too old even if it was the latest available for that entity. The correct result may be missing/null, not the stale value.
This prevents unbounded use of obsolete features. However, TTL is not a proof of actual freshness or availability: the retrieved event could have been ingested after the prediction.
The SQL intuition: an as-of join
A simplified availability-aware query for one example is:
SQLSELECT f.avg_delay_minutes FROM restaurant_features AS f WHERE f.restaurant_id = 'R10' AND f.event_time <= TIMESTAMP '2026-10-10 10:00:00' AND f.event_time >= TIMESTAMP '2026-10-10 08:00:00' AND f.available_at <= TIMESTAMP '2026-10-10 10:00:00' ORDER BY f.event_time DESC, f.available_at DESC LIMIT 1;
This uses timestamps assumed to share the same timezone, with available_at representing actual availability in the relevant serving system. In production, use timezone-aware types and apply this logic separately to every entity-time row, often through a lateral/as-of join or an optimized feature-store engine.
If two records share the same event timestamp, define how corrected values were published and which revision was available at the cutoff. Never use an arbitrarily current correction when building a supposedly historical training row.
How to test for leakage
- Future-event test: Add a feature record at 10:01 AM and predict at 10:00 AM. The result must not change.
- TTL boundary test: With a two-hour TTL, verify a 7:59 AM value is excluded at 10:00 AM, while a qualifying 8:00 AM value is handled according to defined inclusive-boundary rules.
- Late-arrival test: Add the 9:55 AM event whose
available_atis 10:20 AM. Strict availability-aware retrieval at 10:00 AM must still return 7, not 9. - Entity isolation: Feature rows for restaurant R11 must not affect R10.
- Tie/revision test: For duplicated event timestamps, verify deterministic revision selection without future corrections.
- Missing-value test: When no row qualifies, ensure a missing value and the documented fallback are used, rather than a future or stale value.
- Replay test: Compare historical as-of values to logged online feature snapshots for sample predictions; investigate mismatches from ingestion lag or data corrections.
Operational safeguards
- Preserve immutable feature source snapshots, source watermarks and publication timestamps where needed.
- Keep training cutoff times, feature-view definitions, query versions and entity-row timestamps reproducible.
- Ensure labels are computed independently from future-derived feature fields.
- Separate the target-label observation window from the prediction-time feature cutoff.
- Document timezone and clock-skew handling, especially for distributed producers.
- Do not assume
created_timestampalways proves the record was available to a production service; confirm its precise source semantics.
Common mistakes
- Joining the latest known value today onto a historical observation from last month.
- Checking event time but ignoring delayed arrivals that were unavailable at prediction time.
- Measuring a Feast TTL backward from today instead of from each entity timestamp.
- Returning stale values despite a configured freshness boundary.
- Comparing local times with UTC timestamps without normalization.
- Deduplicating corrected records without preserving what was historically visible.
- Assuming good offline validation accuracy rules out leakage.
In short: Match by entity, restrict feature events to the prediction-time window, enforce TTL, and—when accurate production replay requires it—ensure the feature was actually available by that time. Feast supplies event-time point-in-time joins; availability-time and late-correction guarantees may need additional data engineering and validation.
Sources & Research References
Learning Sequence
MLOps Curriculum
How do feature materialization jobs move values into an online store?
Explore Related Questions
Deepen your understanding across related MLOps topics.