Skip to content

fix(relay): Fix race conditions in rate limiter and Kafka producer #125

@ShashwatpSingh

Description

@ShashwatpSingh

Summary

Multiple race conditions found in the relay core that can cause:

  • Rate limiting bypass (allowing more requests than configured)
  • Multiple Kafka producer instances (resource leak)
  • Potential message duplication

Race Condition 1: In-Memory Rate Limiter (Critical)

Location: packages/relay-core/src/ratelimit.ts

Problem: Read-modify-write race on token bucket:

if (b.tokens >= 1) {  // Check
  b.tokens -= 1;        // Modify - multiple requests pass here

Impact: Under concurrent load, the rate limiter allows more requests than the configured RPS.

Fix: Add proper async locking or use atomic compare-and-swap pattern.

Race Condition 2: Kafka Producer Initialization

Location: packages/relay-core/src/producer.ts

Problem: Lazy initialization without locking:

if (producer) return producer;  // Check
// ... async gap ...
producer = kafka.producer();      // Set - multiple producers created

Impact: Multiple Kafka producer instances under concurrent first requests, causing resource leak and potential message duplication.

Fix: Use proper initialization guard with promise-based locking.

Proposed Solution

I can submit a PR with:

  1. Async mutex for rate limiter token operations
  2. Promise-based initialization guard for Kafka producer
  3. Unit tests for concurrent scenarios
  4. No breaking changes to public APIs

These are production-critical fixes for high-traffic deployments.

Testing

  • Concurrent rate limit tests
  • Concurrent producer initialization tests
  • Load testing under parallel requests

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