Replace Sentry with PostHog error tracking and session replay

Objective

  • Replace the current Sentry-based observability setup with PostHog as the primary tool for error tracking and session replay, with parity to today’s Sentry behavior.
  • Stand up the PostHog account and project configuration so engineering can rely on one platform before broader product analytics work (e.g. report-page funnels).
  • Deliver a first phase that is a one-for-one swap of Sentry — not a full redesign of how the team observes the product.

Background

  • Attik uses Sentry across web, API, and mobile today; there is no PostHog in any repo yet.
  • The team wants PostHog introduced as the replacement path for errors and replay, then expanded later for funnels and event analytics.
  • Current Sentry capabilities to match or consciously defer:
  • Exception capture (global handlers, route errors, captureException helpers)
  • Session replay on the Next.js client (sampled session + on-error replay)
  • Distributed tracing via sentry-trace / baggage between frontend and backend
  • Structured logs (Sentry.logger / sentryLogger / frontendLogger) tied to traces
  • User and company context on scope (staff tools, portal pay flows, mobile inspector session)
  • Release and source map linkage for readable stack traces in production
  • This work is distinct from report-page product analytics: that is separate instrumentation once PostHog is a baseline capability.

Scope

Frontend (attik-frontend)

  • Sentry is wired through @sentry/nextjs: client init in src/instrumentation-client.ts (replay + browser tracing, Doppler-driven sample rates), server in sentry.server.config.ts, edge in sentry.edge.config.ts, and withSentryConfig in next.config.js for build-time source map upload.
  • Shared filtering and env: src/util/sentry/sharedConfig.ts (sentryBeforeSend, sentryEnvironment, sentryRelease), trace sampling in src/util/sentry/tracesSamplerConfig.ts.
  • Identity/context: src/components/sentry/SentryAttikScope.tsx (staff session — user, company_id, attik_user_id, surface); portal pay sets tags in src/app/client/job/[slug]/pay-beta/PaymentBetaClient.tsx.
  • Trace propagation to backend: src/util/functions/sentry/applySentryTraceHeaders.ts used from callApiServerRoute.ts, useMultiServer.ts, and some API routes (e.g. src/app/api/data-exports/ai-generate-stream/route.ts).
  • Structured logging wrappers: src/util/functions/sentry/sentryLoggerCore.ts, frontendLogger.ts, domain helpers (authLog.ts, paymentLog.ts, schedulingLog.ts, fetchLog.ts, observability.ts).
  • Global error surface: src/app/global-error.tsx; tools shell mounts scope via src/app/tools/provider.tsx.
  • Decision needed: PostHog SDK placement (Next.js app router patterns), env vars (replacing NEXT_PUBLIC_SENTRY_DSN, replay rate vars, etc.), and whether to keep parallel Sentry during cutover or remove in one pass.
  • Decision needed: Source maps / release tracking equivalent to current Sentry + Vercel build upload (docs/SENTRY_SOURCEMAPS_SETUP.md, disabled workflows under .github/workflows/sentry-sourcemaps-*.yml.disabled).

Backend (attik-backend)

  • Early init in src/instrumentation.ts: Express, HTTP, Mongo, Vercel AI, profiling (@sentry/profiling-node), parent-based trace sampling, beforeSend from src/util/functions/sentry/sharedConfig.ts.
  • Request middleware in src/app.ts reads sentry-trace, tags spans, exposes trace ids on res.locals; CORS allows sentry-trace and baggage.
  • Auth scope: src/util/functions/sentry/requestScope.ts (applyAuthenticatedSentryScope, portal client-token identity, scheduler contact header); used from src/routes/login.ts with sentryExpressTransactionNamingMiddleware.
  • Error path: src/util/functions/errorHandling/requestError.ts captures exceptions with scope; helpers in src/util/functions/sentry/errorCapture.ts, sentryLogger.ts, domain logs (paymentRouteLog.ts, aiSentryWrapper.ts, etc.).
  • CI release upload: .github/workflows/sentry-release-deploy.yml, .github/actions/sentry-upload/action.yml.
  • Decision needed: PostHog server-side error capture vs keeping trace header contract with the frontend during transition.
  • Decision needed: Fate of structured sentryLogger call sites across routes and workers (migrate to PostHog logging/events vs thin adapter).

Mobile (attik-mobile)

  • Init in lib/sentry.ts (@sentry/react-native, routing integration, Sentry.wrap on app/_layout.tsx); user/tags in contexts/AuthContext.tsx; trace headers on lib/api.ts and lib/apiClient.ts; Expo plugin in app.config.js, Metro via metro.config.js.
  • Decision needed: Whether mobile is in scope for phase 1 or a follow-up after web + API parity.

Config / ops

  • PostHog project setup, environments (dev/staging/prod), sampling for replay, and alert/routing — decision needed who owns dashboards and on-call handoff from Sentry.
  • Remove or repoint Sentry DSNs, GitHub Actions, and Doppler secrets once cutover is validated — decision needed rollback plan if parity gaps appear.

Out of scope for this ticket (unless explicitly expanded)

  • Report-page funnel events and tutorial/repair-list instrumentation (separate product-analytics work once PostHog is live).
  • Re-architecting all domain log schemas — only what’s needed for Sentry parity in phase 1.

References

  • PostHog docs
  • PostHog error tracking
  • PostHog session replay
  • Frontend Sentry entry: attik-frontend/src/instrumentation-client.ts, attik-frontend/src/components/sentry/SentryAttikScope.tsx
  • Backend Sentry entry: attik-backend/src/instrumentation.ts, attik-backend/src/util/functions/sentry/requestScope.ts
  • Mobile Sentry entry: attik-mobile/lib/sentry.ts

Please authenticate to join the conversation.

Upvoters
Status

In Progress

Board
🏠

Main App

Date

8 days ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.