Skip to main content

Safe Retries and Rate Limits

Network failures, timeouts, and retries are inevitable in distributed systems. Recurso provides two mechanisms to help you build resilient integrations:
  • Idempotency — Safely retry requests without causing duplicate side effects (double charges, duplicate subscriptions)
  • Rate Limiting — Protect the platform and your account from excessive request volume

Idempotency

How It Works

Every mutating API request (POST, PUT, PATCH, DELETE) can include an Idempotency-Key header. Recurso uses this key to detect duplicate requests and return the original response instead of processing the request again.

Using the Idempotency-Key Header

Include the header on any request that creates or modifies resources:

Key Format Recommendations

Use UUID v4 as your default strategy. Prefix with idem_ for readability in logs. If you need the same request to always produce the same key (e.g., webhook handlers), use a deterministic hash of the request parameters.

Idempotency Rules

Two different API keys can use the same idempotency key value without conflict. Keys are scoped to the authenticated API key making the request.
Idempotency keys are stored for 24 hours. After that, the same key can be reused for a new request. This prevents unbounded storage growth while covering typical retry windows.
If you reuse an idempotency key with a different request body, Recurso returns a 422 Unprocessable Entity error. This prevents accidental misuse where different operations share a key.
GET requests are naturally idempotent and do not require an Idempotency-Key header. The header is only checked on POST, PUT, PATCH, and DELETE requests.
If the original request returned a 4xx or 5xx error, the idempotency key is released. Retrying with the same key will re-execute the request, giving you a chance to succeed after a transient failure.

Idempotency Best Practices

  1. Always use idempotency keys for payment-related operations — Creating subscriptions, recording payments, and issuing refunds should always include an idempotency key
  2. Generate keys client-side — Generate the key before sending the request so retries use the same key
  3. Store keys alongside business operations — Log the idempotency key with your internal transaction ID for traceability
  4. Do not reuse keys across different operations — Each distinct business operation should have a unique key

Rate Limiting

Recurso enforces rate limits per API key to ensure platform stability and fair usage.

Rate Limit Tiers

Rate limits are applied per API key, not per tenant. If you have multiple API keys, each has its own independent rate limit counter.

Rate Limit Headers

Every API response includes headers that tell you your current rate limit status:

Handling 429 Too Many Requests

When you exceed the rate limit, Recurso returns a 429 Too Many Requests response with a Retry-After header:

Retry Strategies

Exponential Backoff

The recommended retry strategy uses exponential backoff with jitter to avoid thundering-herd problems:

Retry Decision Table

Never retry 400, 401, 404, or 422 errors. These indicate client-side issues that will not resolve on retry. Retrying these wastes your rate limit budget.

Monitoring Rate Limit Usage

Track your rate limit consumption to proactively avoid hitting limits:

Best Practices

Always Use Idempotency Keys

Include idempotency keys on every mutating request, especially payments and subscription changes.

Respect Retry-After

When you receive a 429, always honor the Retry-After header rather than using a fixed delay.

Add Jitter to Backoff

Randomize retry delays to prevent multiple clients from retrying in lockstep and overwhelming the API.

Cache Read Results

Cache GET responses locally to reduce API calls. Use webhooks for real-time updates instead of polling.

Use Bulk Endpoints

Prefer batch APIs (e.g., usage.recordBatch) over individual calls to stay within rate limits on high-volume operations.

Monitor and Alert

Set up monitoring on X-RateLimit-Remaining. Alert your team when remaining requests drop below 10% of the limit.