Skip to content

synapsmedia/sentry-rate-limiter

Repository files navigation

@synapsmedia/sentry-rate-limiter

In-memory rate limiter for Sentry error reporting to prevent duplicate error spam and avoid draining your error log quota.

Why?

While Sentry has spike protection that limits errors to ~500 per hour, it doesn't make sense to receive hundreds of logs for a single error on the backend. This library ensures that each unique error is only reported a few times within a configurable time window, dramatically reducing quota usage while still capturing enough information to debug issues.

Features

  • 🚀 Zero dependencies (except peer dependency on @sentry/node)
  • 📦 TypeScript support with full type definitions
  • 🎯 Smart fingerprinting based on error type, message, and stack trace
  • ⏱️ Configurable time windows (hourly, daily, or custom)
  • 🧹 Automatic memory cleanup to prevent memory leaks
  • 📊 Statistics API to monitor rate limiting behavior

Installation

npm install @synapsmedia/sentry-rate-limiter

or

yarn add @synapsmedia/sentry-rate-limiter

Peer dependency: Requires @sentry/node v7.x or v8.x

Usage

Basic Setup

import * as Sentry from "@sentry/node";
import { SentryRateLimiter, createBeforeSend } from "@synapsmedia/sentry-rate-limiter";

// Create rate limiter instance
const rateLimiter = new SentryRateLimiter({
  maxReportsPerWindow: 5,  // Allow max 5 reports per window
  windowHours: 1,          // 1 hour window
});

// Initialize Sentry with rate limiting
Sentry.init({
  dsn: "your-sentry-dsn",
  beforeSend: createBeforeSend(rateLimiter),
  // ... other Sentry options
});

Custom Configuration

const rateLimiter = new SentryRateLimiter({
  maxReportsPerWindow: 3,        // Max 3 reports per window
  windowHours: 24,               // 24 hour window
  cleanupIntervalMinutes: 30,    // Run cleanup every 30 minutes
});

Manual Integration

If you need more control over the beforeSend hook:

import { SentryRateLimiter } from "@synapsmedia/sentry-rate-limiter";

const rateLimiter = new SentryRateLimiter();

Sentry.init({
  dsn: "your-sentry-dsn",
  beforeSend(event) {
    // Your custom logic here
    
    // Apply rate limiting
    if (!rateLimiter.shouldReport(event)) {
      return null;  // Drop the event
    }
    
    // More custom logic
    
    return event;
  },
});

Monitoring Statistics

// Get current rate limiting statistics
const stats = rateLimiter.getStats();

console.log(`Tracking ${stats.trackedErrors} unique errors`);
stats.errors.forEach(error => {
  console.log(`Error ${error.fingerprint}:`);
  console.log(`  Count: ${error.count}`);
  console.log(`  First seen: ${error.firstSeen}`);
  console.log(`  Last seen: ${error.lastSeen}`);
});

Cleanup

If you need to manually destroy the rate limiter (e.g., in tests):

rateLimiter.destroy();

How It Works

  1. Fingerprinting: Each error gets a unique SHA256 fingerprint based on:

    • Error type (e.g., TypeError, ReferenceError)
    • Error message
    • Top 3 stack frames (file and line number)
  2. Rate Limiting:

    • First occurrence of an error is always reported
    • Subsequent identical errors are counted within the time window
    • Once the limit is reached, additional occurrences are dropped
    • After the window expires, the counter resets
  3. Memory Management:

    • Automatic cleanup runs periodically to remove stale entries
    • Prevents memory leaks in long-running applications

Configuration Options

Option Type Default Description
maxReportsPerWindow number 5 Maximum number of reports allowed per unique error within the time window
windowHours number 1 Time window in hours for rate limiting
cleanupIntervalMinutes number 15 How often to run cleanup of stale entries (in minutes)

Examples

Strict Rate Limiting (Daily)

// Only allow 2 reports per error per day
const rateLimiter = new SentryRateLimiter({
  maxReportsPerWindow: 2,
  windowHours: 24,
});

Lenient Rate Limiting (Hourly)

// Allow up to 10 reports per error per hour
const rateLimiter = new SentryRateLimiter({
  maxReportsPerWindow: 10,
  windowHours: 1,
});

Production vs Development

const rateLimiter = new SentryRateLimiter({
  maxReportsPerWindow: process.env.NODE_ENV === 'production' ? 3 : 100,
  windowHours: process.env.NODE_ENV === 'production' ? 24 : 1,
});

TypeScript

This library is written in TypeScript and includes full type definitions. All types are exported:

import type { 
  SentryRateLimiter, 
  SentryRateLimiterOptions,
  ErrorRateLimit 
} from "@synapsmedia/sentry-rate-limiter";

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and questions, please open an issue on GitHub.

About

In-memory rate limiter for Sentry error reporting to better handling the quota

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published