Skip to content

Compute client storage dependents once per hydrate - #7568

Merged
masenf merged 5 commits into
reflex-dev:mainfrom
FarhanAliRaza:farhan/hydrate-storage-dependents
Oct 14, 2026
Merged

masenf merged 5 commits into
reflex-dev:mainfrom
FarhanAliRaza:farhan/hydrate-storage-dependents

Conversation

@FarhanAliRaza

@FarhanAliRaza FarhanAliRaza commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #7508. A smaller alternative to #7515.

Problem

hydrate_and_load sends the snapshot first. Then it passes the browser's client storage values through get_delta overrides again. It marked those values dirty with _mark_dirty. That invalidated their computed dependents, so each dependent was evaluated a second time. The snapshot had already sent them, computed from the same values. In reflex-local-auth, this runs the authenticated_user database query twice on every page load.

Fix

The second pass now builds a delta that holds only the dirty fields. While _send_fields_only is set, build_delta does not invalidate or send computed vars. The pass runs inside the handler, so the flag does not reach any other delta.

The behavior stays the same as on main:

  • Overrides see each browser value once.
  • What an override returns still reaches browser storage.
  • An override still changes only the value sent to the browser, as on every other event.

Testing

A new test, test_hydrate_computes_client_storage_dependents_once, fails on main and passes with the fix. It checks a cached dependent in the same state and a cached dependent in a sibling state. It also checks that an uncached var is not evaluated more often than in a hydrate without stored values.

I also ran an example app in Chrome against main, with stored values set. The app has a cached dependent, a sibling dependent, an uncached var, an override that rewrites a value, and an override that drops a key. Per reload:

main this PR
Cached dependent, same state 2 1
Cached dependent, sibling state 2 1
Uncached var 3 3
Override calls 1 1

The displayed values, the stored values and the backend values stay the same as on main.

The pass now sends its own delta, so a hydrate with stored values sends one more websocket message than on main. This PR does not change that.

View guided diff

hydrate_and_load passes the browser's client storage values through
get_delta overrides after the snapshot. It marked them dirty with
_mark_dirty, so their computed dependents were invalidated and evaluated a
second time, although the snapshot had already sent them computed from the
same values.

Build that delta with only the dirty fields: build_delta skips invalidating
and sending computed vars while _send_fields_only is set. The overrides
still see the browser values once, and what they return still reaches
browser storage.

Fixes reflex-dev#7508
@FarhanAliRaza
FarhanAliRaza requested a review from a team as a code owner October 14, 2026 18:34
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T18:41:08.599559Z 6a7213d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 4 files

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread news/+hydrate-storage-dependents.bugfix.md Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a7213d24b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread reflex/state.py Outdated
@codspeed

codspeed Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 9 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 148 untouched benchmarks


Comparing FarhanAliRaza:farhan/hydrate-storage-dependents (e90bff3) with main (6efb227)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (2fc4a9c) during the generation of this report, so 6efb227 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@greptile-apps

greptile-apps Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues remain.

Summary

The PR avoids computing client-storage dependents again after sending the hydration snapshot.

  • Hydration evaluates client-storage dependents once.

The previous unused-set finding is fixed. The normal build_delta path now creates delta_vars once.

Reviews (3) · Last reviewed commit: "Merge remote-tracking branch 'upstream/m..." · Reviewed by Greptile

Comment thread reflex/istate/delta.py Outdated

@masenf masenf left a comment

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.

nice fix, thanks for simplifying

@masenf
masenf merged commit 7ccaa4e into reflex-dev:main Oct 14, 2026
146 checks passed
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.

Storage-dependent computed vars are evaluated twice on every page load (second boot delta from #7493)

2 participants