DEV Community

jtalk22
jtalk22

Posted on • Originally published at revaddress.com

5 Patterns for Handling USPS v3 API Rate Limits (60 req/hour is brutal)

USPS API Rate Limits: From 6,000/min to 60/hour — What Happened and How to Fix It

USPS replaced their Web Tools XML API with a v3 REST API in January 2026. One thing nobody expected: they dropped rate limits from ~6,000 requests/minute to 60 requests/hour for new applications.

If you're hitting 429s on the USPS v3 API, here's what's actually happening and five architecture patterns to handle it.

What Changed

Old API (Web Tools XML):

  • ~6,000 requests/minute
  • No formal documentation on limits
  • Generous in practice

New API (v3 REST):

  • 60 requests/hour (new applications)
  • 5 requests/minute burst
  • Enforced with HTTP 429

That's a 99% reduction in throughput. A shipping operation doing 1,000 validations/day now needs a fundamentally different architecture.

Why It Happened

USPS's v3 API serves consumer-facing apps (Informed Delivery, etc.) on the same infrastructure. Rate limits protect shared infrastructure. Enterprise shippers get higher limits via the USPS API team, but new applications start at 60/hour.

You can request a rate limit increase through the USPS Developer Portal, but approval takes 2-4 weeks and requires a business justification.

Pattern 1: Response Cache

Most address validation results don't change. Cache responses with a TTL:

import hashlib
import json

def cached_validate(address, cache, client):
    key = hashlib.sha256(
        json.dumps(address, sort_keys=True).encode()
    ).hexdigest()

    cached = cache.get(key)
    if cached:
        return json.loads(cached)

    result = client.addresses.validate(**address)
    cache.set(key, json.dumps(result), ex=86400)  # 24h TTL
    return result
Enter fullscreen mode Exit fullscreen mode

Impact: If 40% of your addresses are repeats (common in B2B), you cut API calls by 40%.

Pattern 2: Request Queue with Rate Smoothing

Don't burst — spread requests evenly across the rate window:

class RateLimiter {
  constructor(maxPerHour = 60) {
    this.interval = (3600 / maxPerHour) * 1000; // ms between requests
    this.queue = [];
    this.processing = false;
  }

  async add(fn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ fn, resolve, reject });
      this.process();
    });
  }

  async process() {
    if (this.processing || !this.queue.length) return;
    this.processing = true;

    const { fn, resolve, reject } = this.queue.shift();
    try {
      resolve(await fn());
    } catch (e) {
      reject(e);
    }

    setTimeout(() => {
      this.processing = false;
      this.process();
    }, this.interval);
  }
}
Enter fullscreen mode Exit fullscreen mode

Pattern 3: Batch Pre-validation

Validate addresses at import time, not checkout time:

  1. Customer uploads CSV of shipping addresses
  2. Background job validates all addresses over hours (staying under rate limit)
  3. Cache results
  4. At label creation time, pull from cache — no API call needed

This works if you have advance notice of addresses (most B2B shippers do).

Pattern 4: Multi-Key Rotation

If you have multiple USPS API credentials (separate business units, departments), rotate between them:

import itertools

keys = itertools.cycle([
    {"client_id": "key1_id", "client_secret": "key1_secret"},
    {"client_id": "key2_id", "client_secret": "key2_secret"},
])

def get_next_client():
    creds = next(keys)
    return USPSClient(**creds)
Enter fullscreen mode Exit fullscreen mode

Warning: USPS terms require each application to have its own credentials. This is only valid if you genuinely have separate applications.

Pattern 5: API Proxy with Built-in Rate Management

If you don't want to build caching and queuing yourself, API proxies handle this at the infrastructure layer. They pool connections, manage token refresh, and smooth rate limits.

I built RevAddress for this exact problem — it's a USPS v3 proxy with 120-600 req/min depending on tier. But you can also build this yourself with Redis + a worker queue.

Request a Rate Limit Increase

The official path:

  1. Log into the USPS Developer Portal
  2. Go to your application → Support
  3. File a service request: "Rate limit increase for [App Name]"
  4. Include: your CRID, current volume, expected volume, business justification
  5. Wait 2-4 weeks

Include actual numbers. "We process 5,000 address validations daily for e-commerce checkout" is better than "we need more requests."


Full article with more code patterns: revaddress.com/blog/usps-api-rate-limits-2026-what-changed

Open-source USPS v3 SDKs: github.com/revereveal/usps-v3

Top comments (0)