Skip to content

fix: Disable event processor background flush timers for edge clients#1797

Merged
keelerm84 merged 3 commits into
mainfrom
mk/sdk-2645/fix-eventprocessor-timer-leak
Jul 8, 2026
Merged

fix: Disable event processor background flush timers for edge clients#1797
keelerm84 merged 3 commits into
mainfrom
mk/sdk-2645/fix-eventprocessor-timer-leak

Conversation

@keelerm84

@keelerm84 keelerm84 commented Jul 8, 2026

Copy link
Copy Markdown
Member

Summary

The Fastly Compute SDK creates a new LDClient per request and never calls close(). Because sendEvents defaults on, a real EventProcessor is constructed and its start() creates setInterval flush timers (the event flush timer and the context-deduplication flush timer). Those are cleared only by EventProcessor.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

  • Add an opt-in internal option disableBackgroundEventFlush (LDInternalOptions), threaded through LDClientImpl's FDv1 and FDv2 construction into the EventProcessor's existing start parameter. It defaults to true when the option is unset, so behavior is unchanged for the Node server SDK and every other consumer.
  • Set disableBackgroundEventFlush: true in the Fastly edge client.
  • Document the per-request client lifecycle and event-flushing model in the README, including the reusable-sandboxes caveat (don't module-scope a client and rely on it to self-flush).
  • Add a test asserting the edge client constructs the event processor with start = false.

flush() and sendEvent() do not depend on start() having run (they only use constructor-initialized state; sdk-client already constructs the processor with start = false), so events are still recorded and delivered via explicit flush().

Part of the Fastly refresh epic (SDK-2643). Fixes SDK-2645.


Note

Medium Risk
Touches shared LDClientImpl event-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 EventProcessor background interval timers without ever calling close(), which kept the runtime alive and pinned the client in memory. This change adds an internal disableBackgroundEventFlush flag on ServerInternalOptions, wires it through LDClientImpl (FDv1/FDv2) into the existing EventProcessor start parameter, and enables it for the Fastly LDClient.

Node and other server SDKs are unchanged when the option is unset (startEventProcessor stays true). Events still buffer and ship via explicit flush() / 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 passes start = false to EventProcessor.

Reviewed by Cursor Bugbot for commit 9040b23. Bugbot is set up for automated code reviews on this repo. Configure here.

keelerm84 added 2 commits July 8, 2026 10:09
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.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 26365 bytes
Compressed size limit: 29000
Uncompressed size: 129044 bytes

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 38747 bytes
Compressed size limit: 39000
Uncompressed size: 212249 bytes

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 32027 bytes
Compressed size limit: 34000
Uncompressed size: 114248 bytes

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@launchdarkly/browser size report
This is the brotli compressed size of the ESM build.
Compressed size: 179504 bytes
Compressed size limit: 200000
Uncompressed size: 831427 bytes

@keelerm84
keelerm84 marked this pull request as ready for review July 8, 2026 14:15
@keelerm84
keelerm84 requested a review from a team as a code owner July 8, 2026 14:15
* 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;

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.

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.
@keelerm84
keelerm84 requested a review from joker23 July 8, 2026 15:50
@keelerm84
keelerm84 merged commit bac7f81 into main Jul 8, 2026
53 checks passed
@keelerm84
keelerm84 deleted the mk/sdk-2645/fix-eventprocessor-timer-leak branch July 8, 2026 17:13
@github-actions github-actions Bot mentioned this pull request Jul 8, 2026
keelerm84 pushed a commit that referenced this pull request Jul 8, 2026
🤖 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>
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