Skip to content

fix(otlp-exporter-base): remove sendBeacon in favor of fetch with keepalive#6391

Merged
overbalance merged 9 commits intoopen-telemetry:mainfrom
embrace-io:overbalance/remove-sendbeacon
Feb 16, 2026
Merged

fix(otlp-exporter-base): remove sendBeacon in favor of fetch with keepalive#6391
overbalance merged 9 commits intoopen-telemetry:mainfrom
embrace-io:overbalance/remove-sendbeacon

Conversation

@overbalance
Copy link
Contributor

@overbalance overbalance commented Feb 10, 2026

Which problem is this PR solving?

TLDR sendBeacon uses fetch+keepalive internally

navigator.sendBeacon() cannot see HTTP response codes, it returns whether the request was queued, not whether the server accepted it:

const queued = navigator.sendBeacon(url, data);
// queued === true, but server returned 503 → data silently lost

This means server errors (503, 429) cause silent data loss with no opportunity to retry. The RetryingTransport wrapper expects a 'retryable' status to trigger retries, but sendBeacon could only return 'success' or 'failure', breaking the retry logic entirely.

Additionally, when the browser's cumulative 64KB limit or 9 concurrent request limit is exceeded, sendBeacon rejects the request outright by returning false. There's no way to fall back to a non-keepalive request that would still deliver the data.

Fixes #3489
Fixes #6274

Short description of the changes

Replace sendBeacon transport with fetch + keepalive and track pending requests to stay within browser limits:

  • 60KB cumulative body size (headroom below 64KB browser limit)
  • 9 concurrent keepalive requests (Chrome limit)
  • Graceful degradation: When limits exceeded, disable keepalive (request still works, just won't survive page unload)
  • Deprecate createOtlpSendBeaconExportDelegate: Still works but delegates to fetch transport

Impact

Scenario Before After
Server returns 503 Data silently lost Retried via RetryingTransport
64KB limit exceeded Request fails Request succeeds without keepalive
Page unload sendBeacon queues blindly fetch+keepalive with limit tracking

Migration

For SDK users: No action required. Behavior improves automatically.

For custom transports: If using createOtlpSendBeaconExportDelegate, it still works but is deprecated. Switch to createOtlpFetchExportDelegate when convenient.

References

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • npm run compile && npm test passes
  • npm run test:browser passes
  • Queue tracking: keepalive enabled/disabled based on limits
  • Retry integration: 503/429 retried, 404 not retried
  • Counter cleanup after request completion

Checklist:

  • Followed the style guidelines of this project
  • Unit tests have been added

@codecov
Copy link

codecov bot commented Feb 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.59%. Comparing base (bfd06e6) to head (ae60364).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6391      +/-   ##
==========================================
+ Coverage   95.50%   95.59%   +0.08%     
==========================================
  Files         365      361       -4     
  Lines       11617    11595      -22     
  Branches     2681     2683       +2     
==========================================
- Hits        11095    11084      -11     
+ Misses        522      511      -11     
Files with missing lines Coverage Δ
...tlp-exporter-base/src/transport/fetch-transport.ts 94.64% <100.00%> (+2.97%) ⬆️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@overbalance overbalance force-pushed the overbalance/remove-sendbeacon branch from 9cf8b11 to ed17d13 Compare February 10, 2026 18:04
@overbalance overbalance marked this pull request as ready for review February 10, 2026 18:06
@overbalance overbalance requested a review from a team as a code owner February 10, 2026 18:06
@overbalance overbalance requested a review from a team as a code owner February 10, 2026 18:17
@overbalance overbalance added the browser Browser-specific additions or benefits label Feb 10, 2026
*/

describe('OTLPTraceExporter', () => {
describe('OTLPMetricExporter', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Typo seemed within scope.

Comment on lines +43 to +47
/**
* Track cumulative pending body size across all in-flight keepalive requests.
* This is necessary because the 64KiB limit is cumulative, not per-request.
*/
let pendingBodySize = 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This applies to all requests per renderer, so not just OTel requests from my understanding. I don't think there's a better solution here but am open to ideas.

Copy link
Member

@pichlermarc pichlermarc left a comment

Choose a reason for hiding this comment

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

this looks good. once this is merged, we should also add an issue to remove the deprecated code eventually.

Would appreciate one additional review from @open-telemetry/browser-approvers before merging this :)

Edit: this probably supersedes #6358

* (user-facing): environment variable configuration is no longer applied automatically when instantiating SDK components
(`LoggerProvider`, `BatchLogRecordProcessor`) directly from `@opentelemetry/sdk-logs`. Please migrate to using
`NodeSDK` from `@opentelemetry/sdk-node` to get automatic environment variable configuration.

Copy link
Member

Choose a reason for hiding this comment

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

deprecations are always weird to categorize. I usually just put a blip here to let people know what's coming. (feel free to ignore)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

@overbalance overbalance requested a review from a team February 11, 2026 17:58
Copy link
Contributor

@david-luna david-luna left a comment

Choose a reason for hiding this comment

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

looks good. A comment that you can skip if you want

@overbalance overbalance added this pull request to the merge queue Feb 16, 2026
Merged via the queue into open-telemetry:main with commit 34e7d91 Feb 16, 2026
27 checks passed
@overbalance overbalance deleted the overbalance/remove-sendbeacon branch February 16, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

browser Browser-specific additions or benefits

Projects

None yet

3 participants

Comments