Rate Limits & Compute Units

API Quotas, Compute Unit Costs, and Backoff Strategies

Tower enforces rate limits based on Compute Units (CU) consumed per minute and monthly quotas to ensure high availability and fair platform utilization.


Plan Tiers & Quotas

Plan TierRate Limit (Req / Min)Monthly Compute UnitsBurst Capacity
Developer (Free)60 req / min100,000 CU10 req / sec
Growth (Paid)600 req / min2,000,000 CU50 req / sec
Enterprise (Custom)CustomDedicated Node PoolCustom

Compute Unit (CU) Costs by Endpoint

EndpointMethodCompute CostScope Required
/api/public/pricesGET1 CUread
/api/public/wallet/balancePOST1 CUread
/api/public/swap/dexesGET1 CUread
/api/public/swap/quotePOST2 CUswaps
/api/public/swap/build-txPOST3 CUswaps
/api/public/rpc/{chainId}POST1 CUread
/api/public/bridgePOST5 CUbridges

Rate Limit Response Headers

Every HTTP response from Tower Developer APIs includes standard rate limit headers:

  • X-RateLimit-Limit: Maximum requests permitted within the active 60-second rolling window.
  • X-RateLimit-Remaining: Number of requests remaining in the current window.
  • Retry-After: Seconds to wait before retrying when an HTTP 429 Too Many Requests is returned.

Handling 429 Responses with Exponential Backoff

When your application hits rate limits (HTTP 429), implement exponential backoff with jitter to retry gracefully.

JavaScript / TypeScript

javascript
async function fetchWithRetry(url, options, maxRetries = 4, baseDelayMs = 500) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    const retryAfter = response.headers.get("Retry-After");
    const delay = retryAfter 
      ? parseInt(retryAfter, 10) * 1000 
      : baseDelayMs * Math.pow(2, attempt);

    console.warn(`Rate limit hit (429). Retrying in ${delay}ms...`);
    await new Promise((resolve) => setTimeout(resolve, delay));
  }

  throw new Error("Max retries exceeded for rate-limited endpoint.");
}

Python

python
import time
import requests

def request_with_retry(method, url, headers=None, json=None, max_retries=4, base_delay=0.5):
    for attempt in range(max_retries):
        response = requests.request(method, url, headers=headers, json=json)
        
        if response.status_code != 429:
            return response
            
        retry_after = response.headers.get("Retry-After")
        delay = float(retry_after) if retry_after else base_delay * (2 ** attempt)
        
        print(f"Rate limit hit (429). Retrying in {delay}s...")
        time.sleep(delay)
        
    raise Exception("Max retries exceeded for rate-limited endpoint.")