Summary
Since v0.64.0, get_online_features refuses to serve any FeatureView whose lifecycle state is
not AVAILABLE_ONLINE/STATE_UNSPECIFIED. Because store.materialize() transitions a FV to
MATERIALIZING in the (shared) registry for the duration of its run, online serving fails for that
FV while it is being materialized. For the canonical setup — a long-running feast serve plus a
periodic (incremental) materialization job sharing one registry — this turns routine materialization
into recurring online-serving outages. Requesting a config option to keep serving the last-materialized
values during MATERIALIZING.
Current behavior
sdk/python/feast/utils.py (_get_online_features) enforces an unconditional gate:
raise ValueError(
f"Feature view '{name}' is in state '{fv.state.name}' "
f"and cannot serve features. Only AVAILABLE_ONLINE feature views can serve."
)
FeatureStore.materialize() sets the FV to MATERIALIZING and commits it to the registry before
writing (feature_view.state = FeatureViewState.MATERIALIZING; self.registry.apply_feature_view(..., commit=True)).
A separate feature server reading the same registry (subject to cache_ttl_seconds) then observes
MATERIALIZING and rejects requests. Since a get_online_features call spans all requested FVs, a
single materializing FV fails the entire request (including any feature service that references it).
Steps to reproduce
- feast apply, then materialize once so the FV is AVAILABLE_ONLINE.
- Start feast serve; confirm /get-online-features works.
- Run feast materialize for that FV (or set its state to MATERIALIZING).
- Call /get-online-features for the same FV during the run →
ValueError: Feature view '<name>' is in state 'MATERIALIZING' and cannot serve features.
Impact
- Continuous online serving + periodic incremental materialization is the standard online pattern;
with one shared registry the serving tier unavoidably observes MATERIALIZING.
- Materialization is exactly when the previous values are still valid and should keep being served;
instead reads hard-fail.
- Blast radius is the whole request / feature service, not just the one FV.
When it was introduced
The gate was added in PR #6401 (“Add enabled/disabled toggle for feature views”), first released in
v0.64.0, and is present unchanged in v0.65.0, v0.66.0, and master. It is unconditional —
there is no config to opt out. Versions ≤ v0.63.x do not have it.
Proposed solution
Add a config flag (e.g. under online_store or top-level in feature_store.yaml) such as:
serve_during_materialization: true # default false to preserve current behavior
When enabled, _get_online_features treats MATERIALIZING as servable (serves the last-materialized
values) instead of raising. GENERATED / never-materialized FVs can still be gated. Alternatively,
scope the gate so MATERIALIZING is always servable (only truly-unavailable states are rejected),
since a FV that is re-materializing already has prior data online.
Environment
- Feast: 0.65.0 (also confirmed in 0.64.0, 0.66.0, master)
- Online store: Redis · Offline store: Athena · Registry: file (S3), shared between feast serve
and a scheduled feast materialize
Summary
Since v0.64.0, get_online_features refuses to serve any FeatureView whose lifecycle state is
not AVAILABLE_ONLINE/STATE_UNSPECIFIED. Because store.materialize() transitions a FV to
MATERIALIZING in the (shared) registry for the duration of its run, online serving fails for that
FV while it is being materialized. For the canonical setup — a long-running feast serve plus a
periodic (incremental) materialization job sharing one registry — this turns routine materialization
into recurring online-serving outages. Requesting a config option to keep serving the last-materialized
values during MATERIALIZING.
Current behavior
sdk/python/feast/utils.py (_get_online_features) enforces an unconditional gate:
FeatureStore.materialize() sets the FV to MATERIALIZING and commits it to the registry before
writing (feature_view.state = FeatureViewState.MATERIALIZING; self.registry.apply_feature_view(..., commit=True)).
A separate feature server reading the same registry (subject to cache_ttl_seconds) then observes
MATERIALIZING and rejects requests. Since a get_online_features call spans all requested FVs, a
single materializing FV fails the entire request (including any feature service that references it).
Steps to reproduce
ValueError: Feature view '<name>' is in state 'MATERIALIZING' and cannot serve features.
Impact
with one shared registry the serving tier unavoidably observes MATERIALIZING.
instead reads hard-fail.
When it was introduced
The gate was added in PR #6401 (“Add enabled/disabled toggle for feature views”), first released in
v0.64.0, and is present unchanged in v0.65.0, v0.66.0, and master. It is unconditional —
there is no config to opt out. Versions ≤ v0.63.x do not have it.
Proposed solution
Add a config flag (e.g. under online_store or top-level in feature_store.yaml) such as:
When enabled, _get_online_features treats MATERIALIZING as servable (serves the last-materialized
values) instead of raising. GENERATED / never-materialized FVs can still be gated. Alternatively,
scope the gate so MATERIALIZING is always servable (only truly-unavailable states are rejected),
since a FV that is re-materializing already has prior data online.
Environment
and a scheduled feast materialize