Skip to content

feat: Add remote materialization support via feature server#6590

Open
aniketpalu wants to merge 9 commits into
feast-dev:masterfrom
aniketpalu:feat/remote-materialize
Open

feat: Add remote materialization support via feature server#6590
aniketpalu wants to merge 9 commits into
feast-dev:masterfrom
aniketpalu:feat/remote-materialize

Conversation

@aniketpalu

@aniketpalu aniketpalu commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

Allow store.materialize() and materialize_incremental() to delegate execution to the feature server instead of running the batch engine locally. This eliminates the need for engine-specific dependencies (PySpark, kubernetes client, etc.) and RBAC on the client pod. Components:

  • New shared poll_materialization_status() function
  • Client-side _remote_materialize() with registry-based FV state polling
  • POST /materialize-async and /materialize-incremental-async endpoints (202)
  • materialize_mode, url, timeout, poll_interval config fields
  • 19 unit tests + 2 E2E integration tests Addresses Remote materialization #4526 (remote materialization).

Which issue(s) this PR fixes:

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

Misc

Allow store.materialize() and materialize_incremental() to delegate
execution to the feature server instead of running the batch engine
locally. This eliminates the need for engine-specific dependencies
(PySpark, kubernetes client, etc.) and RBAC on the client pod.
Components:
- New shared poll_materialization_status() function
- Client-side _remote_materialize() with registry-based FV state polling
- POST /materialize-async and /materialize-incremental-async endpoints (202)
- materialize_mode, url, timeout, poll_interval config fields
- 19 unit tests + 2 E2E integration tests
Addresses feast-dev#4526 (remote materialization).

Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
@aniketpalu
aniketpalu requested a review from a team as a code owner July 8, 2026 21:27
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
Allow store.materialize() and materialize_incremental() to delegate
execution to the feature server instead of running the batch engine
locally. This eliminates the need for engine-specific dependencies
(PySpark, kubernetes client, etc.) and RBAC on the client pod.
Components:
- Shared poll_materialization_status() with stateful FV state tracking
- Client-side _remote_materialize_common() with auth forwarding
- POST /materialize-async and /materialize-incremental-async (202)
- _force_local guard prevents infinite recursion on server
- Concurrency guard returns 409 if FV already materializing
- version parameter forwarded through full chain
- materialize_mode, url, timeout, poll_interval config fields
Addresses feast-dev#4526 (remote materialization).

Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
- Use allow_cache=False in concurrency guard to avoid stale registry reads
- Close HTTP session in finally block to prevent resource leaks
- Wrap remote HTTP call with descriptive error message and exception chaining
- Add from-e chaining on timestamp parse errors
- Improve timeout error message with actionable guidance
- Add @model_validator to reject remote mode without url at config time
- Add unit test for config validation

Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
Comment on lines +15 to +17
materialize_mode: Literal["local", "remote"] = "local"
"""When 'remote', store.materialize() delegates to the feature server's
async endpoint instead of running the batch engine locally."""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we dont need to provide the materialize_mode config. We should strictly feature server take care of materialization delegation to compute engine. Leaving no choice to do materialization on client side.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A cleaner approach might be: a RemoteComputeEngine (like RemoteOnlineStore/RemoteOfflineStore) that POSTs to the existing /materialize endpoint, returning a job handle with a dedicated /materialize-status/{job_id} endpoint - keeping the materialization delegation at the engine layer rather than the FeatureStore layer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you mean something like

batch_engine:
  type: remote.engine
  path: https://feast-online:443   # same host as online
  cert: /var/run/secrets/.../service-ca.crt

I thought about this before choosing current approach. I see two points which made me not take this decision.

  1. This adds another config section which has to indicate only one thing, i.e. trigger materialization on feature server. For this, it add 1 config section & user has to configure 2 redundant fields.
  2. Once client is initialized, user wont have option to try normal materialization flow if remote materialization fails for any reason.

My proposed approach is

store.materialize(remote=True, wait=False) --> pre-process check & return 202 Accepted response
store.poll_materialization() --> returns status

This approach has

  1. Backward compatibility - User can fall back without re-initializing client.
  2. Flexibility of Status polling - Full control to user to set interval of polling.
  3. No need of Operator changes.
  4. The same API can work for UI as well

aniketpalu and others added 4 commits July 10, 2026 13:35
apply_materialization() in SQL and Snowflake registries did not
transition FeatureViewState like the file-based registry does. This
caused remote materialization polling (and any state-based monitoring)
to never see completion when using these registry backends.

Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
- Pass online_store.cert as verify= on the materialize-async HTTP call
  (same server hosts both online store and materialize endpoints)
- Set FV state to AVAILABLE_ONLINE in SQL/Snowflake registry
  apply_materialization() to match file-based registry behavior

Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
Opt in with materialize(..., remote=True); URL/TLS from online_store.
Add wait=False and poll_materialization(); set MATERIALIZING before 202
and reset to GENERATED on async failure; include state in FeatureView.__eq__.
aniketpalu added a commit to aniketpalu/feast that referenced this pull request Jul 14, 2026
Keep feast-dev#6550 batching in materialize loops; skip FV state transition when
_force_local so async /materialize-async (already MATERIALIZING) works.

Co-authored-by: Cursor <cursoragent@cursor.com>
aniketpalu added a commit to aniketpalu/feast that referenced this pull request Jul 14, 2026
Keep feast-dev#6550 batching; skip FV state transition when _force_local so
/materialize-async (already MATERIALIZING) works with SparkApplication.

Co-authored-by: Cursor <cursoragent@cursor.com>
aniketpalu added a commit to aniketpalu/feast that referenced this pull request Jul 16, 2026
Keep feast-dev#6550 batching; skip FV state transition when _force_local so
/materialize-async (already MATERIALIZING) works with SparkApplication.

Co-authored-by: Cursor <cursoragent@cursor.com>
Bring in feast-dev#6550 SparkApplication (supports_batch / _materialize_fvs_batch).
Resolve feature_store.py by keeping master batch structure and threading
_force_local through transition/rollback/batch helpers so async remote-mat
does not double-set MATERIALIZING or wrongly roll back state.

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov-commenter

codecov-commenter commented Jul 18, 2026

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 75.11521% with 54 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.78%. Comparing base (dcd496f) to head (c1f53c9).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
sdk/python/feast/feature_store.py 63.15% 31 Missing and 4 partials ⚠️
sdk/python/feast/feature_server.py 82.19% 12 Missing and 1 partial ⚠️
sdk/python/feast/infra/registry/snowflake.py 0.00% 3 Missing ⚠️
sdk/python/feast/infra/registry/sql.py 0.00% 3 Missing ⚠️
❗ 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    #6590      +/-   ##
==========================================
- Coverage   46.00%   45.78%   -0.22%     
==========================================
  Files         406      413       +7     
  Lines       48164    48974     +810     
  Branches     6814     6950     +136     
==========================================
+ Hits        22157    22425     +268     
- Misses      24461    25000     +539     
- Partials     1546     1549       +3     
Flag Coverage Δ
go-feature-server 30.58% <ø> (ø)
python-unit 47.07% <75.11%> (-0.26%) ⬇️
Files with missing lines Coverage Δ
sdk/python/feast/feature_view.py 85.71% <ø> (ø)
sdk/python/feast/materialization_status.py 100.00% <100.00%> (ø)
sdk/python/feast/infra/registry/snowflake.py 39.35% <0.00%> (-0.22%) ⬇️
sdk/python/feast/infra/registry/sql.py 57.70% <0.00%> (-0.26%) ⬇️
sdk/python/feast/feature_server.py 65.43% <82.19%> (+2.59%) ⬆️
sdk/python/feast/feature_store.py 42.62% <63.15%> (+1.56%) ⬆️

... and 10 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 dcd496f...c1f53c9. 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.

aniketpalu added a commit to aniketpalu/feast that referenced this pull request Jul 18, 2026
Refresh with current feast-dev#6590 tip (includes master merge with feast-dev#6550).
Keep spark_application Dockerfile postgres extra for E2E.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants