Monitoring Guide

Monitor rate limiting activity and integrate with observability tools.

Rate Limit Events

Track rate limiting activity with event handlers:

import { hitlimit } from '@joint-ops/hitlimit'

const limiter = hitlimit({
  limit: 100,
  window: '1m',
  onRateLimit: (req, info) => {
    console.log(`Rate limited: ${info.key}`, {
      count: info.count,
      limit: info.limit,
      resetTime: info.resetTime
    })
  },
  onRequest: (req, info) => {
    // Called on every request
    metrics.increment('ratelimit.request')
  }
})

Prometheus Integration

import { Counter, Gauge } from 'prom-client'

const rateLimitHits = new Counter({
  name: 'ratelimit_hits_total',
  help: 'Total rate limit hits',
  labelNames: ['path', 'status']
})

const rateLimitRemaining = new Gauge({
  name: 'ratelimit_remaining',
  help: 'Remaining requests in window',
  labelNames: ['key']
})

const limiter = hitlimit({
  limit: 100,
  window: '1m',
  onRateLimit: (req, info) => {
    rateLimitHits.inc({ path: req.path, status: 'limited' })
  },
  onRequest: (req, info) => {
    rateLimitHits.inc({ path: req.path, status: 'allowed' })
    rateLimitRemaining.set(
      { key: info.key },
      info.limit - info.count
    )
  }
})

DataDog Integration

import { StatsD } from 'hot-shots'

const dogstatsd = new StatsD({
  host: 'localhost',
  port: 8125,
  prefix: 'api.'
})

const limiter = hitlimit({
  limit: 100,
  window: '1m',
  onRateLimit: (req, info) => {
    dogstatsd.increment('ratelimit.blocked', [
      `path:${req.path}`
    ])
  },
  onRequest: (req, info) => {
    dogstatsd.gauge(
      'ratelimit.remaining',
      info.limit - info.count,
      [`key:${info.key}`]
    )
  }
})

Structured Logging

import pino from 'pino'

const logger = pino({ level: 'info' })

const limiter = hitlimit({
  limit: 100,
  window: '1m',
  onRateLimit: (req, info) => {
    logger.warn({
      event: 'rate_limit_exceeded',
      key: info.key,
      path: req.path,
      count: info.count,
      limit: info.limit,
      ip: req.ip,
      userAgent: req.headers['user-agent']
    })
  }
})

Alerting Rules

Example Prometheus alerting rules:

# prometheus/alerts.yml
groups:
  - name: ratelimit
    rules:
      - alert: HighRateLimitRate
        expr: rate(ratelimit_hits_total{status="limited"}[5m]) > 10
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High rate limit hit rate"

      - alert: RateLimitSpike
        expr: rate(ratelimit_hits_total{status="limited"}[1m]) > 100
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Rate limit spike detected"

Dashboard Metrics

Key metrics to track:

MetricTypeDescription
ratelimit_hits_totalCounterTotal requests by status
ratelimit_remainingGaugeRemaining quota per key
ratelimit_latency_msHistogramRate limit check latency
ratelimit_keys_activeGaugeActive rate limit keys

Health Check Endpoint

app.get('/health/ratelimit', async (req, res) => {
  const store = limiter.store

  try {
    // Test store connectivity
    await store.get('health:check')

    res.json({
      status: 'healthy',
      store: store.constructor.name
    })
  } catch (err) {
    res.status(503).json({
      status: 'unhealthy',
      error: err.message
    })
  }
})