arch-atlas
SaaS Atlas·Pillar 10 / 12

Observability

OpenTelemetry · Sentry · PostHog · Grafana / SigNoz

Observability is not 'logs in a search box'. It's the answer to 'what's broken, why, and who saw it?' in under five minutes. OpenTelemetry is the instrumentation layer the entire industry agreed on; pick storage vendors that consume OTLP (Sentry, Grafana, SigNoz). Combine errors (Sentry) + product (PostHog) + infra (Grafana) → three tabs that cover 95% of incident triage.

7Nodes5Vendors0Decisions4Checklist1Flows

Primary stack

The default picks this pillar assumes

  • @vercel/otel
  • Sentry
  • PostHog

Alternates worth knowing

Swap in when scale, cost or constraints change

  • PostHog Error Tracking
  • Mixpanel
01
InstrumentationInstrumentation standard

OpenTelemetry

OpenTelemetry SDK collects spans (traces), metrics, and logs from your app — agnostic of backend. Configure once, pipe to any OTLP receiver (Sentry, Grafana Tempo, SigNoz). No more swapping SDKs to swap vendors.

How it flows

step by step
  1. 01

    Install @vercel/otel (Vercel) or @opentelemetry/sdk-node (self-hosted).

    step
  2. 02

    Register instrumentations: http, postgres, fetch, nextjs.

    step
  3. 03

    Add custom spans around business work: tracer.startActiveSpan('createSubscription', ...).

    step
  4. 04

    Spans flow via OTLP to your storage backend.

    step

Cases & edge cases

watch for these

Don't over-span — every span is cost. Tag spans, don't proliferate them.

Trace context propagation: ensure outgoing fetch carries traceparent header so the next service joins the trace.

Sampling: head-based 10% in prod is the default; bump to 100% on errors.

Vendors & tools

what implements this

@vercel/otel

primary

Vercel's pre-wired OTel for Next.js.

Where it lives

code references
References
  • instrumentation.ts // Next.js OTel registration
  • lib/telemetry/tracer.ts
02
Errors & AlertsExceptions · Performance

Sentry (Errors)

Sentry captures unhandled exceptions + slow transactions, groups them by stack trace, alerts you on new occurrences. Source maps mean stack traces show your TypeScript, not minified output.

How it flows

step by step
  1. 01

    @sentry/nextjs auto-instruments error.tsx, Server Components, route handlers.

    step
  2. 02

    Source maps uploaded on every Vercel build (sentry-cli releases via build hook).

    step
  3. 03

    Errors group by stack signature; new error type → Slack/PagerDuty alert.

    step
  4. 04

    Issue view links to the trace, the related session replay (PostHog integration), and the release.

    step

Cases & edge cases

watch for these

Filter expected errors (NotFoundError, ValidationError) at the SDK before they hit your quota.

Per-release issue tracking → 'this error started in v2.34.1' is the question you'll ask most.

User context (sentry.setUser) makes debugging humane — but redact PII (replace email with user_id).

Vendors & tools

what implements this

Sentry

primarysite

Errors + perf monitoring; the boring correct answer.

PostHog Error Tracking

alternate

Free if already on PostHog; less mature than Sentry but catching up.

Where it lives

code references
References
  • sentry.client.config.ts
  • sentry.server.config.ts
03
Metrics & ProductAnalytics · Replay · Flags

PostHog (Product)

PostHog is the all-in-one product analytics platform: events, funnels, retention, session replay, feature flags, A/B tests, surveys. Self-hostable or cloud. Most generous free tier in the category.

How it flows

step by step
  1. 01

    posthog.identify(userId, { email, plan }) on sign-in.

    step
  2. 02

    posthog.capture('event_name', { props }) for every meaningful action.

    step
  3. 03

    Session replay records DOM (with masking for sensitive fields).

    step
  4. 04

    Feature flags: posthog.isFeatureEnabled('new-billing-ui').

    step
  5. 05

    Funnels + retention analyzed in the dashboard.

    step

Cases & edge cases

watch for these

Event naming convention: object_action ('subscription_created'), past-tense. Document in events.ts.

Mask all input fields by default in session replay; explicitly unmask only what's safe.

PostHog feature flags evaluate client-side; for server-side, use local evaluation with a periodic poll.

Vendors & tools

what implements this

PostHog

primarysite

Analytics + replay + flags + A/B + surveys.

pricingFree 1M events/mo + 5k recordings/mo

Mixpanel

alternate

Excellent funnels; doesn't bundle replay/flags.

Where it lives

code references
References
  • lib/posthog/client.ts
  • lib/posthog/events.ts // typed event catalog
04
Logs & TracesJSON · Correlation IDs

Structured Logs

Every log line is JSON with a stable shape: { level, time, msg, req_id, user_id, org_id, ...context }. Searchable in Better Stack / Grafana Loki / Datadog. Correlation ID links a user-visible request to all its server-side hops.

How it flows

step by step
  1. 01

    logger.info({ msg, ...context }) — pino in Node, structured logger in edge.

    step
  2. 02

    Request middleware generates a req_id, attaches to async context (cls-hooked / async_hooks).

    step
  3. 03

    Every subsequent log inherits req_id automatically.

    step
  4. 04

    Logs shipped via OTLP or Vercel log drains to the storage backend.

    step

Cases & edge cases

watch for these

Don't log secrets — even hashed. Even debug logs. Lint rules help.

Don't log on the success path — log on decision points + errors. Otherwise the bill eats you.

Log volume: keep p99 line size under 4KB or your collector chokes.

Where it lives

code references
References
  • lib/log/logger.ts
  • middleware.ts // assigns req_id
05
Metrics & ProductVital signs at a glance

Dashboards

Three dashboards everyone should have: 'Vitals' (p99 latency, error rate, request rate), 'Business' (MRR, signups, churn), 'Health' (DB connections, queue depth, cache hit). One screen each. Grafana or PostHog dashboards.

How it flows

step by step
  1. 01

    Define core SLO/SLI dashboards in code (Terraform Grafana provider or PostHog API).

    step
  2. 02

    Vitals: requests/sec, p50/p99 latency, error %, with thresholds.

    step
  3. 03

    Business: MRR, signup funnel, activation rate, churn, NPS.

    step
  4. 04

    Health: DB conn pool, Inngest queue depth, Stripe webhook delivery rate.

    step

Cases & edge cases

watch for these

Dashboards rot. Quarterly review: still useful? still accurate?

Link from runbook → dashboard → trace → log. Investigators should never search.

On-call dashboard URL goes in the on-call handoff doc.

06
Errors & AlertsPages that matter

Alerts & On-Call

Alerts have two tiers: 'page someone now' (real customer impact) and 'queue for working hours'. Better Stack / PagerDuty manage rotations + escalation. The rule: every page comes with a runbook link.

How it flows

step by step
  1. 01

    SLO breach (e.g. error rate >1% for 5 min) → PagerDuty fires → on-call gets a call.

    step
  2. 02

    On-call opens the runbook (linked from the page).

    step
  3. 03

    Triage: dashboard → trace → logs → fix or escalate.

    step
  4. 04

    Post-incident: 5 Whys doc within 48h, action items tracked.

    step

Cases & edge cases

watch for these

Alert fatigue is the #1 killer of observability programs. Tune until each page is real.

Auto-resolve on metric recovery — don't make people manually clear pages.

Quarterly on-call experience review: which pages were the worst? Are runbooks current?

Checklist

ship readiness
  • Tiered alerts (page vs. ticket)

    must
  • Runbook link on every alert

    must
  • Auto-resolve on recovery

    should
  • Quarterly on-call review

    should
07
Logs & TracesEnd-to-end request paths

Distributed Tracing

A trace is a tree of spans: edge → middleware → tRPC → DB → Stripe → webhook. Tracing reveals where time goes — 'why is this endpoint slow' is answered without log mining.

How it flows

step by step
  1. 01

    Edge middleware starts the trace; every downstream op is a child span.

    step
  2. 02

    OTel context propagation flows through fetch + DB driver + Inngest.

    step
  3. 03

    Sentry / Grafana Tempo / SigNoz visualize the waterfall.

    step
  4. 04

    Tail-based sampling: keep 100% of slow / error traces, 5% of healthy ones.

    step

Cases & edge cases

watch for these

Spans without attributes are noise — always tag with org_id, op_name, status.

External calls (Stripe, FCM) need spans too — outbound latency is the silent killer.

Pull traces from the actual customer report time (with req_id) — not just generic 'find a slow one'.

Annotate0 strokes

Apple Pencil draws with pressure. Fingers still scroll. Saved per pillar.