PATTERN Cited by 1 source
Bundle-size budget for browser telemetry¶
Problem¶
Observability in a browser context has a cost server-side observability never has: every byte of the telemetry SDK adds to page weight and competes with customer-facing JavaScript for the critical render path. Default OpenTelemetry JS browser distributions bundle more auto-instrumentation + exporters + SDK machinery than any given site actually uses; off-the-shelf installation can easily add hundreds of kilobytes to the initial page payload.
Three knock-on effects:
- Page weight → slower first contentful paint, worse Core Web Vitals (LCP, FCP).
- More JavaScript → longer parse/compile/execute on low-end devices → worse INP.
- Observability tooling itself regresses the metric it's trying to measure (page performance) — a self-defeating shape.
Solution¶
Treat browser-side observability as a byte-budget engineering problem, not a plug-and-play install:
1. Cherry-pick upstream packages¶
Don't install @opentelemetry/sdk-node-auto-instrumentations-
style meta packages. Install only the specific tracer,
specific exporter, and specific auto-instrumentations you
actually need — see
concepts/cherry-picked-instrumentation-payload.
2. Split critical vs lazy payload¶
Packages that must be on the critical page-load path (e.g. tracing page load itself, generating propagation context for API requests) go in the initial bundle; everything else is loaded asynchronously after the critical render path completes.
3. Low-priority transport¶
Use navigator.sendBeacon() (concepts/send-beacon-telemetry-transport)
instead of fetch() / XMLHttpRequest for telemetry export
so network requests sit at the lowest priority tier below
all customer-facing requests.
4. Baseline + budget¶
Set an explicit bundle-size budget for the telemetry payload and check it in CI. If a new OTel dependency exceeds the budget, it gets broken into critical + lazy halves before merging.
Zalando numbers¶
Source: sources/2024-07-28-zalando-opentelemetry-for-javascript-observability-at-zalando:
- First off-the-shelf telemetry package trialled: ~400 KB added to page size — "we tried to integrate some telemetry packages only to realise they added about 400 KBs to the page size!"
- Final cherry-picked Zalando SDK: ~30 KB added. >13× reduction.
- Non-critical packages deferred to after critical load path.
- Network transport via
sendBeacon()at lowest priority.
When to use this pattern¶
- Customer-facing web application where page-load performance matters (e-commerce checkout flow, news, SaaS login).
- OTel JS browser integration where you'd otherwise take the
default
@opentelemetry/sdk-trace-web+ auto-instrumentation bundle. - Fleet of web apps — define the budget once, enforce fleet-wide via the platform team's SDK (patterns/observability-sdk-as-zalando-specific-wrapper).
When not to use this pattern¶
- Internal-only tools with captive audiences and no page-load performance budget — don't over-engineer a 300 KB dashboard.
- Native mobile or Electron apps — no browser critical-render- path constraint (though code-size matters for install-size reasons).
Failure modes¶
- Budget without enforcement — written-down targets that no CI check validates drift upward over releases.
- Lazy load breaks page-load tracing — if the tracer for the initial navigation span is deferred it misses the very thing it's supposed to instrument. Page-load tracer must stay in the critical bundle.
- SendBeacon loses data on aggressive unload — low
priority means the browser may cancel queued beacons at
unload; real-world data loss rate is small but nonzero.
Don't use
sendBeaconfor audit-grade data. - Over-trimming breaks auto-instrumentation surface — cherry-picking too aggressively can leave holes where key framework events aren't instrumented. The SDK team has to own the completeness audit.
Sibling patterns¶
- patterns/observability-sdk-as-zalando-specific-wrapper — where the cherry-picked packages live; the wrapper is how the budget is enforced across a fleet.
- patterns/edge-proxy-as-telemetry-collector-ingress — the transport-layer pattern this payload-layer pattern composes with.
Alternative evaluated¶
Grafana Faro — Zalando called this out as "a great package to check out if you are starting from scratch". Faro is a browser-SDK purpose-built for frontend observability with bundle-size consciousness as a design primitive, so if you're greenfield and don't already have an OTel-based SDK family, Faro may sidestep the cherry-picking work.
Seen in¶
- sources/2024-07-28-zalando-opentelemetry-for-javascript-observability-at-zalando — canonical Zalando disclosure of the 400 KB → 30 KB cherry-pick reduction + lazy-load + sendBeacon transport pattern.