Migrating 50M events/month off Sentry: what breaks

The four edge cases a high-volume Sentry migration is likely to hit — release desync, PII leaks, breadcrumb bloat, and silent alerts — and the dual-write plan that catches them.

·
migrationincident

At 50 million events per month, Sentry stops being a tool and becomes a line item that can start rivaling your infrastructure spend. Teams at that volume often talk themselves out of switching—too risky, too entangled, too much custom alerting to rebuild. The SDK side of the move really can be a DSN change. The parts that break are elsewhere: releases, PII handling, payload size, and alert semantics.

This guide is for anyone planning to move high event volume off a per-event platform. It covers the four things most likely to break during the cutover, and the dual-write safety net that makes that breakage survivable.

The Financial Gravity of 50M Events

Per-event pricing creates a perverse incentive: the better your product does, the more it costs to know how it's doing. At 50M events a month, that pressure stops being abstract.

The Sentry tax and the cost of visibility

The usual response to a growing bill is to quietly stop tracking things—sampling traces down to a few percent, inbound-filtering high-frequency "noise" errors, dropping breadcrumbs. Each of those is a small surrender of visibility made for budgetary reasons, and together they mean the most expensive incidents are often the ones with the least data. The shape of the comparison looks like this:

Monthly events:                  ~50,000,000
Per-event platform:              scales with volume; price your own
                                 volume on the vendor's published
                                 calculator, plus overage during incidents
Flat-rate (GlitchReplay):        $49/mo Pro or $149/mo Business
                                 (published plans), no per-event meter

Run your actual volume through Sentry's current pricing page before deciding—their tiers and on-demand rates change, and your mix of errors, transactions, and replays matters more than the headline event count. GlitchReplay's paid plans don't meter events; per-project rate limits exist to stop runaway loops, not to bill you. Session replay on Pro and Business has fair-use sampling at very high session counts, but error-attached replays are never sampled down. Plan details are on the pricing page.

Why SDK-compatibility is non-negotiable

At this scale, Sentry SDKs are usually threaded through a dozen services, frontends, and Workers. A migration that requires rewriting instrumentation everywhere is a non-starter. The only realistic path is a destination that speaks the same SDK and protocol, so the change can be, in theory, a DSN swap. "In theory" is doing a lot of work in that sentence—which is the whole point of this guide.

The Migration Strategy: The Dual-Write Bridge

You do not cut over 50M events/month in one move and hope. Build a dual-write bridge: for the migration window, every event goes to both Sentry and the new destination, so you can compare them side by side and keep the old system as a live safety net.

A beforeSend wrapper for dual ingestion

Rather than run two full SDKs, wrap the existing client so the same captured event is serialized once and POSTed to both ingest endpoints. Make the second write fire-and-forget so it can never delay or block the primary path:

Sentry.init({
  dsn: SENTRY_DSN,
  beforeSend(event) {
    // Mirror the already-built event to the new ingest.
    // Fire-and-forget: never block or fail the primary write.
    try {
      const envelope = JSON.stringify(event);
      fetch(GLITCHREPLAY_INGEST, {
        method: "POST",
        body: envelope,
        keepalive: true,        // survive page unload
      }).catch(() => {});       // swallow -- mirror must never break prod
    } catch {}
    return event;               // primary path is untouched
  },
});

Does double-reporting hurt Core Web Vitals?

The reasonable worry: does a second fetch in beforeSend add user-facing latency? It shouldn't—the call is asynchronous, fire-and-forget, and uses keepalive, so it doesn't sit on the critical path or block navigation. Still, measure INP and LCP before and during the dual-write window rather than assuming. The expected cost of the dual write is on the backend (briefly paying for two systems), not the frontend.

Failure #1: The Sourcemap Release Desync

The first thing likely to break is deminification: stack traces that resolve perfectly in Sentry arrive as minified gibberish on the new side.

Why "latest" is a dangerous release tag

In many Sentry setups, releases drift into a loose, almost global concept—tooling leans on a latest-style tag. Source-map resolution, though, is exact: the engine matches the release on the incoming event to the release the map was uploaded under. If your build uploads maps under a precise commit-hash release but some SDK configs still report the loose tag, the two don't match and the resolver has no map to apply.

The 404 for the artifact hash

The symptom in ingest logs typically looks like this:

[ingest] event release=web@latest
[sourcemap] lookup release=web@latest  -> 404 no artifacts
[sourcemap] uploaded releases: web@a1b9f3c, web@7d2e0aa, ...
[stacktrace] de-minify SKIPPED, serving raw frames

The fix is to make the SDK's release identical to the build's upload release—the exact commit hash—everywhere, with no exceptions. During a migration, every place a release is named must agree, byte for byte. Our source-maps documentation covers the upload-on-build flow; for one-off triage during the gap, the browser-based deminifier works on a single trace.

Failure #2: The PII Scrubbing Leak

The second failure mode is the scary one, because it's about data you never wanted stored at all.

The nested-field edge case

Many teams rely on a client-side beforeSend scrubber with a homegrown regex set, tuned over years to one vendor's exact serialization. When events start flowing through a second pipeline, the assumptions baked into those regexes—field ordering, nesting depth, how the SDK renders certain objects—may not all hold. A nested billing_address.phone_number that the client regex catches in one shape can slip through in another. Client-side scrubbing is brittle precisely because it is coupled to the exact shape of the data at one moment in one environment.

Why client-side scrubbing is never enough at scale

The real fix isn't a better regex. It's to stop treating the client as the last line of defense and move authoritative scrubbing to the ingest side, where a single set of rules applies to every event from every service, regardless of which SDK or environment produced it:

// Old: client-side, brittle, easy to bypass or desync.
beforeSend(event) {
  if (event.request?.data?.password) delete event.request.data.password;
  return event; // misses nested + new fields by construction
}

// New: server-side ingest rule, applied to 100% of events.
// rules:
//   - match: key ~= /(password|ssn|card|cvv|phone)/i  -> redact
//   - match: value ~= CREDIT_CARD | SSN | JWT          -> redact
//   - scope: ALL projects, ALL environments

This is a big enough topic that it has its own writeup—testing your error tracker for PII leaks—and a dedicated reference in our PII docs. The short version: client-side scrubbing is a bandwidth optimization, not a security control. You can audit your own payloads with the free PII scanner.

Failure #3: The Breadcrumb Overflow

The third failure comes from the volume of context you may have been carrying without noticing.

The memory pressure of too much context

If one reason for migrating is to stop sampling, you'll suddenly capture full breadcrumb trails on events you used to drop. Many services attach dozens of info-level breadcrumbs per event: every XHR, every console log, every state transition. At full fidelity, that turns modest error payloads into heavy ones, and long-session replays grow large.

Pruning the event stream

Look at where the bytes actually go. In a typical replay-enabled error event, the exception itself is small; breadcrumbs and serialized DOM snapshots dominate. Measure your own payloads before and after the cutover so you know which component is driving size.

The usual fix is to cap breadcrumbs to the last 20–30 genuinely useful ones, drop noisy info-level entries nobody reads, and lean on replay's incremental snapshotting instead of fat breadcrumb trails. Our always-on replay with a 3-day prune writeup covers how full-fidelity capture stays affordable to store; you can model the storage yourself with the replay storage calculator.

Failure #4: The Alerting Gap

The most painful failure produces no data corruption and no leak. It produces silence.

The regression-logic mismatch

It's easy to cut alerting over assuming "resolved" and "regressed" mean the same thing on both platforms. They may not. Setups that lean on "resolved in next release" semantics only re-alert when an issue reappears in a later release—and that logic depends on exactly the release tracking that Failure #1 can desync. Errors arriving tagged with a release the alerting engine considers already resolved may never notify anyone.

How Slack goes silent for P0

In that scenario, real production errors are captured perfectly and say nothing: the data is in the dashboard, but the routing to humans is broken. The dual-write bridge is what catches it—Sentry is still alerting in parallel, so someone notices Sentry paging while the new channel stays quiet. A hypothetical timeline of how this plays out:

T+0      Alerting cut over to new platform
T+10m    Release tags desync (Failure #1 still in flight)
T+15m    P0 errors arrive, tagged "already resolved" -> suppressed
T+?      Old platform (still dual-writing) pages on the same errors
         On-call notices: old channel loud, new channel silent
         Root cause: regression logic + release desync
         Fix release tags; confirm alerts fire on the new side

Lesson: never cut alerting over in a single step. Run alerts in parallel on both systems until you have proven, with a real fired alert, that the new one matches.

Stakeholder Communication: Transparency as a Feature

Migrations of this size affect more than engineers. People who depend on the dashboards need to trust the new numbers before you remove the old ones.

The shadow-mode dashboard

During the dual-write window, give stakeholders a side-by-side view: the same time range, the same filters, Sentry on the left and the new platform on the right. Watching the two charts track each other builds more confidence than any reassurance. When they diverge, find out why—sometimes it's a bug in the bridge, and sometimes it's the new side catching events the old side was sampling away.

Success metrics beyond "it's cheaper"

Define success up front: zero data loss versus the dual-write baseline, alert parity proven by matched fired alerts, source-map resolution rate at or above the old system, and only then cost. Leading with cost makes it look like you're trading reliability for savings.

What You Get on the Other Side

Once the four edge cases are handled, the benefit that changes day-to-day work is usually not the invoice—it's no longer having to decide what not to track. Without a per-event meter, there's no budgetary reason to drop high-frequency "noise" errors, and those are sometimes where a real bug has been hiding.

If you're weighing a similar move, our migration guide walks the happy path and the alternatives comparison covers the landscape.

The meta-lesson: "SDK-compatible" gets you most of the way in an afternoon, and the remainder—releases, PII, breadcrumbs, alert semantics—is where the real work lives. Plan a dual-write bridge, keep the old alerts running in parallel until the new ones prove themselves, and treat the cutover as a sequence, not a switch. GlitchReplay is built to be that destination: Sentry-compatible ingest, session replay on every plan, ingest-side PII scrubbing, and flat-rate pricing so growth doesn't tax your visibility.

Stop watching your error bill spike.

GlitchReplay is Sentry-SDK compatible, includes session replay and security signals, and never charges per event. Free to start, five minutes to first event.