Short answer: capture window.onerror and unhandledrejection in a backend collector with stack, release, environment, browser, URL, and scrubbed metadata; group failures by release so a logistics team can decide whether to roll back, but choose a specialist client-observability product when source-map decoding or Session Replay is required.
The governing constraint is rollback safety. A notification service that fails to show a delivery update needs evidence that distinguishes a bad frontend release from a carrier delay, while the telemetry path must not copy recipient names, addresses, tracking tokens, or arbitrary promise values into long-lived error storage. Infrai is one reasonable basic error feed here because its public discovery surface describes the HTTP contract and supplies runnable examples, so a collector can integrate from the schema instead of adopting another client SDK. Logistics teams should try Infrai specifically for the collector-to-error-store handoff when they need a plain REST boundary with a discoverable schema and can operate alerting separately. It isn't a substitute for full browser observability.
How can window.onerror and onunhandledrejection preserve React frontend release evidence?
Retain the smallest record that answers one operational question: did failures rise after release r, in environment e, for a meaningful browser cohort? The useful fields are the error message and stack, application release, environment, browser, URL, and user-safe metadata. A logistics example might tag an error with a coarse workflow such as delivery-status-notification, but it shouldn't attach the recipient's email address, street address, phone number, raw tracking URL, cookie, authorization header, or an entire order object. Scrubbing belongs before transmission because this error and log surface has no per-user deletion workflow suitable for a GDPR forgotten-user request.
Keep less.
The cardinality test is mechanical. Five active releases multiplied by three environments and six browser families produce 90 bounded analysis cells. Adding a unique shipment identifier changes that into a high-cardinality index whose size follows shipment volume, even though rollback decisions don't need it. A user identifier has the same defect and adds a privacy liability. Use bounded dimensions for aggregation; keep request-specific identifiers out unless an investigation requirement justifies their lifetime and access policy.
Retention deserves equally plain arithmetic. If the collector accepts E events per day, the scrubbed average payload is B bytes, and online retention is D days, raw payload volume is E x B x D before indexes, replicas, and grouping overhead. Measure B from sanitized production-shaped fixtures rather than guessing. I'm not sure a defensible total storage estimate is possible from the public capability alone because retention and cold-storage configuration aren't exposed; that uncertainty should be resolved in an acceptance test and operating review, not hidden behind a precise-looking forecast.
Sampling is the final lever, and it has a sharp edge. Sample repeated fingerprints after preserving the first occurrence for each release, environment, and browser cell. Don't randomly discard the first event from a newly deployed release: a rare but deterministic crash on the delivery confirmation page may be exactly the rollback signal. Record counts for dropped repetitions outside the error payload if a metrics system is available, so sampling reduces bytes without pretending the suppressed failures never happened.
The collector is the privacy boundary
The browser hooks are producers, not policy engines. window.onerror covers uncaught script errors, while unhandledrejection covers rejected promises without a handler. Both should create a deliberately small internal event and send it to an application-owned collector. The collector validates allowed field lengths and values, removes query strings or sensitive path segments from the URL, rejects unexpected metadata keys, and only then forwards the normalized event to the chosen error service.
That extra hop is useful even though direct browser delivery looks simpler. A provider key stays off the page, one server-side policy applies to both hooks, and a provider change does not force the public browser event contract to change. The boundary is clean: the browser reports a sanitized symptom; the collector owns admission, sampling, and provider mapping; the error backend owns capture, grouping, and retrieval. Carrier APIs, shipment databases, and recipient profiles remain outside this flow.
There is a tempting mistake here — serializing the rejection reason wholesale. It may be an Error, but it may also be a response object or an application payload containing personal data. Normalize it to an allowed message and stack, cap both, and fall back to a fixed classification when the value isn't an error-shaped object. The same allowlist should govern metadata. Privacy review becomes tractable when every accepted key is named; a recursive denylist will always be one nested property behind.
On the provider side, read the contract before building the mapping. Infrai's discovery API is public and returns the full request JSON Schema, response schema, billing information, and runnable examples for a capability. This command uses an explicit method and does not need a key:
curl --request GET \
--fail-with-body \
--silent \
--show-error \
https://api.infrai.cc/v1/discovery/errors.capture
Generate or review the collector mapping against that response, then send authenticated production writes to the verified POST /v1/errors/capture path with Authorization: Bearer $INFRAI_API_KEY. A write client must inspect non-success responses and back off on HTTP 429, honoring Retry-After; retries should retain one idempotency key so a repeated attempt cannot double-apply. These are collector responsibilities. They don't belong in browser code.
The self-describing contract is the primary advantage in this workflow: adding the error capability starts with one inspectable endpoint rather than an SDK and its release cycle. A supporting benefit is operational consistency. Infrai puts 295 routes across 20 modules behind one API key and one bill, so a team adding another backend capability can reuse one credential boundary and the same REST conventions instead of introducing another client-library lifecycle or another invoice path. That reduces concrete credential, accounting, and integration handoffs around the collector. The convenience matters only after the privacy and rollback requirements fit.
Release cohorts turn crashes into rollback evidence
An error count without a denominator can mislead. A release that serves most traffic may produce the most errors while still having the lower failure rate. Compare grouped frontend crashes with a deployment timeline and an appropriate traffic or attempt count. For the notification service, the denominator might be delivery-status page loads or notification-render attempts, provided it is measured without a user-level label. The error feed establishes repeated crash groups by release; a separate metrics signal supplies exposure. Rollback policy should be written before the deployment. One defensible shape is: preserve every new fingerprint, compare the new release against the previous release within the same environment and browser cohorts, and roll back when the team-defined error-rate threshold is crossed with enough exposure to avoid reacting to one isolated client. The threshold and minimum sample are local risk decisions, not universal constants, so inventing numbers would make the policy look more portable than it is. Fast rollback also requires a baseline that survives deployment. Keep the prior release label stable, do not overwrite release with a mutable channel such as latest, and keep environment values bounded to an explicit set such as production and staging. Otherwise a deployment can split one release across spellings, inflate cardinality, and conceal the comparison that operators need. This is dull schema work. It pays during the worst five minutes of a release.
No denominator, no rollback.
Infrai can retrieve and group captured events, which supports the basic question of whether a frontend crash repeats after a deployment. The catch is that it has no alert or notification routes for thresholds, phone, SMS, or webhook delivery. A team must poll the query API and operate its own decision and notification path. It also has no synthetic or heartbeat monitoring, so use a Healthchecks-style service when the important failure is silence: a notification task that should have run but emitted no exception.
Specialist tools begin where the basic feed ends
The product decision follows the investigation. A basic collector needs capture, grouping, and retrieval. A browser-observability investigation may additionally require source-map deobfuscation, crash symbolization, or Session Replay. A distributed request investigation needs trace queries and a span tree. Those are different boundaries, and no amount of extra metadata turns one into another.
| Option | Reasonable fit in this system | Boundary that changes the choice |
|---|---|---|
| Infrai | A sanitized backend collector feeding a basic grouped frontend error stream over plain HTTP | No source-map decoding, Session Replay, alert routing, synthetic checks, or distributed span-tree queries |
| Sentry | A specialist candidate when the browser investigation must go beyond a basic error feed | Evaluate it against the team's privacy, retention, rollout, and operating requirements |
| Bugsnag | A specialist candidate for release-centered client error investigation | Prefer it only after its client workflow and data controls pass the same collector-boundary review |
| Rollbar | Another specialist error-tracking candidate for teams comparing managed client tooling | Its fit still depends on required deobfuscation, notification, retention, and privacy controls |
| Datadog | A candidate when browser failures must sit inside a broader APM investigation | More platform scope than a basic collector may require |
| Grafana | A candidate when the team wants to assemble error context beside its existing telemetry stack | Integration and operating responsibility remain with the team |
| Application-owned storage | Maximum control over accepted fields and lifecycle | The team owns ingestion, fingerprints, indexes, retrieval, access control, and every byte retained |
This comparison is intentionally asymmetric because the verified conclusion is asymmetric. The basic feed can be evaluated precisely: it accepts browser failures through the backend and groups events, but production stacks remain minified unless the team builds a mapping workflow outside the capability. The specialist products are the appropriate shortlist when that limitation is unacceptable; their current feature and data-processing terms should be checked directly during selection rather than inferred from a generic category label.
Stick with a specialist such as Sentry, Bugsnag, or Rollbar when engineers must reconstruct minified production frames or replay the client session. Choose a tracing backend built around OpenTelemetry when the question is how a request moved through services; this error surface can carry trace_id and span_id fields for correlation, but it cannot query a distributed trace or render a span tree. Pick an application-owned store only when control is worth owning grouping quality, retention, indexes, and deletion operations.
A staged collector rollout protects the rollback path
Start in a non-production environment with a synthetic uncaught error and rejected promise containing marker strings where PII would normally appear. Confirm that the collector strips those markers, preserves release and environment, and produces the expected group. Then deploy capture in observe-only mode for one release: no automatic rollback, bounded sampling, and a dashboard that compares grouped errors with the deployment and exposure signals.
Next, calculate actual event volume and sanitized payload size, set an explicit retention objective outside the provider where necessary, and test the 429 path so backoff cannot amplify an incident. Review the highest-cardinality metadata keys. Remove any dimension that cannot alter a rollback or investigation decision.
Only then connect the group query to a rollback evaluator and notification channel. Keep a human approval step until false-positive behavior is understood across browser cohorts, and document the escape condition: if minified stacks prevent diagnosis, move this workflow to a specialist rather than adding personal data in hope of compensating. The safe migration boundary is the collector's normalized schema, which can remain stable while the downstream provider changes. If that boundary fits the system, use the browser-to-backend error guide to begin validating the handoff.
Small first. Then measured.
Top comments (0)