Skip to content

fix(stream): raise SSE event limit to 5 MiB and honour per-call maxEv… - #567

Merged
ditadi merged 1 commit into
mainfrom
fix/stream-config-per-call-overrides
Sep 2, 2026
Merged

fix(stream): raise SSE event limit to 5 MiB and honour per-call maxEv…#567
ditadi merged 1 commit into
mainfrom
fix/stream-config-per-call-overrides

Conversation

@ditadi

@ditadi ditadi commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Analytics queries returning more than 1 MiB of JSON failed. The SSE event size limit (streamDefaults.maxEventSize) was 1 MiB, and oversized events are dropped — so a legitimate result set silently never reached the client.

The documented workaround (format="ARROW_STREAM", which bypasses SSE) isn't viable for every app.

There was also a second problem: StreamConfig.maxEventSize could be passed per call via executeStream({ stream: { maxEventSize } }), it type-checked, and it was then silently ignored. The value was only ever read in the StreamManager constructor, and BasePlugin constructs its manager with no arguments — so there was no way to raise the limit at all.

Changes

1. Default raised from 1 MiB to 5 MiB

At ~234 bytes per row (typical dashboard row: ids, timestamps, metrics, labels), this moves the ceiling from ~4.5k to ~22k rows. Measured peak heap is ~11 MB per stream, comfortable against the 6 GB of a Medium app. 5 MiB also matches the existing MAX_RESPONSE_BYTES in the database plugin.

Raised on both sides: streamDefaults.maxEventSize and connectSSE's maxBufferSize. These must stay in sync — a smaller client buffer turns a legal server event into "Buffer size exceeded" plus retries.

2. maxEventSize now honoured per call

Resolved once at stream creation and stored on the StreamEntry, instead of read off the shared StreamManager instance. One manager serves every stream a plugin opens, which is why the instance field made per-call overrides ineffective.

3. Size measured in UTF-8 bytes

The check used String.length (UTF-16 code units) while the error message said "bytes". Non-ASCII payloads (accents, CJK, emoji) could exceed the limit on the wire and still pass.

Scope

13 lines of production code across 4 files. bufferTTL, disconnectGraceMs, heartbeatInterval and maxActiveStreams are untouched — they have the same constructor-only limitation, but fixing them isn't needed here.

Tests

4 tests covering the per-call path, which had no coverage before (the constructor path did — that's how this survived). Verified by reintroducing each bug and confirming the tests fail.

pnpm -r typecheck clean; 112 stream tests passing.

@ditadi
ditadi requested a review from a team as a code owner September 2, 2026 12:45
@ditadi
ditadi requested a review from MarioCadenas September 2, 2026 12:45
…entSize

Signed-off-by: ditadi <victordperd@gmail.com>
@ditadi
ditadi force-pushed the fix/stream-config-per-call-overrides branch from b7a0c3b to 7ac639b Compare September 2, 2026 12:46
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle size report

Compared against bundle-size-baseline.json (main).

@databricks/appkit

npm tarball (packed): 1.0 MB (+244 B) — gzipped download (dist + bin; excludes release-only docs/NOTICE).

dist raw gzip
JS (runtime) 1.0 MB (+223 B) 376 KB (+42 B)
Type declarations 385 KB 136 KB
Source maps 2.1 MB (+484 B) 704 KB (+184 B)
Other 11 KB 3.7 KB
Total 3.5 MB (+707 B) 1.2 MB (+226 B)
Per-entry composition (own code — deps external (as shipped))
Entry Initial (gz) Lazy (gz) Total (gz) node_modules (min) Own code (min)
. 95 KB (+24 B) 2.5 KB 97 KB (+24 B) external 311 KB (+58 B)
./beta 75 KB (+37 B) 458 B (+1 B) 75 KB (+38 B) external 225 KB (+58 B)
./testing 17 KB 0 B 17 KB external 50 KB
./tsdown 520 B 0 B 520 B external 813 B
./type-generator 22 KB 0 B 22 KB external 65 KB

Chunks:

Entry Chunk Load Size (gz)
. index.js initial 91 KB
. utils.js initial 4.0 KB
. remote-tunnel-manager.js lazy 2.5 KB
./beta beta.js initial 59 KB
./beta stream-manager.js initial 5.8 KB
./beta wide-event-emitter.js initial 3.2 KB
./beta databricks.js initial 3.2 KB
./beta configuration.js initial 2.1 KB
./beta service-context.js initial 1.3 KB
./beta client.js initial 434 B
./beta client-options.js initial 220 B
./beta supervisor-api.js lazy 193 B
./beta databricks.js lazy 142 B
./beta index.js lazy 123 B
./testing index.js initial 17 KB
./tsdown index.js initial 520 B
./type-generator index.js initial 22 KB

@databricks/appkit-ui

npm tarball (packed): 350 KB (-59 B) — gzipped download (dist + bin; excludes release-only docs/NOTICE).

dist raw gzip
JS (runtime) 395 KB 132 KB
Type declarations 229 KB 84 KB (+1 B)
Source maps 766 KB (-121 B) 253 KB (-76 B)
CSS 16 KB 3.2 KB
Total 1.4 MB (-121 B) 473 KB (-75 B)
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
Entry Initial (gz) Lazy (gz) Total (gz) node_modules (min) Own code (min)
./js 5.3 KB 49 KB 55 KB 208 KB 14 KB
./js/beta 20 B 0 B 20 B 0 B 0 B
./react 432 KB 49 KB 481 KB 1.3 MB 177 KB
./react/beta 1.0 KB 0 B 1.0 KB 0 B 1.9 KB

Chunks:

Entry Chunk Load Size (gz)
./js index.js initial 5.2 KB
./js chunk initial 120 B
./js apache-arrow lazy 49 KB
./js/beta beta.js initial 20 B
./react index.js initial 430 KB
./react tslib initial 2.1 KB
./react apache-arrow lazy 49 KB
./react/beta beta.js initial 1.0 KB

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

🤖 AppKit PR bot

🔬 Run evals

Start an eval for this PR from the evals-monitor app: Go to Evals Monitor →

📦 Try this PR's app template

Scaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh auth login — and the Databricks CLI):

gh run download 33631840535 -R databricks/appkit -n appkit-template-0.69.1-pr.5f175f9-fix-stream-config-per-call-overrides-567 -D appkit-pr-567 \
  && unzip -o "appkit-pr-567/appkit-template-0.69.1-pr.5f175f9-fix-stream-config-per-call-overrides-567.zip" -d "appkit-pr-567" \
  && databricks apps init --template "appkit-pr-567"

The template pins @databricks/appkit and @databricks/appkit-ui to tarballs built from this branch, so the scaffolded app runs against this PR's code.

@ditadi
ditadi enabled auto-merge (squash) September 2, 2026 12:57
@ditadi
ditadi merged commit e7474c8 into main Sep 2, 2026
12 checks passed
@ditadi
ditadi deleted the fix/stream-config-per-call-overrides branch September 2, 2026 12:59
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