GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat: Batch DynamoDB online reads across feature views by NopeCharon · Pull Request #7134 · feast-dev/feast

Conversation

@NopeCharon

@NopeCharon NopeCharon commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

The generic OnlineStore._read_features_per_fv loop reads one feature view after another. For DynamoDB that means a sync get_online_features call spanning N feature views costs at least N sequential BatchGetItem round trips, and the async path sends at least N separate requests. Redis and PostgreSQL already override this seam to batch. This PR does the same for DynamoDB, as discussed in #3259, where per-store overrides were agreed as the approach.

DynamoDB keeps each feature view in its own table, and one BatchGetItem request can read from several tables. The override:

  • resolves every view's table name (versioning included) and entity ids up front;
  • packs all of the keys into as few requests as possible, with at most batch_size keys per request across all of its tables. Each table keeps its own ProjectionExpression and ConsistentRead;
  • sends the requests in parallel: a thread pool capped at max_read_workers on the sync path, asyncio.gather on the async path;
  • splits the returned items back apart by table and entity id, and fills the response in grouped_refs order.

For example, a request for 10 feature views and 5 entities now needs 1 BatchGetItem call instead of 10.

BatchGetItem rejects a request that lists the same key twice for a table. So views that map to the same table, such as one feature view requested under two aliases, are read once, projecting the union of their requested features. Extra features in a row are already ignored when the response is filled.

The gating follows the PostgreSQL implementation (#6832):

  • A single-view request always takes the generic path, because there is nothing to combine.
  • Requests larger than the new max_batched_result_rows setting (entity rows × feature views, default 2048) also take the generic path. At that size each view already fills requests of its own, so packing saves at most one partly filled request per view, while holding every view's items at once raises peak memory.
  • Setting max_batched_result_rows: 0 turns batching off.

Error and throttling behaviour does not change: any exception from batch_get_item still propagates, and UnprocessedKeys are handled the same way as in the per-view path. The item decoding in _process_batch_get_response moves into a shared _to_read_row helper, so both paths parse items the same way.

Docs: the DynamoDB online store reference (new option plus a performance note) and the online server performance tuning guide.

Which issue(s) this PR fixes:

Refs #3259

Checks

  • I've made sure the tests are passing.
  • My commits are signed off (git commit -s)
  • My PR title follows conventional commits format

Testing Strategy

  • Unit tests
  • Integration tests
  • Manual tests
  • Testing is not required for this change

New tests are in sdk/python/tests/unit/infra/online_store/test_dynamodb_batched_read.py. They run against moto-backed tables, and each one covers both the sync and the async override:

  • One request serves three views (two of them share an entity id and a feature name, and the third is keyed on a different entity), and the response matches the generic per-view path exactly, including entities that are missing from one view.
  • Keys are packed across tables up to batch_size.
  • Aliases of one view read each key once, with the union projection.
  • Projection is set per table.
  • A single view, max_batched_result_rows: 0, or a request over the limit falls back to one online_read per view.
  • Config default and validation.

The existing DynamoDB unit tests still pass.

Misc

Release note: The DynamoDB online store now packs the reads of every feature view in a request into shared BatchGetItem calls, so requests that span several feature views need fewer round trips. The new max_batched_result_rows option controls this.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@NopeCharon
NopeCharon requested a review from a team as a code owner November 11, 2026 17:21
@codecov-commenter

codecov-commenter commented Nov 11, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 97.93814% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.06%. Comparing base (5efc16f) to head (51b75b5).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
sdk/python/feast/infra/online_stores/dynamodb.py 97.93% 1 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #7134      +/-   ##
==========================================
+ Coverage   51.88%   52.06%   +0.18%     
==========================================
  Files         458      459       +1     
  Lines       57726    57881     +155     
  Branches     8486     8506      +20     
==========================================
+ Hits        29950    30137     +187     
+ Misses      25745    25705      -40     
- Partials     2031     2039       +8     
Flag Coverage Δ
go-feature-server 30.58% <ø> (ø)
python-unit 53.58% <97.93%> (+0.19%) ⬆️
Files with missing lines Coverage Δ
sdk/python/feast/infra/online_stores/dynamodb.py 73.99% <97.93%> (+8.64%) ⬆️

... and 8 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5efc16f...51b75b5. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ntkathole
ntkathole force-pushed the feat/dynamodb-batched-online-read branch from bb3b127 to 4342d12 Compare November 12, 2026 03:59
@ntkathole ntkathole added the ok-to-test label Nov 12, 2026
ntkathole
ntkathole approved these changes Nov 12, 2026
View reviewed changes
@NopeCharon @ntkathole
feat: Batch DynamoDB online reads across feature views
51b75b5
The generic OnlineStore._read_features_per_fv loop reads one feature view after
another, so a sync request spanning N feature views costs at least N sequential
BatchGetItem round trips, and an async one at least N concurrent requests. Redis
and Postgres already override that seam to batch; DynamoDB now does too.

Each feature view lives in its own DynamoDB table, and a single BatchGetItem
request can read from several tables at once. The override resolves every view's
entity ids up front, packs all of the keys into as few requests as possible
(at most batch_size keys each, across all of their tables), sends those requests
in parallel (a thread pool capped at max_read_workers on the sync path,
asyncio.gather on the async path) and then splits the returned items back apart
by table and entity id. Each table keeps its own ProjectionExpression and
ConsistentRead setting.

BatchGetItem rejects a request that repeats a key within a table, so views that
map to the same table, such as one feature view requested under two aliases, are
read once with the union of their requested features.

Following the Postgres implementation, a single-view request keeps the generic
path, and requests larger than the new max_batched_result_rows setting (entity
rows x feature views, default 2048, 0 disables batching) also fall back to it.
Past that size each view already fills requests of its own, so packing saves at
most one partially filled request per view while holding every view's items at
once.

The item parsing in _process_batch_get_response moves into a shared _to_read_row
helper so the batched and per-view paths decode items identically.

Refs feast-dev#3259

Signed-off-by: NopeCharon <[email protected]>
@ntkathole
ntkathole force-pushed the feat/dynamodb-batched-online-read branch from 4342d12 to 51b75b5 Compare November 12, 2026 06:49
@ntkathole
ntkathole merged commit 915df1f into feast-dev:master Nov 12, 2026
19 of 23 checks passed

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ntkathole ntkathole ntkathole approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

ok-to-test

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@NopeCharon @codecov-commenter @ntkathole
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.