FeatureService cannot pin a specific FeatureView/OnDemandFeatureView version
- Dominant language
- Python
- Stars
- 7.3k
- Forks
- 1.4k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 15
Description
### Problem
A `FeatureService` exists to freeze the exact feature definitions a model was
trained and served on. Today it cannot pin a specific feature view **version** —
it always resolves to the active (promoted) version. Feast's own docs name this
limitation verbatim on the [alpha feature-view-versioning page](https://docs.feast.dev/reference/alpha-feature-view-versioning):
> **Feature services** — Feature services always resolve to the active (promoted)
> version. `--no-promote` versions are not served until promoted.
Building a service from a version-pinned `FeatureView` silently falls back to the
promoted version:
```python
fv = FeatureView(name="driver_stats", version="v2", ...)
svc = FeatureService(name="model_v1", features=[fv[["conv_rate"]]])
svc.feature_view_projections[0].version_tag # -> None (should be 2)
svc.feature_view_projections[0].name_to_use() # -> "driver_stats" (should be "driver_stats@v2")
```
### Root cause
1. `FeatureService.__init__` appends the source view's projection without
translating its `version` string into `projection.version_tag` (the field
`name_to_use()` checks to render `fv@v2`).
2. `utils._get_feature_views_to_use` hard-codes the version as `None` for the
`FeatureService` branch, so retrieval always falls through to the promoted
snapshot via `get_any_feature_view`.
While fixing this, a second pre-existing bug surfaced: **offline** retrieval of a
version-pinned `OnDemandFeatureView` fails. Offline stores re-fetch ODFVs from the
registry via an unversioned `registry.list_on_demand_feature_views`, so a pinned
ODFV ref (`odfv@v1:feat`) raises `ValueError: Could not find feature view from
reference ...` or silently drops the ODFV's features. Every offline backend is
affected (they funnel through `OnDemandFeatureView.get_requested_odfvs` or
`offline_utils.get_feature_view_query_context`, plus dask's inline duplicate).
### Proposal
- Capture the pinned version into the service's projection, and read it back at
retrieval time (fixes both online and offline for plain FeatureViews, which
share `_get_feature_views_to_use`).
- Add a clean pinning API: allow plain string refs as `FeatureService.features`
entries (`"driver_stats@v2:trips_today"`), resolved against the registry at
`feast apply` time — no importing/reconstructing historical view objects.
- Fix offline ODFV resolution with a shared version-aware helper.
Gated by the existing `registry.enable_online_feature_view_versioning` flag,
which (despite its name) gates both online and offline versioned resolution.
Contributor guide
Research direction
Start with FeatureService.__init__ and utils._get_feature_views_to_use to trace how version tags are captured and retrieved. Then inspect OnDemandFeatureView.get_requested_odfvs, offline_utils.get_feature_view_query_context, the dask duplicate, and registry.list_on_demand_feature_views. Done means pinned FeatureView and OnDemandFeatureView references resolve online and offline, while string refs are resolved during feast apply.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data-engineering, machine-learning
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100