ZenCex.Adapters.Binance.RateLimiter (zen_cex v0.2.1)
View SourcePragmatic rate limiter for Binance REST APIs - optimized for regular trading, not HFT.
This implementation follows a reactive approach suitable for non-HFT usage:
- Monitors rate limit headers from responses and logs warnings
- Does NOT maintain sliding windows or complex state
- Relies on Req's retry mechanism for 429 responses
- Emergency Bypass: Always allows critical safety operations (cancel_order, cancel_all, close_position)
- Reserved Capacity: Reserves 10% of rate limit capacity for emergency operations
Binance Rate Limits (per minute)
- Spot API: 1200 weight units (1080 regular, 120 emergency reserve)
- SAPI: 12000 weight units (10800 regular, 1200 emergency reserve)
- USD-M Futures: 2400 weight units (2160 regular, 240 emergency reserve)
- COIN-M Futures: 2400 weight units (2160 regular, 240 emergency reserve)
- Portfolio Margin: 3000 weight units (2700 regular, 300 emergency reserve)
Emergency Operations
Emergency operations that bypass normal rate limits:
- Order cancellation (single, batch, all)
- Position closing
- Risk management operations
Monitoring Approach
- Logs WARNING at 80% of regular capacity
- Logs CRITICAL at 95% of regular capacity
- Emergency operations always proceed even at 100% usage
- Lets Req handle 429 responses with exponential backoff
ETS Table Management
This module creates separate ETS tables for each API type to prevent contention:
- Table naming convention:
Elixir.ZenCex.Adapters.Binance.RateLimiter.Table.{api_type} - Tables are created on-demand when first accessed
- Supported API types:
:spot,:sapi,:usdm_futures,:coinm_futures,:portfolio - Each table tracks rate limit usage independently with minute-based windows
Summary
Functions
Enhanced version that accepts operation atom for better emergency detection.
Cleans up old entries from all API type tables. Should be called periodically (e.g., every minute) to prevent memory growth.
Functions
@spec check_and_increment(String.t() | atom(), non_neg_integer(), atom() | nil) :: :ok | {:error, :rate_limited} | {:error, {:rate_limited, non_neg_integer()}}
Enhanced version that accepts operation atom for better emergency detection.
@spec cleanup_old_entries() :: non_neg_integer()
Cleans up old entries from all API type tables. Should be called periodically (e.g., every minute) to prevent memory growth.