fix: Disable event processor background flush timers for edge clients#1797
Conversation
Add an internal disableBackgroundEventFlush option, threaded through the FDv1/FDv2 construction paths into the EventProcessor's existing start flag (default true, so non-edge SDKs are unchanged). The Fastly edge client sets it: it runs per request and flushes explicitly via event.waitUntil(client.flush()), so the periodic flush timers only leave an interval running that keeps the runtime alive and pins the client graph in memory.
Document that the SDK is created per request and flushed via waitUntil(), that there is no periodic background flush (a background timer cannot reliably send events on Compute, where outbound requests must happen during request handling and the default sandbox is torn down after each request), and the reusable-sandboxes caveat about not module-scoping a client and relying on it to flush on its own. Also fixes the grammar in the events usage note.
|
@launchdarkly/js-sdk-common size report |
|
@launchdarkly/js-client-sdk-common size report |
|
@launchdarkly/js-client-sdk size report |
|
@launchdarkly/browser size report |
| * interval timer keeps the runtime event loop alive and roots the whole client | ||
| * graph in memory, which for a per-request client is a leak. | ||
| */ | ||
| disableBackgroundEventFlush?: boolean; |
There was a problem hiding this comment.
Since this is specific to edge sdks, I think putting this option in packages/shared/sdk-server/src/options/ServerInternalOptions.ts is more appropriate.
Address review feedback on #1797: the flush-timer opt-out is a server-SDK concern consumed only by LDClientImpl, so move it off the shared common LDInternalOptions and onto ServerInternalOptions. Export ServerInternalOptions from js-server-sdk-common so the Fastly edge client can type its internal options with it.
🤖 I have created a release *beep* *boop* --- <details><summary>akamai-edgeworker-sdk-common: 2.0.25</summary> ## [2.0.25](akamai-edgeworker-sdk-common-v2.0.24...akamai-edgeworker-sdk-common-v2.0.25) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common bumped from ^2.19.2 to ^2.19.3 </details> <details><summary>akamai-server-base-sdk: 3.0.26</summary> ## [3.0.26](akamai-server-base-sdk-v3.0.25...akamai-server-base-sdk-v3.0.26) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/akamai-edgeworker-sdk-common bumped from ^2.0.24 to ^2.0.25 </details> <details><summary>akamai-server-edgekv-sdk: 1.4.28</summary> ## [1.4.28](akamai-server-edgekv-sdk-v1.4.27...akamai-server-edgekv-sdk-v1.4.28) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/akamai-edgeworker-sdk-common bumped from ^2.0.24 to ^2.0.25 * @launchdarkly/js-server-sdk-common bumped from ^2.19.2 to ^2.19.3 </details> <details><summary>client-testing-plugin: 1.0.3</summary> ## [1.0.3](client-testing-plugin-v1.0.2...client-testing-plugin-v1.0.3) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/react-sdk bumped from 4.1.4 to 4.1.5 * peerDependencies * @launchdarkly/react-sdk bumped from ^4.1.4 to ^4.1.5 </details> <details><summary>cloudflare-server-sdk: 2.7.27</summary> ## [2.7.27](cloudflare-server-sdk-v2.7.26...cloudflare-server-sdk-v2.7.27) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common-edge bumped from 2.6.23 to 2.6.24 </details> <details><summary>fastly-server-sdk: 0.2.17</summary> ## [0.2.17](fastly-server-sdk-v0.2.16...fastly-server-sdk-v0.2.17) (2026-07-08) ### Bug Fixes * Accept eventsUri option in Fastly SDK init() ([#1791](#1791)) ([18deecd](18deecd)) * Disable event processor background flush timers for edge clients ([#1797](#1797)) ([bac7f81](bac7f81)) * Do not cache rejected KV loads in Fastly EdgeFeatureStore ([#1796](#1796)) ([8f51339](8f51339)) ### Performance Improvements * Import only used crypto-js submodules in Fastly SDK ([#1795](#1795)) ([5c12f19](5c12f19)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common bumped from 2.19.2 to 2.19.3 </details> <details><summary>js-server-sdk-common: 2.19.3</summary> ## [2.19.3](js-server-sdk-common-v2.19.2...js-server-sdk-common-v2.19.3) (2026-07-08) ### Bug Fixes * Disable event processor background flush timers for edge clients ([#1797](#1797)) ([bac7f81](bac7f81)) </details> <details><summary>js-server-sdk-common-edge: 2.6.24</summary> ## [2.6.24](js-server-sdk-common-edge-v2.6.23...js-server-sdk-common-edge-v2.6.24) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common bumped from 2.19.2 to 2.19.3 </details> <details><summary>node-server-sdk: 9.12.1</summary> ## [9.12.1](node-server-sdk-v9.12.0...node-server-sdk-v9.12.1) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common bumped from 2.19.2 to 2.19.3 </details> <details><summary>node-server-sdk-dynamodb: 6.2.33</summary> ## [6.2.33](node-server-sdk-dynamodb-v6.2.32...node-server-sdk-dynamodb-v6.2.33) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/node-server-sdk bumped from 9.12.0 to 9.12.1 * peerDependencies * @launchdarkly/node-server-sdk bumped from >=9.11.3 to >=9.12.1 </details> <details><summary>node-server-sdk-otel: 1.3.20</summary> ## [1.3.20](node-server-sdk-otel-v1.3.19...node-server-sdk-otel-v1.3.20) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/node-server-sdk bumped from 9.12.0 to 9.12.1 * peerDependencies * @launchdarkly/node-server-sdk bumped from >=9.11.3 to >=9.12.1 </details> <details><summary>node-server-sdk-redis: 4.2.32</summary> ## [4.2.32](node-server-sdk-redis-v4.2.31...node-server-sdk-redis-v4.2.32) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/node-server-sdk bumped from 9.12.0 to 9.12.1 * peerDependencies * @launchdarkly/node-server-sdk bumped from >=9.11.3 to >=9.12.1 </details> <details><summary>openfeature-node-server: 1.3.3</summary> ## [1.3.3](openfeature-node-server-v1.3.2...openfeature-node-server-v1.3.3) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/node-server-sdk bumped from 9.12.0 to 9.12.1 * peerDependencies * @launchdarkly/node-server-sdk bumped from ^9.0.0 to ^9.12.1 </details> <details><summary>react-sdk: 4.1.5</summary> ## [4.1.5](react-sdk-v4.1.4...react-sdk-v4.1.5) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common bumped from ^2.19.2 to ^2.19.3 </details> <details><summary>server-sdk-ai: 1.2.1</summary> ## [1.2.1](server-sdk-ai-v1.2.0...server-sdk-ai-v1.2.1) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/js-server-sdk-common bumped from 2.19.2 to 2.19.3 * peerDependencies * @launchdarkly/js-server-sdk-common bumped from ^2.0.0 to ^2.19.3 </details> <details><summary>server-sdk-ai-langchain: 0.8.5</summary> ## [0.8.5](server-sdk-ai-langchain-v0.8.4...server-sdk-ai-langchain-v0.8.5) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/server-sdk-ai bumped from ^1.2.0 to ^1.2.1 * peerDependencies * @launchdarkly/server-sdk-ai bumped from ^1.1.1 to ^1.2.1 </details> <details><summary>server-sdk-ai-openai: 0.7.5</summary> ## [0.7.5](server-sdk-ai-openai-v0.7.4...server-sdk-ai-openai-v0.7.5) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/js-server-sdk-common bumped from 2.19.2 to 2.19.3 * @launchdarkly/server-sdk-ai bumped from ^1.2.0 to ^1.2.1 * peerDependencies * @launchdarkly/server-sdk-ai bumped from ^1.1.1 to ^1.2.1 </details> <details><summary>server-sdk-ai-vercel: 0.7.5</summary> ## [0.7.5](server-sdk-ai-vercel-v0.7.4...server-sdk-ai-vercel-v0.7.5) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * devDependencies * @launchdarkly/server-sdk-ai bumped from ^1.2.0 to ^1.2.1 * peerDependencies * @launchdarkly/server-sdk-ai bumped from ^1.1.1 to ^1.2.1 </details> <details><summary>shopify-oxygen-sdk: 0.1.15</summary> ## [0.1.15](shopify-oxygen-sdk-v0.1.14...shopify-oxygen-sdk-v0.1.15) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common bumped from 2.19.2 to 2.19.3 </details> <details><summary>vercel-server-sdk: 1.3.50</summary> ## [1.3.50](vercel-server-sdk-v1.3.49...vercel-server-sdk-v1.3.50) (2026-07-08) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/js-server-sdk-common-edge bumped from 2.6.23 to 2.6.24 </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
The Fastly Compute SDK creates a new
LDClientper request and never callsclose(). BecausesendEventsdefaults on, a realEventProcessoris constructed and itsstart()createssetIntervalflush timers (the event flush timer and the context-deduplication flush timer). Those are cleared only byEventProcessor.close(), which the SDK and its example never call, so the timers keep the runtime event loop alive and root the whole client graph in memory -- a leak for a per-request client. (This is also what caused jest to hang without--forceExit.)A background flush timer is not a viable delivery mechanism on Fastly Compute anyway: outbound requests must be made while a request is being handled, and by default each request runs in a fresh sandbox that is torn down afterward. The supported pattern is to flush explicitly with
event.waitUntil(client.flush()), which the SDK already documents and the example already uses.Changes
disableBackgroundEventFlush(LDInternalOptions), threaded throughLDClientImpl's FDv1 and FDv2 construction into theEventProcessor's existingstartparameter. It defaults totruewhen the option is unset, so behavior is unchanged for the Node server SDK and every other consumer.disableBackgroundEventFlush: truein the Fastly edge client.start = false.flush()andsendEvent()do not depend onstart()having run (they only use constructor-initialized state;sdk-clientalready constructs the processor withstart = false), so events are still recorded and delivered via explicitflush().Part of the Fastly refresh epic (SDK-2643). Fixes SDK-2645.
Note
Medium Risk
Touches shared
LDClientImplevent-processor construction for all server SDKs, though default behavior is preserved unless edge SDKs opt in.Overview
Per-request Fastly clients were starting the shared
EventProcessorbackground interval timers without ever callingclose(), which kept the runtime alive and pinned the client in memory. This change adds an internaldisableBackgroundEventFlushflag onServerInternalOptions, wires it throughLDClientImpl(FDv1/FDv2) into the existingEventProcessorstartparameter, and enables it for the FastlyLDClient.Node and other server SDKs are unchanged when the option is unset (
startEventProcessorstays true). Events still buffer and ship via explicitflush()/sendEvent()without background timers.The Fastly README now documents per-request
init(),event.waitUntil(ldClient.flush()), and why module-scoped clients are unsafe with reusable sandboxes. A unit test asserts the edge client passesstart = falsetoEventProcessor.Reviewed by Cursor Bugbot for commit 9040b23. Bugbot is set up for automated code reviews on this repo. Configure here.