Rate Limiting
AutoP2P uses a three-layer rate limiting architecture to stay within Binance's limits while maximising repricing frequency. A circuit breaker provides automatic recovery from overload.
Three-Layer Architecture
Requests pass through three independent layers in order. All layers must allow a request before it is dispatched.
| Layer | Scope | Mechanism | Key Config |
|---|---|---|---|
| L1 | Per-Ad | Token bucket per individual ad engine | LIMITER_GLOBAL_RPS=4.5, LIMITER_PER_AD_RPS=1.5 |
| L2 | Global | Shared token bucket + concurrency semaphore | GLOBAL_BINANCE_RPS=5.0, GLOBAL_MAX_CONCURRENT=8, weight limit 12 000/min |
| L3 | Client Retry Budget | Per-call exponential backoff with attempt cap | RETRY_BUDGET=5 attempts |
Circuit Breaker State Machine
The global limiter includes a circuit breaker that automatically suspends requests when error rates spike, then probes recovery before resuming full traffic.
| Variable | Default | Description |
|---|---|---|
| GLOBAL_CB_THRESHOLD | 15 | Consecutive failures before tripping OPEN |
| GLOBAL_CB_COOLDOWN | 45.0 | Seconds to wait in OPEN before entering HALF-OPEN |
| GLOBAL_CB_HALF_OPEN_REQUESTS | 1 | Number of probe requests allowed in HALF-OPEN state |
Client-Side Rate Limit Groups
Binance enforces separate weight limits per API group. AutoP2P tracks usage per group using response headers.
| Group | Endpoints | Weight Header | Limit |
|---|---|---|---|
| adv | All /sapi/v1/c2c/ endpoints | x-mbx-used-weight-1m | 12 000 / min |
| sapi | Signed SAPI requests (general) | x-sapi-used-ip-weight-1m | 12 000 / min |
| spot | /api/v3/ endpoints (e.g. server time) | x-mbx-used-weight-1m | 6 000 / min |
Weight Tracking
After every response, AutoP2P reads the x-mbx-used-weight-1m header and compares it to the known limit. When usage exceeds WEIGHT_BACKOFF_THRESHOLD (default 80%), the global limiter slows token emission to avoid hitting the hard ceiling.
# Pseudo-logic in global_limiter.on_response()
used = int(response.headers.get("x-mbx-used-weight-1m", 0))
ratio = used / 12_000 # WEIGHT_LIMIT
if ratio >= WEIGHT_BACKOFF_THRESHOLD: # default 0.8
# Reduce token emission rate proportionally
limiter.set_rate(GLOBAL_BINANCE_RPS * (1 - ratio))
else:
limiter.set_rate(GLOBAL_BINANCE_RPS)Empty response arrays from the public BAPI search (EP-0) trigger a separate soft rate limit detector. After EMPTY_RESPONSE_THRESHOLD consecutive empty results, the limiter adds a cooldown before the next search request.
Best Practices
Price-Only Updates
Send only advNo + price in EP-7. Each extra field adds Binance validation load and risks error 187049.
Fresh Timestamps on Retry
On -1021 / -1022 errors, always rebuild the request with a new timestamp after syncing server time. Reusing the old signed URL will fail again.
Respect Concurrency Limit
GLOBAL_MAX_CONCURRENT is a semaphore, not a queue. Requests that cannot acquire a slot immediately are deferred, not dropped.
Stealth Headers for BAPI
The public BAPI search (EP-0) soft rate limits on repeated identical User-Agent strings. Rotate browser-like User-Agent headers to avoid detection.
All Environment Variables
All rate limiting behaviour is configurable via environment variables. Defaults are tuned for safe production operation with a single Binance account.
| Variable | Default | Description |
|---|---|---|
| GLOBAL_BINANCE_RPS | 5.0 | Global token bucket RPS |
| GLOBAL_MAX_CONCURRENT | 8 | Max concurrent Binance requests |
| GLOBAL_CB_THRESHOLD | 15 | Circuit breaker failure threshold |
| GLOBAL_CB_COOLDOWN | 45.0 | Circuit breaker cooldown (seconds) |
| GLOBAL_CB_HALF_OPEN_REQUESTS | 1 | Requests allowed in half-open state |
| LIMITER_GLOBAL_RPS | 4.5 | Per-ad global RPS across all ads |
| LIMITER_PER_AD_RPS | 1.5 | Per-ad max RPS |
| WEIGHT_BACKOFF_THRESHOLD | 0.8 | Weight usage ratio triggering backoff |
| EMPTY_RESPONSE_THRESHOLD | 3 | Empty responses before soft rate limit detection |
| RETRY_BUDGET | 5 | Max retry attempts per call |
| ERROR_187XXX_RETRY_SLEEP_SEC | 0.3 | Sleep before retry on 187xxx errors |
| BINANCE_RETRY_SYNC_ON_1000 | false | Per-method flag: sync time on -1000 errors |
| C2C_AD_NOT_FOUND_TTL_SEC | 60 | Negative 404 cache TTL |
| C2C_AD_NOT_FOUND_CACHE_MAX | 1024 | Max entries in 404 cache |
| ENGINE_BINANCE_RANGE_TTL_SEC | 300 | Dynamic price range cache TTL |