Skip to content

Add Discord rate limiting with exponential backoff retry mechanism #284

@anshulchikhale30-p

Description

@anshulchikhale30-p

Is your feature request related to a problem?

  • Yes, it is related to a problem

Describe the feature you'd like

Problem

The Discord bot lacks proper rate limit handling:

  • 429 errors occur when hitting Discord API rate limits
  • No recovery mechanism - errors just propagate to user
  • Poor user experience - message send failures without auto-retry
  • Silent failures - no logging of rate limit incidents

Current Behavior

User command → Bot tries to send → 429 Error → User sees "something went wrong"

Desired Behavior

User command → Bot tries to send → 429 Error → Auto-retry with exponential backoff → Success

Solution Overview

Implement a robust rate limiting system with:

  1. Rate limit tracking per Discord endpoint/bucket
  2. Exponential backoff retry logic (2^n + jitter)
  3. Command queueing during rate limits
  4. Comprehensive logging and metrics
  5. Graceful degradation with user-friendly messages

Implementation Details

Component 1: Rate Limiter Core

  • Create backend/rate_limiter.py
  • Implement DiscordRateLimiter class with:
    • wait_if_rate_limited() - Check if endpoint is rate limited
    • execute_with_retry() - Execute with automatic retry
    • Exponential backoff: 2^attempt × retry_after + jitter
    • Maximum 3 retry attempts

Component 2: Discord Client Wrapper

  • Create backend/discord_client.py
  • Implement EnhancedDiscordClient class with:
    • send_message_with_retry() - Send with rate limit handling
    • edit_message_with_retry() - Edit with rate limit handling
    • Error handling for 429 responses
    • User-friendly error messages

Component 3: Redis Integration

  • Use Redis to track rate limit state across bot instances
  • Store: discord_ratelimit:bucket:remaining, discord_ratelimit_reset:bucket
  • Per-endpoint tracking (channels, reactions, etc.)

Files to Create

backend/
├── rate_limiter.py (180 lines) - Core rate limiting logic
├── discord_client.py (250 lines) - Enhanced Discord client
└── discord_utils.py (80 lines) - Helper utilities
tests/
├── test_rate_limiter.py (200 lines) - Rate limiter tests
├── test_discord_client.py (150 lines) - Client tests
└── fixtures/discord_mocks.py (100 lines) - Test fixtures
docs/
└── DISCORD_RATE_LIMITING.md (150 lines) - Usage documentation

Integration Points

  • Update backend/bot.py to use enhanced client (+45 lines)
  • Add redis>=4.0.0 to requirements.txt
  • Set environment: REDIS_URL=redis://localhost:6379

Testing

  • 12+ unit tests for rate limiter logic
  • Integration tests with mock Discord API
  • Exponential backoff calculation verification
  • Retry exhaustion handling
  • Performance tests (minimal overhead when not rate limited)

Acceptance Criteria

  • Rate limits properly detected and handled
  • Automatic retry with exponential backoff
  • Maximum 3 retry attempts configurable
  • Command queueing during rate limits
  • Rate limit incidents logged with details
  • Zero performance impact when not rate limited
  • 90%+ test coverage
  • No merge conflicts
  • All existing tests still pass
  • Documentation included

Performance Requirements

  • Overhead when NOT rate limited: <1ms per request
  • Successful retry adds latency only when rate limited
  • Redis operations are async and non-blocking
  • No impact on normal message flow

Migration Guide

For deployments using this:

  1. Install Redis: pip install redis>=4.0.0
  2. Set REDIS_URL environment variable
  3. Start Redis service
  4. Update code to use EnhancedDiscordClient
  5. Test in staging first
  6. Deploy with monitoring

References

Related Issues

Fixes: Bot resilience failures when hitting Discord limits
Related to: #48 (general bot reliability)

Nice to Have (Future)

  • Prometheus metrics for rate limit tracking
  • Rate limit prediction using historical data
  • Per-guild rate limiting
  • Analytics dashboard

Record

  • I agree to follow this project's Code of Conduct
  • I want to work on implementing this feature

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions