Skip to content

Make shared storage opt-in, move msgspec to extras - #4095

Merged
T4rk1n merged 4 commits into
devfrom
shared-storage-opt-in
Oct 29, 2026
Merged

T4rk1n merged 4 commits into
devfrom
shared-storage-opt-in

Conversation

@T4rk1n

@T4rk1n T4rk1n commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Shared storage and the streaming downlink it powers (#3930, #3931) were on by default for every app. To keep upgrades from changing how existing deployments run, both are now opt-in, and msgspec is no longer a hard dependency.

Changes

  • Dash() has no shared storage unless shared_storage= is passed or DASH_SHARED_STORAGE is set. An unset, empty or none value disables it, and local turns it on. Streaming callbacks still work without it, each on its own connection, as before.
  • msgspec moves out of the install requirements:
    • The new dash[shared_storage] extra brings it for the persistent LocalSharedStorage modes (persist, persist-reset).
    • dash[diskcache] and dash[redis] each include it, so those backends work from their own install.
  • Without msgspec, in-memory LocalSharedStorage still works across workers, and its socket transport falls back to stdlib JSON.
  • Every backend that writes encoded bytes somewhere lasting (persistent modes, Diskcache, Redis) raises an ImportError naming the extra to install, so the stored format never depends on what happens to be installed.
  • A stream downlink request on an app without shared storage now gets a 403 instead of a 500.

Tests

  • tests/shared_storage/test_no_msgspec.py runs with msgspec blocked. It checks that memory mode works between two processes over JSON, and that each lasting backend raises the right extra's error.
  • test_stwg004 runs 4 gunicorn workers with msgspec blocked and a browser streaming across them.
  • test_downlink_without_shared_storage_is_rejected covers the 403 on Flask, FastAPI and Quart.
  • Tests that relied on the old default now pass LocalSharedStorage explicitly.

Dash() no longer starts shared storage or the multiplexed streaming
downlink unless shared_storage= or DASH_SHARED_STORAGE is set. Streaming
callbacks still work on a per-callback connection without it.

msgspec moves from install requirements to the new dash[shared_storage]
extra (persistent LocalSharedStorage modes) and to dash[diskcache] and
dash[redis]. Without it, in-memory LocalSharedStorage falls back to JSON
on its socket transport.
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Dash performance benchmarks

✅ all within thresholds

scenario metric p90 (ms) median growth baseline p90 note
✅ callback_chain chain_ms 278.5 258.2 0.9x 499.1
✅ callback_chain graph_ms 2.2 2.2 1.0x 2.4
✅ callback_fanout fanout_ms 50.2 47.3 0.87x 92.5
✅ deep_nesting render_ms 38.3 35.7 1.25x 56.8
✅ full_children_replace replace_ms 3121.2 1118.3 18.05x 4697.1
✅ initial_render_large render_ms 396.9 378.5 1.02x 694.4
✅ initial_render_small render_ms 65.0 59.2 2.63x 104.0
✅ patch_append_nested append_ms 113.2 73.2 2.51x 192.3
✅ patch_append_toplevel append_ms 100.4 75.7 2.69x 140.2
✅ patch_scalar_update_large update_ms 129.4 123.7 1.07x 202.9
✅ wildcard_all_resolve wildcard_ms 177.4 169.5 0.94x 313.6
✅ wildcard_all_resolve graph_ms 0.7 0.7 1.0x 1.3

growth = late-third / early-third per-op time; ~1 is flat, a large value means the per-op cost scales with accumulated state.

machine scale vs baseline: 0.62x - divided out of the baseline ratios so they compare like for like (the absolute warn/fail ceilings are left un-scaled); calibrated on initial_render_small.

@sonarqubecloud

Copy link
Copy Markdown

@T4rk1n
T4rk1n merged commit 5abb55c into dev Oct 29, 2026
110 of 115 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.

2 participants