Skip to main content Inicio Creadores jeremylongshore claude-code-plugins-plus-skills sentry-load-scale
sentry-load-scale Scale Sentry for high-traffic applications handling millions of events per day.
Use when optimizing SDK performance at high volume, implementing adaptive sampling,
managing quotas and costs at scale, or deploying Sentry across multi-region infrastructure.
Trigger with phrases like "sentry high traffic", "scale sentry", "sentry millions events",
"sentry high volume", "sentry quota management", "sentry load test".
Ir a la instalación Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill sentry-load-scaleEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Más de este repositorio Implement user sign-up and sign-in flows with Clerk.
Use when building authentication UI, customizing sign-in experience,
or implementing OAuth social login.
Trigger with phrases like "clerk sign-in", "clerk sign-up",
"clerk login flow", "clerk OAuth", "clerk social login".
Implement session management and middleware with Clerk.
Use when managing user sessions, configuring route protection,
or implementing token refresh and custom JWT templates.
Trigger with phrases like "clerk session", "clerk middleware",
"clerk route protection", "clerk token", "clerk JWT".
Configure enterprise SSO, role-based access control, and organization management.
Use when implementing SSO integration, configuring role-based permissions,
or setting up organization-level controls.
Trigger with phrases like "clerk SSO", "clerk RBAC",
"clerk enterprise", "clerk roles", "clerk permissions", "clerk organizations".
Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional SOC
Explorador de archivos
7 archivos name sentry-load-scale description Scale Sentry for high-traffic applications handling millions of events per day.
Use when optimizing SDK performance at high volume, implementing adaptive sampling,
managing quotas and costs at scale, or deploying Sentry across multi-region infrastructure.
Trigger with phrases like "sentry high traffic", "scale sentry", "sentry millions events",
"sentry high volume", "sentry quota management", "sentry load test".
allowed-tools Read, Write, Edit, Grep, Bash(node:*), Bash(npx:*), Bash(k6:*) version 1.51.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","sentry","performance","scaling","high-traffic","enterprise"] compatibility Designed for Claude Code, also compatible with Codex and OpenClaw
Sentry Load & Scale
Overview
Configure Sentry for applications processing 1M+ requests/day without sacrificing error visibility, burning through quota, or adding measurable SDK overhead. Covers adaptive sampling, connection pooling, multi-region tagging, quota management, SDK benchmarking, batch submission, load testing, and self-hosted deployment considerations.
Prerequisites
Application handling sustained high traffic (>10K requests/min or >1M events/day)
Sentry organization with quota and billing access (Settings > Subscription)
@sentry/node v8+ installed (npm ls @sentry/node)
Performance baseline established (p50/p95/p99 latency without Sentry)
Event volume estimates calculated per category (errors, transactions, replays, attachments)
Instructions
Step 1 — Implement Adaptive Sampling
Static tracesSampleRate wastes quota at scale because it treats a health check the same as a checkout. Replace it with a traffic-aware tracesSampler that adjusts rates based on endpoint criticality and current load.
Traffic-aware tracesSampler:
import * as Sentry from '@sentry/node' ;
const endpointVolume = new Map <string , { count : number ; resetAt : number }>();
const WINDOW_MS = 60_000 ;
function getAdaptiveRate (name : string , baseRate : number ): number {
const now = Date .now ();
entry = endpointVolume. (name);
(!entry || now > entry. ) {
entry = { : , : now + };
endpointVolume. (name, entry);
}
entry. ++;
(entry. > ) baseRate * ;
(entry. > ) baseRate * ;
baseRate;
}
. ({
: process. . ,
: {
{ name, parentSampled } = samplingContext;
(parentSampled !== ) parentSampled ? : ;
(name?. ( )) ;
(name?. ( )) ;
(name?. ( ) || name?. ( )) ;
(name?. ( )) ( , );
(name?. ( )) (name, );
(name?. ( )) (name, );
(name?. ( )) (name, );
(name?. ( )) (name, );
(name?. ( ) || name?. ( )) {
(name, );
}
(name || , );
},
});
let
get
if
resetAt
count
0
resetAt
WINDOW_MS
set
count
if
count
1000
return
0.25
if
count
100
return
0.5
return
Sentry
init
dsn
env
SENTRY_DSN
tracesSampler
(samplingContext ) =>
const
if
undefined
return
1.0
0
if
match
/\/(health|ready|alive|ping|metrics|favicon)/
return
0
if
match
/\.(css|js|png|jpg|svg|woff2?|ico)$/
return
0
if
includes
'/payment'
includes
'/checkout'
return
1.0
if
includes
'/auth/login'
return
getAdaptiveRate
'auth'
0.5
if
startsWith
'POST /api/'
return
getAdaptiveRate
0.05
if
startsWith
'PUT /api/'
return
getAdaptiveRate
0.05
if
startsWith
'DELETE /api/'
return
getAdaptiveRate
0.05
if
startsWith
'GET /api/'
return
getAdaptiveRate
0.02
if
startsWith
'job:'
startsWith
'queue:'
return
getAdaptiveRate
0.01
return
getAdaptiveRate
'default'
0.005
Adaptive error deduplication with beforeSend:
const errorCounts = new Map <string , number >();
const ERROR_WINDOW_MS = 60_000 ;
setInterval (() => errorCounts.clear (), ERROR_WINDOW_MS );
Sentry .init ({
dsn : process.env .SENTRY_DSN ,
beforeSend (event, hint ) {
const error = hint?.originalException ;
const key = error instanceof Error
? `${error.name} :${error.message?.substring(0 , 100 )} `
: `unknown:${String (event.message || '' ).substring(0 , 100 )} ` ;
const count = (errorCounts.get (key) || 0 ) + 1 ;
errorCounts.set (key, count);
if (count === 1 ) return event;
if (count <= 10 ) return count % 5 === 0 ? event : null ;
if (count <= 100 ) return count % 25 === 0 ? event : null ;
return count % 100 === 0 ? event : null ;
},
});
Step 2 — Optimize SDK for Minimal Overhead At high throughput, every byte and every millisecond of SDK processing matters. This configuration reduces memory footprint, payload size, and CPU time.
import * as Sentry from '@sentry/node' ;
import os from 'node:os' ;
Sentry .init ({
dsn : process.env .SENTRY_DSN ,
environment : process.env .NODE_ENV || 'production' ,
release : `${process.env.SERVICE_NAME} @${process.env.VERSION || 'unknown' } ` ,
maxBreadcrumbs : 15 ,
maxValueLength : 200 ,
integrations : (defaults ) => defaults.filter (i =>
!['Console' , 'ContextLines' ].includes (i.name )
),
profilesSampleRate : 0 ,
transportOptions : {
bufferSize : 100 ,
},
beforeSend (event ) {
if (event.contexts ) {
for (const [key, ctx] of Object .entries (event.contexts )) {
const str = JSON .stringify (ctx);
if (str.length > 2000 ) {
event.contexts [key] = { _truncated : true , originalSize : str.length };
}
}
}
if (event.request ?.headers ) {
const keep = ['content-type' , 'accept' , 'user-agent' , 'x-request-id' ];
event.request .headers = Object .fromEntries (
Object .entries (event.request .headers )
.filter (([k] ) => keep.includes (k.toLowerCase ()))
);
}
return event;
},
serverName : process.env .HOSTNAME || process.env .POD_NAME || os.hostname (),
initialScope : {
tags : {
region : process.env .AWS_REGION || process.env .GCP_REGION || 'unknown' ,
cluster : process.env .K8S_CLUSTER || 'default' ,
pod : process.env .POD_NAME || 'unknown' ,
service : process.env .SERVICE_NAME || 'unknown' ,
},
},
});
Graceful shutdown ensuring event delivery:
import * as Sentry from '@sentry/node' ;
async function shutdown (signal : string ) {
console .log (`${signal} received — flushing Sentry events` );
server.close ();
const flushed = await Sentry .close (2000 );
if (!flushed) {
console .warn ('Sentry flush timed out — some events may be lost' );
}
process.exit (0 );
}
process.on ('SIGTERM' , () => shutdown ('SIGTERM' ));
process.on ('SIGINT' , () => shutdown ('SIGINT' ));
Step 3 — Manage Quotas, Test Under Load, and Plan for Scale Quota management and reserved volume pricing:
Application: 10M requests/day, 0.1% error rate, @sentry/node v8
Error events (with adaptive beforeSend):
Raw errors: 10M x 0.001 = 10,000/day
After dedup: ~1,000/day (90% reduction) = 30K/month
Transaction events (with tiered tracesSampler):
Health/static: 0% of 4M = 0
Payment (T1): 100% of 5K = 5,000/day
POST API (T2): 5% of 500K = 25,000/day
GET API (T3): 2% of 5M = 100,000/day
Other (T5): 0.5% of 500K = 2,500/day
Total: ~132K/day = 4M/month
Sentry Business plan ($26/mo base):
Errors: 30K included in base plan
Transactions: 100K included, overage 3.9M x $0.000025 = ~$97/mo
Estimated total: ~$123/month for 10M requests/day
Reserved volume (if predictable traffic):
5M txns/mo reserved = $80/mo (vs $97 on-demand)
Saves ~$17/mo, locks in price for 12 months
→ Total: ~$106/month
const initStart = performance.now ();
Sentry .init ({ });
const initMs = performance.now () - initStart;
console .log (`Sentry.init: ${initMs.toFixed(1 )} ms` );
import { performance, PerformanceObserver } from 'node:perf_hooks' ;
async function benchmarkOverhead (iterations : number = 1000 ) {
const baseStart = performance.now ();
for (let i = 0 ; i < iterations; i++) {
await handleRequest ({ path : '/api/test' , method : 'GET' });
}
const baseMs = (performance.now () - baseStart) / iterations;
const sentryStart = performance.now ();
for (let i = 0 ; i < iterations; i++) {
await Sentry .startSpan (
{ name : 'GET /api/test' , op : 'http.server' },
() => handleRequest ({ path : '/api/test' , method : 'GET' })
);
}
const sentryMs = (performance.now () - sentryStart) / iterations;
console .log (`Baseline: ${baseMs.toFixed(3 )} ms/req` );
console .log (`With Sentry: ${sentryMs.toFixed(3 )} ms/req` );
console .log (`Overhead: ${(sentryMs - baseMs).toFixed(3 )} ms (${(((sentryMs - baseMs) / baseMs) * 100 ).toFixed(1 )} %)` );
}
Load testing Sentry integration with k6:
import http from 'k6/http' ;
import { check, sleep } from 'k6' ;
import { Rate , Trend } from 'k6/metrics' ;
const errorRate = new Rate ('sentry_errors_captured' );
const latencyOverhead = new Trend ('sentry_latency_overhead_ms' );
export const options = {
stages : [
{ duration : '1m' , target : 50 },
{ duration : '3m' , target : 200 },
{ duration : '1m' , target : 0 },
],
thresholds : {
http_req_duration : ['p(95)<500' ],
sentry_latency_overhead_ms : ['p(95)<5' ],
},
};
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000' ;
export default function ( ) {
const readRes = http.get (`${BASE_URL} /api/products` );
check (readRes, { 'GET 200' : (r ) => r.status === 200 });
const sentryMs = readRes.headers ['Server-Timing' ]?.match (/sentry;dur=(\d+\.?\d*)/ );
if (sentryMs) latencyOverhead.add (parseFloat (sentryMs[1 ]));
if (Math .random () < 0.1 ) {
const writeRes = http.post (`${BASE_URL} /api/orders` , JSON .stringify ({
items : [{ sku : 'TEST-001' , qty : 1 }],
}), { headers : { 'Content-Type' : 'application/json' } });
check (writeRes, { 'POST 201' : (r ) => r.status === 201 });
}
if (Math .random () < 0.01 ) {
const errRes = http.get (`${BASE_URL} /api/nonexistent-route` );
errorRate.add (errRes.status === 404 );
}
sleep (0.1 );
}
Background worker batch patterns:
import * as Sentry from '@sentry/node' ;
async function processJobBatch (jobs : Job [] ) {
return Sentry .startSpan (
{
name : `batch.${jobs[0 ]?.type || 'unknown' } ` ,
op : 'queue.batch' ,
attributes : { 'batch.size' : jobs.length },
},
async () => {
const results = { success : 0 , failed : 0 };
for (const job of jobs) {
try {
await Sentry .withScope (async (scope) => {
scope.setTag ('job.type' , job.type );
scope.setTag ('job.queue' , job.queue );
scope.setContext ('job' , {
id : job.id ,
attempts : job.attempts ,
});
await executeJob (job);
results.success ++;
});
} catch (error) {
results.failed ++;
Sentry .captureException (error, {
tags : { 'job.id' : job.id , 'job.type' : job.type },
level : job.attempts >= 3 ? 'error' : 'warning' ,
});
}
}
Sentry .setMeasurement ('batch.success_rate' ,
results.success / jobs.length , 'ratio' );
return results;
}
);
}
setInterval (async () => {
await Sentry .flush (2000 );
}, 30_000 );
Self-hosted Sentry for enterprise (>100M events/month):
Relay: RELAY_PROCESSING_MAX_RATE: 50000, RELAY_UPSTREAM_MAX_CONNECTIONS: 200
Kafka: KAFKA_NUM_PARTITIONS: 32 (match to consumer count)
Snuba: 4+ consumer replicas for Clickhouse ingestion parallelism
Clickhouse: 16G+ RAM, dedicated SSD volumes
Self-hosted vs SaaS break-even:
SaaS at 100M events/month: ~$2,500/mo (Business plan + overage)
Self-hosted (3x r6g.2xlarge): ~$1,200/mo infra + $800/mo ops (0.25 FTE)
Break-even: ~50M events/month
→ Use SaaS up to 50M events; evaluate self-hosted above that
Output
Adaptive sampling reducing duplicate error volume by 90%+ while preserving first-occurrence fidelity
Traffic-aware tracesSampler with 5 tiers adjusting dynamically based on endpoint volume
SDK memory and CPU footprint minimized (15 breadcrumbs, truncated contexts, filtered headers)
Connection pooling via persistent HTTPS agent for efficient event submission
Multi-region infrastructure tags for filtering by region/cluster/pod in Sentry dashboard
Cost model with reserved volume pricing showing $106/month for 10M requests/day
k6 load test script validating Sentry overhead stays under 5ms at p95
Batch job processing pattern with scope isolation and periodic flush
Self-hosted vs SaaS break-even analysis for enterprise decision-making
Error Handling Error Cause Solution Events silently dropped SDK buffer full during traffic spike Increase transportOptions.bufferSize to 200+, verify network to Sentry ingest 429 rate limit from Sentry Quota exhausted or spike protection triggered Enable spike protection in Settings > Subscription, reduce sample rates Memory growing linearly over time Breadcrumb or scope accumulation Reduce maxBreadcrumbs, verify withScope is used (not configureScope) Lost events on deploy/restart No Sentry.close() in shutdown handler Add SIGTERM/SIGINT handlers calling Sentry.close(2000) Distributed traces broken at scale Mixed sampling decisions across services Always check parentSampled first in tracesSampler Clickhouse OOM on self-hosted Insufficient memory for event volume Allocate 16G+ RAM, increase Snuba consumer replicas k6 shows >5ms Sentry overhead Too many integrations or large payloads Disable Console/ContextLines integrations, reduce maxValueLength Quota burn from replay/attachments Replays not rate-limited separately Set replaysSessionSampleRate: 0.01 and replaysOnErrorSampleRate: 0.1
Examples Minimal high-scale init (copy-paste ready):
import * as Sentry from '@sentry/node' ;
Sentry .init ({
dsn : process.env .SENTRY_DSN ,
environment : process.env .NODE_ENV ,
release : `${process.env.SERVICE_NAME} @${process.env.VERSION} ` ,
maxBreadcrumbs : 15 ,
maxValueLength : 200 ,
profilesSampleRate : 0 ,
tracesSampler : ({ name, parentSampled } ) => {
if (parentSampled !== undefined ) return parentSampled ? 1.0 : 0 ;
if (name?.match (/\/(health|ping|metrics)/ )) return 0 ;
if (name?.includes ('/payment' )) return 1.0 ;
if (name?.startsWith ('POST /api/' )) return 0.05 ;
return 0.005 ;
},
});
Verify sampling is working as expected:
Sentry .init ({
tracesSampler : (ctx ) => {
const rate = calculateRate (ctx);
if (process.env .DEBUG_SENTRY === 'true' ) {
console .log (`[sentry] ${ctx.name} → rate=${rate} ` );
}
return rate;
},
});
Resources
Next Steps
Run the k6 load test against staging to establish your baseline Sentry overhead
Set up Sentry Spike Protection (Settings > Subscription > Spike Protection) before going to production
Configure server-side sampling rules in Sentry Dynamic Sampling (Project Settings > Performance) to complement client-side tracesSampler
Create a Sentry dashboard with widgets for: events/hour by category, quota usage %, p95 SDK overhead
Review the sentry-cost-tuning skill for detailed quota optimization strategies