Skip to content
Published on

Frontend Monitoring & Error Tracking 2025 — Sentry, Datadog RUM, PostHog, LogRocket, Session Replay, Source Maps, AI Anomaly Detection (S6 E8)

Authors

Prologue — "works on my machine"

Sunday 10pm after a deploy. Slack pings: "checkout is broken." Local is fine, staging is fine, only production fails. Which browser? Which OS? Which A/B variant? No logs. No idea.

In 2025, deploying without monitoring is driving blindfolded. Backends have had APM + logs + metrics for 20 years; frontends only got true RUM in the last five.

Four 2025 shifts:

  1. RUM went mass-market — Sentry, Datadog, Vercel Speed Insights, PostHog offer affordable RUM. Even startups see more detail than CrUX gives.
  2. Session Replay ethics crystallized — 2024 password/credit-card-in-replay scandals forced industry guidelines for when, what, how much to record.
  3. AI-powered anomaly detection — beyond threshold alerts: LLMs do grouping, root-cause, alert-noise reduction.
  4. Privacy regulation bite — GDPR, CCPA, Korean PIPA directly regulate frontend logging scope and retention.

This post maps every layer.


1. What to monitor — four axes

Backend observability is Logs + Metrics + Traces. Frontend adds users → four axes.

AxisQuestionTool
ErrorsWhat broke?Sentry, Bugsnag, Rollbar
Performance (RUM)How slow?Datadog RUM, Vercel Speed Insights, SpeedCurve
User BehaviorWhat are users doing?PostHog, Mixpanel, Amplitude, Heap
Session ReplayHow did they experience it?LogRocket, Clarity, PostHog, FullStory

No single tool wins. 2025 startup default: Sentry (errors) + PostHog (behavior + replay) + Vercel Speed Insights (RUM).

Connect them via consistent distinctId, user_id, release across all three — otherwise the noise wins.


2. Sentry — the de facto error tracker

Install for Next.js:

npx @sentry/wizard@latest -i nextjs

Minimal init:

import * as Sentry from '@sentry/nextjs'
Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NEXT_PUBLIC_ENV,
  release: process.env.NEXT_PUBLIC_BUILD_ID,
  tracesSampleRate: 0.1,
  replaysSessionSampleRate: 0.05,
  replaysOnErrorSampleRate: 1.0,
  integrations: [Sentry.replayIntegration({ maskAllText: true, blockAllMedia: true })],
})

User + context + breadcrumbs:

Sentry.setUser({ id: user.id, segment: user.plan })
Sentry.setTag('feature_flag_checkout_v2', 'enabled')
Sentry.addBreadcrumb({ category: 'purchase', message: 'coupon applied', level: 'info' })

Release tracking — link commits to errors:

sentry-cli releases new $VERSION
sentry-cli releases set-commits $VERSION --auto
sentry-cli releases finalize $VERSION

3. Source Maps — the decoder

Production bundles are mangled. Source maps (.map files) translate minified frames back to original lines.

Don't publish .map to CDN

Your source code becomes public. Instead:

  1. Upload .map to Sentry only.
  2. Remove or obscure sourceMappingURL in bundles.
  3. Sentry resolves stacks server-side.
sentry-cli sourcemaps upload \
  --release $VERSION \
  --url-prefix '~/_next' \
  .next/static

Next.js: withSentryConfig({ widenClientFileUpload: true, hideSourceMaps: true }).

Before: TypeError: n is undefined at t.default (main.a3f2.js:1:4829) After: TypeError: user is undefined at CheckoutForm.tsx:42:16


4. Datadog RUM — enterprise full-stack observability

import { datadogRum } from '@datadog/browser-rum'
datadogRum.init({
  applicationId: process.env.NEXT_PUBLIC_DD_APP_ID,
  clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN,
  site: 'datadoghq.com',
  service: 'web-app',
  env: 'prod',
  version: process.env.NEXT_PUBLIC_BUILD_ID,
  sessionSampleRate: 100,
  sessionReplaySampleRate: 20,
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  defaultPrivacyLevel: 'mask-user-input',
})
datadogRum.startSessionReplayRecording()

Strength: trace → session link. Backend trace IDs auto-injected as request headers, so one timeline shows "API X served this session."

Caveat: Datadog RUM pricing is enterprise. Drop sessionSampleRate to 10–30% at scale.


5. PostHog — analytics + replay + flags + experiments

Open-source Amplitude + LogRocket + LaunchDarkly.

import posthog from 'posthog-js'
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
  api_host: 'https://app.posthog.com',
  session_recording: { maskAllInputs: true, maskTextSelector: '[data-private]' },
  autocapture: true,
})
posthog.capture('checkout_started', { cart_total: cart.total, items: cart.items.length })
posthog.identify(user.id, { email: user.email, plan: user.plan })
if (posthog.isFeatureEnabled('checkout-v2')) return <CheckoutV2 />

2025 additions: SQL Insights (ClickHouse), LLM Observability (auto OpenAI/Anthropic instrumentation), Data Warehouse sync.


6. Session replay tools

  • LogRocket — JS + network + Redux + console, premium. 10k sessions free, steep after.
  • Microsoft Clarity — free unlimited, heatmaps, rage/dead clicks. You share data with Microsoft.
  • FullStory — enterprise, best privacy controls.

Session replay value: reproduce impossible bugs, UX insight (rage clicks, abandons), funnel completion with the "why."


7. Session replay ethics — privacy by design

2024 scandals: passwords and credit-card numbers captured, GDPR fines.

Three defensive layers

1. Safe defaults

Sentry.replayIntegration({ maskAllText: true, maskAllInputs: true, blockAllMedia: true })

2. Markup-level controls

<input type="password" data-private />
<div data-private>{creditCard}</div>
<span class="ph-no-capture">SSN</span>

3. Client-side sanitize before send

posthog.capture('form_submit', {
  email: user.email.replace(/(.{2}).+(@.+)/, '$1***$2'),
})

GDPR Art. 6/7

  • Explicit consent — "session recording" as separate item in cookie banner.
  • Purpose limitation — UX only.
  • Retention — 30–90 days.
  • DSAR — users can delete their recordings.

8. Frontend error types

JS runtime

TypeError: Cannot read property 'x' of undefined. Fix: TS strict + null guards.

Unhandled promise rejection

window.addEventListener('unhandledrejection', (e) => Sentry.captureException(e.reason))

ChunkLoadError — the deploy classic

User had tab open during deploy; old chunk gone from CDN.

window.addEventListener('error', (e) => {
  if (e.message.includes('ChunkLoadError') || e.message.includes('Loading chunk')) {
    window.location.reload()
  }
})

Or long-term cache with hash invalidation.

Hydration mismatch

SSR ≠ client render (Date, Math.random, localStorage).

const [now, setNow] = useState('')
useEffect(() => { setNow(new Date().toLocaleString()) }, [])
return <div suppressHydrationWarning>{now}</div>

CORS / CSP errors

Start with CSP Report-Only → tighten gradually. Use nonces.

3rd-party script errors

"Script error." with no stack = cross-origin block. Fix: <script crossorigin="anonymous"> + CORS headers + Sentry.ignoreErrors.


9. Core Web Vitals — the RUM loop

web-vitals library

import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals'
function send(metric) {
  navigator.sendBeacon('/api/vitals', JSON.stringify({
    name: metric.name, value: metric.value, id: metric.id,
    rating: metric.rating, delta: metric.delta, navigationType: metric.navigationType,
  }))
}
onCLS(send); onINP(send); onLCP(send)

Vercel Speed Insights

On Vercel: one line, <SpeedInsights />. CrUX-style RUM, free tier.

Dashboard discipline

  • Percentiles — p75/p90/p95, not average.
  • Segments — device, route, version, region.
  • Regression detection — pre/post-deploy diff.

10. Alert fatigue — the real enemy

50 Slack alerts/day → everyone mutes → the important ones die in the noise.

SLO-based alerting (Google SRE)

Alert on "burn rate," not "an error happened":

slo:
  name: checkout-success-rate
  target: 99.9%
  window: 30d
  alert:
    - burn_rate: 14.4  # 2% budget in 1 hour
      duration: 5m
      severity: critical
    - burn_rate: 6     # 5% budget in 6 hours
      duration: 30m
      severity: warning

Grouping

Sentry auto-groups by stack pattern. Alert on new issue types or 3× traffic spikes.

Priority tiers

  1. Critical — page down, checkout broken. Paging.
  2. Warning — partial issue, perf regression. Business hours.
  3. Info — trend watching, dashboard only.

11. AI anomaly detection + root cause

Static thresholds miss seasonality. 2024–2025 Datadog Watchdog, Sentry Insights, PostHog AI, Dynatrace Davis ship LLM/time-series anomaly features.

What they do:

  1. Detect change-points (3σ vs same time last week).
  2. Correlate error spikes with deploys, flags, external deps (RCA suggestions).
  3. LLM summarizes stacks + logs in plain language: "this function of this flow failed."
  4. Business-impact ranking (traffic × checkout page).

Caveat: correlation ≠ causation. AI narrows the search; humans decide.


12. User feedback loops

Numbers answer "how many," feedback answers "why."

  • NPS/CSAT — Delighted, Wootric, Typeform.
  • In-app feedback — Canny, UserVoice, Feedback Fish.
  • Session + comment — LogRocket/PostHog "share recording."
  • Sentry User Feedback — prompt users on error:
Sentry.showReportDialog({ user: { email: user.email, name: user.name } })

13. Checklist + anti-patterns

14-item checklist

  1. Sentry (or equivalent) collecting errors.
  2. Source maps uploaded only to Sentry, not public.
  3. Release tracking — commit → build → error chain.
  4. User context injected.
  5. RUM deployed (Vercel Speed Insights / Datadog / PostHog).
  6. CWV collected + pre/post-deploy diff.
  7. Session replay with mask defaults + data-private.
  8. ChunkLoadError auto-retry.
  9. Hydration mismatch monitored.
  10. unhandledrejection global handler.
  11. SLO-based burn-rate alerting.
  12. 3-tier alert priority.
  13. GDPR/PIPA compliance (consent, retention, DSAR).
  14. Dashboard segmented by device/route/version.

Top 10 monitoring anti-patterns

  1. console.error without server-side collection.
  2. Sending PII to Sentry un-masked.
  3. Publishing .map files to CDN.
  4. Every error as critical.
  5. Dev/staging/prod mixed (no environment tag).
  6. 100% sample rate (cost explosion).
  7. Session replay without data-private.
  8. No release tracking ("when did this start?" → silence).
  9. Ignoring hydration mismatches.
  10. Quant data and feedback stored separately.

Next episode

Season 6 Episode 9: Frontend Security 2025 — XSS, CSRF, CSP v3, Trusted Types, JWT, OAuth + PKCE, Passkey, supply chain, SRI.

"Monitoring is a second product shipping after deploy. Measure errors, performance, behavior, emotion — but never at the cost of users' privacy."

— End of Frontend Monitoring & Error Tracking.