Design Engineering
Quality & Polish

Production Observability

Systematic observability for frontend applications — what to observe, how to alert, and how to respond when things go wrong in production.

Observability is the practice of making a system's internal state inferable from its external outputs. For frontend applications, this means knowing whether the app is working for real users — not just whether the server responds. A well-observed application surfaces problems before users report them.

What to Observe

Observability covers four pillars. Each answers a different question about production health.

PillarQuestion it answersFrontend equivalent
LogsWhat happened?Console errors, API error responses, client-side exceptions
MetricsHow many? How often? How slow?Page load time, API latency, error rate, Core Web Vitals
TracesWhat caused it?Request waterfall, component render timing, API call chains
AlertsShould someone look right now?Threshold-based or anomaly-based notifications

Minimum viable frontend observability

What to observeWhyHow
Page load time (LCP)Largest Contentful Paint is the user's perception of speed. >2.5s is poor.web-vitals library or Vercel Speed Insights
Interaction readiness (INP)Interaction to Next Paint measures how responsive the page feels. >200ms is poor.web-vitals library
JavaScript errorsUnhandled exceptions that break functionalityGlobal window.onerror, error boundary capture, Sentry
API failure ratePercentage of API requests that return non-2xx responsesFetch wrapper with counter
API latency (p95/p99)Slowness that affects only a subset of usersFetch wrapper with timing
Client-side exceptionsErrors in React render, React error boundary catchesError boundary componentDidCatch or onError callback

Frontend Observability

Error tracking with Sentry

Sentry provides structured error capture with context, breadcrumbs, and source maps. Set it up in the root layout or provider.

import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  tracesSampleRate: 0.1, // 10% of transactions for performance monitoring
  environment: process.env.NODE_ENV,
  integrations: [Sentry.replayIntegration()],
});

What to capture in every error

The error tracking service is only useful if errors contain enough context to reproduce the issue.

ContextHow to capture
User identitySentry.setUser({ id: user.id, email: user.email })
Current routeSentry.setTag('route', pathname)
Browser and OSAutomatically captured by Sentry SDK
Console breadcrumbsAutomatically captured by Sentry SDK
Network requestsReplay integration captures fetch/XHR
Custom contextSentry.setContext('form', { projectName: 'foo' })

Performance monitoring with Web Vitals

Web Vitals reporting
import { onLCP, onINP, onCLS } from 'web-vitals';

function reportWebVitals() {
  onLCP((metric) => {
    // Send to analytics: metric.value is in milliseconds
    console.log('LCP:', metric.value);
  });
  onINP((metric) => {
    console.log('INP:', metric.value);
  });
  onCLS((metric) => {
    console.log('CLS:', metric.value);
  });
}

On Vercel, Speed Insights and Analytics handle this automatically. For other platforms, send these values to your analytics provider or custom endpoint.

Alerting Strategy

Not every problem needs a notification. Alert on symptoms that require human intervention.

Alert levelExampleResponse time
CriticalError rate > 5% in last 5 minutes, site is downImmediately (on-call)
WarningError rate > 1%, p95 latency > 3s, LCP exceeds thresholdWithin business hours
InformationalNew API endpoint timing baseline establishedLogged, no immediate action

Alert rules for frontend

AlertThresholdWhy
JavaScript error rate spike>2× baseline in 10 minutesA new deployment may have introduced a breaking change
API failure rate>5% over 5 minutesBackend may be degraded or rolling back
LCP degradation>3s for >5% of usersUser experience is measurably worse
INP degradation>300ms for >5% of usersInteractivity feels sluggish
404 pagesSpike in 404s (non-API)A link or redirect may be broken

Alert fatigue is dangerous. If an alert fires repeatedly without requiring action, adjust its threshold or silence it. Noisy alerts cause teams to ignore critical ones.

Incident Response

When an alert fires, the team should follow a predictable process. Define it before the first incident.

Frontend incident severity levels

SeverityDefinitionResponse
SEV-1Core user flow broken for all users. E.g., login page crashes, checkout fails.Immediate investigation. Rollback or hotfix.
SEV-2Major flow broken for a subset of users. E.g., dashboard fails for a specific browser.Fix within 24 hours or rollback.
SEV-3Minor functional or visual issue. E.g., broken image, wrong copy, layout shift.Fix in next sprint.
SEV-4Cosmetic, low-impact. E.g., slightly misaligned element on a specific screen size.Fix when convenient.

Runbook approach for common scenarios

ScenarioFirst actionSecond actionThird action
Error rate spikeCheck Sentry for new error or error grouping.Check deployment log — was a deploy pushed in the last 30 minutes?Rollback latest deployment if change is correlated.
LCP degradationCheck which pages are affected. Check if a new image or font was added.Check Core Web Vitals dashboard for LCP element breakdown.Optimise or revert the heavy resource.
API failure spikeCheck if the failure is across all endpoints or specific.Check backend monitoring or status page.If backend is degraded, show cached data or maintenance page.

Post-incident checklist

After resolving an incident, document:

  1. What was the trigger (alert or user report)?
  2. What was the root cause?
  3. How long did it take to detect, diagnose, and resolve?
  4. What change would prevent this from recurring?
  5. What change would make detection or diagnosis faster next time?

Analytics Integration

Observability and analytics serve different purposes but share infrastructure.

ObservabilityAnalytics
PurposeDetect and diagnose problemsUnderstand user behaviour
Time horizonReal-time to hoursDays to months
Data setErrors, performance, all sessionsPage views, events, sampled sessions
AudienceEngineering teamProduct team, stakeholders

Common analytics setup

// Page view tracking in layout
function AnalyticsProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  
  useEffect(() => {
    if (process.env.NODE_ENV === 'production') {
      trackPageView({ path: pathname, referrer: document.referrer });
    }
  }, [pathname]);

  return <>{children}</>;
}

// Custom event tracking
function trackEvent(name: string, properties?: Record<string, unknown>) {
  if (process.env.NODE_ENV !== 'production') return;
  // Send to analytics provider
}

On Vercel, you can use the built-in @vercel/analytics package which handles page views automatically. See Deployment for the CI/CD setup that deploys alongside monitoring.

The distinction between observability and analytics keeps your error data clean. Do not send every page view to Sentry, and do not send every error stack trace to your analytics provider.

On this page