VanaAPI

← 文章

Retries With Backoff That Never Double-Charge

接口格式EN2026-10-25

A request times out. Your application retries. The second attempt succeeds, but did the first attempt already generate tokens? Backoff controls when another attempt happens; it does not establish whether repeating an operation is safe. Preventing duplicate effects requires an idempotency contract, not just a longer delay. ([aws.amazon.com](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/?did=ba_card&utm_source=openai))

This walkthrough separates two goals: charging your customer once and avoiding duplicate upstream generation. You can enforce the first in your application. The second requires documented provider support or a conservative decision not to replay uncertain requests.

§ Step 1: Establish the guarantee

Vana API provides an OpenAI-compatible entry point alongside native protocol routes. Compatibility tells you how to send requests, not whether repeated requests share one execution or bill. Verify the selected route’s idempotency behavior before enabling automatic replay. Do not assume that adding an Idempotency-Key header creates deduplication. ([vanaapi.com](https://vanaapi.com/))

Define the boundary: your application can promise one customer debit per logical operation. Promise one upstream charge only when the provider explicitly guarantees deduplication across retries, including its retention window and failure behavior. Otherwise, stop on ambiguity.

§ Step 2: Persist one logical operation

Create a durable operation ID before contacting the API. Reuse it for browser resubmissions, queue redelivery, and worker retries. Associate it with the authenticated customer and a fingerprint of the complete generation request: model, messages, tools, and generation settings.

  • Use a database uniqueness constraint to admit one operation per customer and operation ID.
  • Reject reuse of an ID with a different request fingerprint.
  • Store states such as pending, running, completed, failed, and unknown.
  • Return the saved result when a completed operation is requested again.

This follows the explicit-request-identity approach used in idempotent API design. A matching prompt alone is not a sufficient identifier: users may intentionally submit identical requests twice. ([aws.amazon.com](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/?did=ba_card&utm_source=openai))

§ Step 3: Give one layer retry ownership

Choose the application or SDK to manage retries, rather than stacking independent loops. The OpenAI JavaScript SDK retries certain failures twice by default, including connection errors, timeouts, rate limits, and server errors. When implementing the policy here, disable those automatic retries so every network attempt passes through your safety checks. ([developers.openai.com](https://developers.openai.com/api/reference/typescript?utm_source=openai))

Require an atomic worker claim before dispatch. Do not automatically redispatch an expired running job: a crashed worker may have sent the request before losing its database connection. Mark that situation unknown and reconcile it.

§ Step 4: Classify before retrying

Separate temporary rejection from uncertain execution. Fix invalid input, authentication, and exhausted billing limits instead of retrying unchanged requests. Temporary throttling may justify a delayed retry, but inspect the error details rather than treating every 429 identically. ([developers.openai.com](https://developers.openai.com/api/docs/guides/error-codes?utm_source=openai))

A timeout, dropped connection, or server failure can leave the outcome uncertain. Under the strict policy, retry only when you can establish that execution never began, or when documented idempotency makes replay safe. Otherwise, preserve the operation as unknown rather than launching another generation. ([aws.amazon.com](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/?did=ba_card&utm_source=openai))

§ Step 5: Apply bounded backoff with jitter

For requests that pass that safety gate, start with an example policy of three total attempts and a 30-second deadline. Before each retry, choose a random delay between zero and the smaller of eight seconds or 500 milliseconds multiplied by two to the retry index, starting at zero.

Honor a valid Retry-After value as a minimum wait. If it exceeds your remaining deadline, defer or stop rather than shortening it. Randomization spreads retries; attempt and elapsed-time limits keep recovery bounded. These are scheduling controls, not duplicate-billing protection. ([developers.openai.com](https://developers.openai.com/api/docs/guides/rate-limits?utm_source=openai))

§ Step 6: Settle once, then test uncertainty

Design one database transaction to save the completed result and insert a customer ledger debit with a unique operation ID. On repeat delivery, return the saved result without inserting another debit. Keep upstream usage records separate from customer settlement.

Test simultaneous submissions, worker crashes after dispatch, lost responses, and interrupted streams. Require unknown outcomes to remain blocked from automatic replay. This trades some automatic recovery for a defensible no-duplicate policy.

Create a Vana API account to test this workflow with a small, controlled workload before enabling retries in production.