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_featuresrefuses to serve any FeatureView whose lifecycle state isnot
AVAILABLE_ONLINE/STATE_UNSPECIFIED. Becausestore.materialize()transitions a FV toMATERIALIZINGin the (shared) registry for the duration of its run, online serving fails for thatFV while it is being materialized. For the canonical setup — a long-running
feast serveplus aperiodic (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 toMATERIALIZINGand commits it to the registry beforewriting (
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 observesMATERIALIZINGand rejects requests. Since aget_online_featurescall spans all requested FVs, asingle materializing FV fails the entire request (including any feature service that references it).
Steps to reproduce
feast apply, then materialize once so the FV isAVAILABLE_ONLINE.feast serve; confirm/get-online-featuresworks.feast materializefor that FV (or set its state toMATERIALIZING)./get-online-featuresfor the same FV during the run →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_storeor top-level infeature_store.yaml) such as:When enabled,
_get_online_featurestreatsMATERIALIZINGas servable (serves the last-materializedvalues) instead of raising.
GENERATED/ never-materialized FVs can still be gated. Alternatively,scope the gate so
MATERIALIZINGis always servable (only truly-unavailable states are rejected),since a FV that is re-materializing already has prior data online.
Environment
feast serveand a scheduled
feast materialize