Agent Skills: Sentry Architecture Variants

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/sentry-architecture-variants

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/sentry-pack/skills/sentry-architecture-variants

Skill Files

Browse the full folder contents for sentry-architecture-variants.

Download Skill

Loading file tree…

plugins/saas-packs/sentry-pack/skills/sentry-architecture-variants/SKILL.md

Skill Metadata

Name
sentry-architecture-variants
Description
|

Sentry Architecture Variants

Overview

Choose the right Sentry SDK, project layout, and tracing strategy for each application architecture. Every pattern below uses Sentry SDK v8 APIs — @sentry/node, @sentry/browser, @sentry/react, @sentry/react-native, @sentry/aws-serverless, and @sentry/google-cloud-serverless. The goal is one coherent trace from the user's device through every backend hop, regardless of how many runtimes or deployment targets sit in between.

Deep-dive references for each pattern: Monolith | Microservices | Serverless | Event-driven | Frontend SPA | Mobile | Hybrid | Errors

Prerequisites

  • Node.js 18+ (or target platform runtime)
  • Sentry organization with at least one project created at sentry.io
  • SENTRY_DSN available as an environment variable (one per Sentry project)
  • Application architecture documented — service inventory, deployment targets, team ownership mapped
  • For distributed tracing: all inter-service transports identified (HTTP, gRPC, Kafka, SQS)

Instructions

Step 1 — Identify Your Architecture and Select SDK Packages

Map every runtime in your system to the correct Sentry SDK package and project layout.

| Architecture | SDK Package | Sentry Projects | Key Integration | |---|---|---|---| | Monolith | @sentry/node | 1 project, env tags | Module tags + ownership rules | | Microservices | @sentry/node (per service) | 1 project per service | Distributed tracing via headers | | Serverless (Lambda) | @sentry/aws-serverless | 1 per function group | Sentry.wrapHandler() + auto-flush | | Serverless (GCP) | @sentry/google-cloud-serverless | 1 per function group | Sentry.wrapCloudEventFunction() | | Event-driven (Kafka/SQS) | @sentry/node | 1 per consumer group | continueTrace() from message headers | | Frontend SPA | @sentry/browser or @sentry/react | 1 frontend project | browserTracingIntegration() | | Mobile (React Native) | @sentry/react-native | 1 mobile project | Native crash reporting + JS errors | | Hybrid | Mix of above | 1 per deployment target | Cross-platform trace correlation |

Install the SDK for your architecture:

# Monolith / Microservices / Event-driven
npm install @sentry/node @sentry/profiling-node

# Serverless — AWS Lambda
npm install @sentry/aws-serverless

# Serverless — Google Cloud Functions
npm install @sentry/google-cloud-serverless

# Frontend SPA (React)
npm install @sentry/react

# Mobile — React Native
npx @sentry/wizard@latest -i reactNative

Step 2 — Initialize Sentry for Each Architecture Pattern

Monolith — Single Project, Module Tags

One DSN, one project. Separate concerns with module tags and team ownership rules.

// instrument.mjs — load via: node --import ./instrument.mjs app.js
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  release: process.env.APP_VERSION,
  tracesSampleRate: 0.1,
  initialScope: { tags: { app: 'monolith' } },
});

// Tag errors by module so each team sees only their issues
function captureModuleError(module: string, error: Error) {
  Sentry.withScope((scope) => {
    scope.setTag('module', module);
    scope.setTag('team', getTeamForModule(module));
    Sentry.captureException(error);
  });
}

// Module-based breadcrumbs for traceability
Sentry.addBreadcrumb({ category: 'auth', message: 'Login attempt', level: 'info' });
captureModuleError('auth', new Error('Token expired'));
// Dashboard ownership: tags.module:auth → #platform-team

Microservices — Project-per-Service, Distributed Tracing

Each service gets its own Sentry project. A shared config package keeps init consistent.

// packages/sentry-config/index.ts — shared across all services
import * as Sentry from '@sentry/node';

export function initServiceSentry(serviceName: string) {
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    environment: process.env.NODE_ENV,
    release: `${serviceName}@${process.env.APP_VERSION}`,
    serverName: serviceName,
    tracesSampleRate: 0.1,
    sendDefaultPii: false,
    initialScope: {
      tags: {
        service: serviceName,
        cluster: process.env.K8S_CLUSTER || 'default',
        namespace: process.env.K8S_NAMESPACE || 'default',
      },
    },
  });
}
// Usage: initServiceSentry('api-gateway');

HTTP tracing works automatically — SDK v8 propagates sentry-trace and baggage headers on all outbound HTTP requests. For service mesh (Istio/Linkerd), headers pass through transparently. For non-HTTP transports (gRPC, message queues), see event-driven pattern below and microservices deep-dive.

Serverless — Lambda and Cloud Functions

Serverless SDKs wrap your handler to auto-capture errors and flush events before the runtime freezes.

// AWS Lambda — handler.ts
import * as Sentry from '@sentry/aws-serverless';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.STAGE,
  tracesSampleRate: 0.1,
});

export const handler = Sentry.wrapHandler(async (event, context) => {
  Sentry.setTag('function', context.functionName);
  Sentry.setTag('region', process.env.AWS_REGION);

  // Track cold starts
  const isColdStart = !global.__sentryWarm;
  global.__sentryWarm = true;
  Sentry.setTag('cold_start', String(isColdStart));

  const result = await processRequest(event);
  return { statusCode: 200, body: JSON.stringify(result) };
});
// wrapHandler auto-calls flush() — do NOT call it yourself (double-flush causes timeout)
// Google Cloud Functions — index.ts
import * as Sentry from '@sentry/google-cloud-serverless';

Sentry.init({ dsn: process.env.SENTRY_DSN, tracesSampleRate: 0.1 });

export const httpHandler = Sentry.wrapHttpFunction(async (req, res) => {
  res.json(await processRequest(req.body));
});

export const eventHandler = Sentry.wrapCloudEventFunction(async (event) => {
  await processEvent(event.data);
});

Event-Driven — Kafka, SQS, and Message Queues

Propagate trace context through message headers so consumer spans connect to producer traces.

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

// Producer: embed trace context in message headers
async function publishToKafka(topic: string, payload: object) {
  const activeSpan = Sentry.getActiveSpan();
  const headers: Record<string, string> = {};
  if (activeSpan) {
    headers['sentry-trace'] = Sentry.spanToTraceHeader(activeSpan);
    headers['baggage'] = Sentry.spanToBaggageHeader(activeSpan) || '';
  }
  await Sentry.startSpan(
    { name: `kafka.produce.${topic}`, op: 'queue.publish' },
    () => kafka.send({ topic, messages: [{ value: JSON.stringify(payload), headers }] })
  );
}

// Consumer: continue the producer's trace
async function consumeFromKafka(message: KafkaMessage) {
  const headers = message.headers || {};
  Sentry.continueTrace(
    {
      sentryTrace: headers['sentry-trace']?.toString(), // Buffer → string
      baggage: headers['baggage']?.toString(),
    },
    () => {
      Sentry.startSpan(
        { name: `kafka.consume.${message.topic}`, op: 'queue.process' },
        async (span) => {
          try {
            await processMessage(message);
            span.setStatus({ code: 1 });
          } catch (error) {
            span.setStatus({ code: 2, message: 'consumer_error' });
            Sentry.captureException(error);
            throw error;
          }
        }
      );
    }
  );
}

For SQS consumers on Lambda, see event-driven deep-dive.

Frontend SPA — Browser and React

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

Sentry.init({
  dsn: process.env.REACT_APP_SENTRY_DSN,
  release: process.env.REACT_APP_VERSION,
  tracesSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration({ maskAllText: true, blockAllMedia: true }),
  ],
  // Must match your API domain or frontend-to-backend traces break
  tracePropagationTargets: ['localhost', /^https:\/\/api\.yourapp\.com/],
});

Route-based transactions, error boundaries, and session replay configuration: see frontend SPA deep-dive.

Mobile — React Native

import * as Sentry from '@sentry/react-native';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 0.2,
  integrations: [
    Sentry.reactNativeTracingIntegration({
      routingInstrumentation: Sentry.reactNavigationIntegration(),
    }),
  ],
  tracePropagationTargets: [/^https:\/\/api\.yourapp\.com/],
  enableNativeCrashHandling: true,
  attachScreenshot: true,
  attachViewHierarchy: true,
});

export default Sentry.wrap(App);
// Upload source maps + dSYMs in CI — see mobile deep-dive

Full navigation instrumentation and CI upload commands: see mobile deep-dive.

Step 3 — Wire Up Hybrid and Cross-Platform Tracing

For systems that span multiple architectures, connect traces end-to-end. The trace flow for a typical hybrid system:

  1. @sentry/react creates a transaction on user click
  2. Browser SDK adds sentry-trace + baggage headers to fetch()
  3. API gateway (@sentry/node) auto-continues the trace
  4. API gateway calls payment-service — headers propagate via HTTP
  5. payment-service publishes to Kafka — headers injected manually (see event-driven pattern)
  6. Worker (@sentry/node) continues trace from Kafka headers

Result: single trace ID visible across all services in Sentry Trace View. Backend-to-frontend correlation requires tracePropagationTargets in the browser SDK matching your API domains. Without this, the browser SDK will not attach trace headers and traces break at the browser-to-server boundary. See hybrid deep-dive.

Architecture decision matrix:

| Architecture | Projects | Tracing Strategy | SDK Flush | Key Gotcha | |---|---|---|---|---| | Monolith | 1 | Single-service spans | Automatic | Module tag cardinality — keep under 50 | | Microservices | 1 per service | Distributed via HTTP headers | Automatic | Missing baggage breaks sampling | | Serverless | 1 per function group | Per-invocation, auto-flush | wrapHandler() | Double-flush causes timeout | | Event-driven | 1 per consumer group | continueTrace() from headers | Manual periodic | DLQ needs separate error capture | | Frontend SPA | 1 | browserTracingIntegration() | Automatic (beacon) | tracePropagationTargets required | | Mobile | 1 | reactNativeTracingIntegration() | Automatic | Source maps + dSYMs required | | Hybrid | Mix of above | End-to-end header propagation | Per-component | One missing link breaks whole trace |

Output

After applying the appropriate pattern, you will have:

  • Architecture-specific Sentry.init() configuration with correct SDK package
  • Distributed tracing connected across all services (HTTP, gRPC, and message queues)
  • Serverless handlers wrapped with automatic error capture and event flushing
  • Event-driven consumers that continue producer traces via message headers
  • Frontend SPA with route-based transactions, session replay, and backend trace correlation
  • Mobile app with native crash reporting, screenshot capture, and navigation tracing
  • Hybrid systems with end-to-end trace visibility from browser/mobile through every backend hop

Error Handling

| Error | Cause | Solution | |---|---|---| | Distributed traces broken | Missing header propagation | Verify sentry-trace AND baggage headers in every inter-service call | | Lambda events lost after timeout | Calling flush() inside wrapHandler | Remove manual flush()wrapHandler auto-flushes | | Kafka consumer traces disconnected | Headers not serialized as strings | Call .toString() on Kafka message headers before continueTrace() | | SPA traces stop at API boundary | tracePropagationTargets missing | Add API domain regex to browser SDK init | | React Native traces unreadable | Missing source maps / dSYMs | Run sentry-cli sourcemaps upload and sentry-cli upload-dif in CI | | Multi-tenant data leakage | setTag() at global scope | Use withScope() per request — global tags persist across requests | | Worker events silently dropped | No periodic flush | Add setInterval(() => Sentry.flush(2000), 30_000) | | High cardinality alert | Dynamic values in span names | Use parameterized names: kafka.consume.orders not kafka.consume.order-12345 |

See also: Full error reference

Examples

Example 1 — Monolith with 5 teams: Request: "Set up Sentry for a monolith with auth, billing, inventory, shipping, and analytics modules." Result: Single Sentry project with module and team tags. Each team filters issues via tags.module:billing. Ownership rules route alerts to the correct Slack channel.

Example 2 — Microservices with Kafka: Request: "Configure Sentry for 12 microservices communicating via REST and Kafka." Result: 12 Sentry projects with shared initServiceSentry(). HTTP traces auto-propagate. Kafka producers inject sentry-trace/baggage into headers. Consumers call continueTrace(). Trace view: api-gateway -> order-service -> [kafka] -> fulfillment-worker.

Example 3 — Serverless API on Lambda: Request: "Add Sentry to 8 AWS Lambda functions behind API Gateway." Result: One Sentry project. Each handler wrapped with Sentry.wrapHandler(). Cold starts tagged. No manual flush() calls.

Example 4 — React SPA + Node API: Request: "Full-stack Sentry for a React frontend calling a Node.js Express API." Result: Two projects (frontend + backend). React uses @sentry/react with browserTracingIntegration() and replayIntegration(). tracePropagationTargets connects frontend to backend traces.

See also: Full examples

Resources

Next Steps

  • Run the sentry-performance-tuning skill to optimize tracesSampleRate and tracesSampler for production traffic volumes
  • Use sentry-cost-tuning to set rate limits and event budgets per project
  • Configure sentry-deploy-integration to tie releases to deploys for regression detection
  • Set up sentry-multi-env-setup to manage DSN routing across staging/production
  • Apply sentry-reliability-patterns for retry logic and circuit breakers around Sentry calls