You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
get_online_features forces online stores to make multiple network calls #3259
Is your feature request related to a problem? Please describe.
When using get_online_features, if features from multiple feature views are requested, the FeatureStore._get_online_features implementation groups the features by the feature-view they belong to and calls the online store's online_read method for each of those groups sequentially.
This means that if the online store has the ability to fetch all the data for all the feature-views in one network call, that opportunity is not provided to the online store. For example, in the upcoming BigTable online store implementation, data for different feature-views that share the same entities is colocated. I strongly suspect that it would be faster to fetch all the data in one go than it would be to make multiple sequential network calls.
Describe the solution you'd like
One solution would be to allow the OnlineStore to have a separate method (perhaps called online_read_all or something) that could get all the information regarding all the feature_views and the requested features in one shot (instead of splitting that information across the multiple calls to online_read). If the OnlineStore does not implement the online_read_all method, then we can default to calling the various online_read methods sequentially. This way, we don't break the API of the current online stores.
Additionally, in the FeatureStore._get_online_features method, we could potentially consider performing all the online_reads concurrently. This way, all the existing online stores will experience a potentially free performance lift.
Describe alternatives you've considered
Nothing is currently broken, so the alternative is to just not do anything.
Alternatively, a worse solution would be to provide a hint to the existing online_read method about the other feature views and their requested features. The online_read method could then make a single API call for all of it, cache it somewhere and return only the relevant parts. I'm not too keen on this idea though, since a cleaner API option is still available.
Another alternative would be for any of the online stores to just get data for all the feature views ahead of time (for the same entity keys) in one network call and cache it. I'm not 100% sure if this would actually lead to a reasonable performance gain in all scenarios since there's inherent waste here.
Probably the OnlineStore interface should be a bit more flexible. As long as we can make it happen in a backwards compatible way (should be easy to do? by pushing the logic from the provider into the online store, and defaulting to the existing implementation of online_read)
In my opinion the current implementation of get_online_features should be deprecated with the intention of replacing it with an API which allows for the proposed advantages. This would be in accordance with the 3 minor version Backwards Compatibility Policy: https://docs.feast.dev/project/compatibility
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
But the seam @adchia asked for already exists. _read_features_per_fv went in with 8011550, and its docstring says subclasses can override it to batch. online_read keeps its single feature view signature, so nothing breaks and a store that can batch just opts in.
Redis opted in. Nothing else did: 22 files implement online_read, one overrides the seam.
The Go side already does this right, incidentally. OnlineRead in go/internal/feast/onlinestore/onlinestore.go takes featureViewNames []string and reads them in one shot, so the two implementations have drifted apart.
The precompute path from that same commit covers a good chunk of this, but as far as I can tell only for a FeatureService with precompute_online=True and no ODFVs. Ad hoc feature lists, services that have not opted in, and anything with an ODFV still take the slow path. So batching still seems worth having, though you would know better whether precompute is meant to be the general answer.
Postgres and DynamoDB look like the best places to start. Postgres reads each view's table with SELECT ... WHERE entity_key = ANY(%s), so a UNION ALL with a tag column turns N queries into one. DynamoDB is the fun one: RequestItems is keyed by table name, so batch_get_item already spans tables, and Feast just builds the payload one table at a time.
@ntkathole, since you built the seam: was skipping the other stores scope in that PR or a deliberate call? And would you rather see per store overrides accumulate, or the generic path grow a default batched read for stores that can do a multi table lookup? @tokoko, you kept this one open back in 2024, so you may have a view on whether that is still the right target.
If overrides are fine I would start with Postgres, where the testcontainers setup makes it easy to verify locally, and add a call count test. Nothing references _read_features_per_fv in the tests today, so that would cover Redis too.
@DKilkenny Scoping decision, not a deliberate skip. The _read_features_per_fv seam was introduced as part of the pre-computed feature vectors PR, which focused on two things: (1) moving precompute logic to the base OnlineStore class so it works with all backends, and (2) extracting the per-FV read into an overridable method so stores like Redis could optimize the non-precomputed path with pipeline batching. Adding overrides for Postgres, DynamoDB, etc. was out of scope for that PR but was always the intent behind making it a seam.
Per-store overrides is the right approach. Each store has fundamentally different batching mechanisms. A generic batched read in the base class wouldn't capture these store-specific optimizations. The pattern should be: base class provides the default sequential path, stores override _read_features_per_fv to batch however makes sense for their backend.
Precompute is not the general answer. You're right that it's scoped to FeatureService with precompute_online=True — it's an opt-in materialized-view pattern that trades storage for read speed. Ad-hoc feature lists, services without opt-in, and ODFVs all still go through _read_features_per_fv, so batching there is absolutely worth having.
Activity
adchia commentedon Sep 30, 2022
Probably the OnlineStore interface should be a bit more flexible. As long as we can make it happen in a backwards compatible way (should be easy to do? by pushing the logic from the provider into the online store, and defaulting to the existing implementation of online_read)
judahrand commentedon Oct 7, 2022
In my opinion the current implementation of
get_online_featuresshould be deprecated with the intention of replacing it with an API which allows for the proposed advantages. This would be in accordance with the 3 minor version Backwards Compatibility Policy: https://docs.feast.dev/project/compatibilitystale commentedon Mar 18, 2023
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
DKilkenny commentedon Sep 11, 2026
Hello! I wanted to help contribute to Feast and found this old issue was still open so I'm hoping I could help!
It still reproduces on master, though it has changed since 2022. Three feature views, one request, sqlite store:
But the seam @adchia asked for already exists.
_read_features_per_fvwent in with 8011550, and its docstring says subclasses can override it to batch.online_readkeeps its single feature view signature, so nothing breaks and a store that can batch just opts in.Redis opted in. Nothing else did: 22 files implement
online_read, one overrides the seam.The Go side already does this right, incidentally.
OnlineReadingo/internal/feast/onlinestore/onlinestore.gotakesfeatureViewNames []stringand reads them in one shot, so the two implementations have drifted apart.The precompute path from that same commit covers a good chunk of this, but as far as I can tell only for a
FeatureServicewithprecompute_online=Trueand no ODFVs. Ad hoc feature lists, services that have not opted in, and anything with an ODFV still take the slow path. So batching still seems worth having, though you would know better whether precompute is meant to be the general answer.Postgres and DynamoDB look like the best places to start. Postgres reads each view's table with
SELECT ... WHERE entity_key = ANY(%s), so a UNION ALL with a tag column turns N queries into one. DynamoDB is the fun one:RequestItemsis keyed by table name, sobatch_get_itemalready spans tables, and Feast just builds the payload one table at a time.@ntkathole, since you built the seam: was skipping the other stores scope in that PR or a deliberate call? And would you rather see per store overrides accumulate, or the generic path grow a default batched read for stores that can do a multi table lookup? @tokoko, you kept this one open back in 2024, so you may have a view on whether that is still the right target.
If overrides are fine I would start with Postgres, where the testcontainers setup makes it easy to verify locally, and add a call count test. Nothing references
_read_features_per_fvin the tests today, so that would cover Redis too.ntkathole commentedon Sep 11, 2026
@DKilkenny Scoping decision, not a deliberate skip. The
_read_features_per_fvseam was introduced as part of the pre-computed feature vectors PR, which focused on two things: (1) moving precompute logic to the base OnlineStore class so it works with all backends, and (2) extracting the per-FV read into an overridable method so stores like Redis could optimize the non-precomputed path with pipeline batching. Adding overrides for Postgres, DynamoDB, etc. was out of scope for that PR but was always the intent behind making it a seam.Per-store overrides is the right approach. Each store has fundamentally different batching mechanisms. A generic batched read in the base class wouldn't capture these store-specific optimizations. The pattern should be: base class provides the default sequential path, stores override
_read_features_per_fvto batch however makes sense for their backend.Precompute is not the general answer. You're right that it's scoped to FeatureService with precompute_online=True — it's an opt-in materialized-view pattern that trades storage for read speed. Ad-hoc feature lists, services without opt-in, and ODFVs all still go through
_read_features_per_fv, so batching there is absolutely worth having.Feel free to add and extend it, happy to review.
feat: Batch Postgres online reads across feature views
feat: Batch Postgres online reads across feature views
feat: Batch Postgres online reads across feature views
feat: Batch Postgres online reads across feature views
feat: Batch Postgres online reads across feature views
feat: Batch Postgres online reads across feature views
feat: Batch Postgres online reads across feature views (#6832)
chore(release): release 0.67.0
fix: Merge upstream feast-dev/feast master - resolve CSV conflict (#247)