> ## Documentation Index
> Fetch the complete documentation index at: https://docs.deepface.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Production outcomes, cost and retries

> Separate completed work, rejected requests and uncertain compute before deciding whether another attempt is safe.

# Production outcomes, cost and retries

A failed client command does not prove that inference failed or that no charge
occurred. Keep **completion**, **billability** and **the next permitted action**
separate. Use the complete [JavaScript](/guides/javascript.md) or
[Python](/guides/python.md) examples as the conservative starting point: each
command sends at most one compute request, omits optional paid priority and
never automatically replays a failed or uncertain response.

Use only permitted inputs and authorized compute. Configure credentials in your
backend; do not put keys, images, embeddings or signed image URLs in logs, chat
or command arguments. Prepare code while an owner completes the existing
[account/key step](/authentication.md). Missing credentials mean preparation is
blocked, not that an integration has completed.

## Interpret the outcome before retrying

The table assumes a trusted response from the named layer and the corresponding
endpoint contract. A status number, HTML proxy page or `Retry-After` header alone
cannot establish when work stopped.

| Evidence | Completion and cost interpretation | Next action |
| - | - | - |
| Valid completed `/verify` response, including `verified: false`; valid `/represent` or `/compare` result | Completed work. A non-match is not a service failure. Completed usage can consume free allowance or be charged under the account's policy. | Record the result. Do not repeat inference to turn a non-match into a match. |
| Gateway HTTP `422` with `error: "no_face_detected"` | Detection completed without finding a face. This is a billable completed outcome despite the non-2xx status. | Handle no-face explicitly. Another permitted image is a new authorized compute attempt, not a free transient retry. |
| Confirmed invalid input, missing/revoked key or invalid priority rejected before compute | No completed inference. Invalid requests are uncharged under the public contract. | Correct the input/configuration or complete the owner handoff. Do not rotate keys or enable priority to bypass controls. |
| Explicit precompute rejection such as `429 rate_limited`, `503 queue_full`, `queue_timeout`, `request_body_budget_full`, `gateway_draining` or `auth_backend_unavailable` | That rejected attempt did not start inference. Final gateway failures are uncharged. | A bounded retry policy may be appropriate after the condition clears and another attempt is authorized. The examples do not perform it automatically. |
| Explicit `503 model_not_ready`, `model_busy` or `model_queue_timeout` | Model admission rejected that attempt before inference. The gateway already performs bounded admission retries internally. | Respect the returned delay and your total attempt/time/cost budget; do not add an unbounded outer retry loop. |
| Timeout, connection loss, malformed/truncated response, unrecognized 5xx, `upstream_failed` or `upstream_timeout` | Work may have started or completed. A client/MCP/proxy failure does not establish the gateway's final billing receipt. | Preserve the request ID, mark completion and charge as unresolved, and investigate before another compute attempt. |
| MCP `compute_outcome_unknown`, with `outcome: "unknown"` and `retryable: false` | The adapter cannot establish completion. Accepted gateway work may continue after the MCP wait ends. | Stop automatic compute replay. Retain the original ID; do not switch adapters or change IDs to evade uncertainty. |
| Accepted/pending response such as HTTP `202` | Acceptance is not completed inference. It does not establish the final result or charge. | Follow that endpoint's documented completion mechanism. These synchronous examples report an unknown outcome rather than inventing success. |
| `409 request_id_conflict` | A request ID was already used/reserved where replay protection applies. The conflict is not a cached inference result or proof of completion. | Reconcile the original attempt. Never automatically mint another ID to get past the conflict. |

An ordinary example exit code of `1` includes no-face, pending and unknown
outcomes. Its `retryable: false` means the example will not replay compute; it
is not a statement that the request was unbilled. The public gateway preserves
legacy no-face HTTP 422 even when the private model reports a no-face success.
See [error details](/api-reference/errors.md) for the exact codes and boundaries.

## Preserve the original attempt

Before dispatch, persist your own job/attempt state in private application
storage. If your client owns request-ID generation, persist its normalized UUID
before the call. The provided examples generate an ID inside the compute helper
and return it with a completed result or error; they do not implement a durable
job store. Capture that ID when available. If the process loses the ID, keep the
job unresolved; a missing ID does not prove no inference ran. Retain the
operation, time, symbolic outcome and explicit retry delay, without sensitive
payloads in operational logs.

For an unknown outcome:

1. Mark the original job unresolved and stop automatic compute retries, including
   retries hidden in HTTP middleware, SDK wrappers, worker redelivery or an agent.
2. Keep the original request ID. Do not resubmit under a new ID, another key or
   another adapter as a way to get a result.
3. Have an authorized operator reconcile the request record, result if available,
   account usage and billing receipt. Send only the minimum permitted diagnostic
   context through the owner's normal support process.
4. Resume only after the outcome is understood and another action is authorized.
   If a known completed result was retained securely, reuse it rather than
   rerunning inference to repair a local export or database write.

Request IDs support tracing and replay-conflict detection; they are not a
universal idempotency key, stored-result lookup or exactly-once guarantee.
Do not rely on replay protection being active for every account/deployed
revision. Reusing an ID may return a conflict rather than a result. A separately
authorized new attempt after a confirmed precompute rejection needs its own
application attempt record and must follow the endpoint's ID contract; preserve
the earlier ID in its history. This never authorizes changing an unresolved ID.

If your application persists embeddings or enrollments, keep its storage state
separate from compute completion. A lost database acknowledgement can follow
successful inference. Use a durable pending/reservation state so worker retries
do not silently issue the same paid computation again. The [customer-owned
search pattern](/customer-owned-face-search.md) has additional storage and isolation
requirements; no hosted result-retrieval endpoint is implied here.

## Bound a deliberate retry policy

For a confirmed precompute rejection, an application may implement a policy
with an explicit attempt ceiling, total deadline and owner-approved cost limit.
Honor `Retry-After`, use bounded backoff with jitter, and stop on an unknown
outcome or a terminal configuration/authorization error. A retry is a new HTTP
attempt that can pass through rate limiting/admission again. Do not assume it is
free or exempt from the account's limits.

Only the exact documented model admission rejections are retried by the gateway
within its upstream deadline. Those internal admission retries retain one
normalized request UUID and settle one final request outcome. A second client
POST is different. Generic 502/504 responses and lost connections are not proof
that model admission rejected the work. Avoid a blanket “retry all 5xx” policy.

MCP and gateway time budgets are different: the MCP compute wait is 120 seconds;
the gateway's documented upstream budget is 240 seconds. An earlier caller
abort does not prove the gateway cancelled work. Increasing a local timeout
does not make an already-unknown attempt safe to replay. See
[limits and admission behavior](/api-reference/rate-limits.md).

## Keep billing separate from transport success

Under the public contract, completed processing includes a non-match and no-face.
Other final gateway non-2xx failures are uncharged. A timeout or malformed response
observed at another layer does not establish that final gateway outcome. Retain
an unresolved charge state until it is reconciled; do not label it zero-cost
merely because your client exited with an error.

A billable completion does not necessarily debit a paid balance: free allowance,
active discounts and the account's agreed contract affect settlement. Use actual
account usage/receipts for the amount. This guide does not activate a tariff or
promise a fixed price. See [current pricing and governance](/pricing-governance.md).

Default requests should omit `X-Request-Priority` and MCP `priority`.
Omitted, null and zero mean normal own-account order, with no per-request
priority surcharge. Any explicitly positive priority can double completed-call
pricing, even when the queue is idle. A value such as `0.79` is positive too.
Under the default policy, enterprise lane treatment can also select 2× pricing;
both privileges together apply 2× once, not 4×. Agreed contracts can differ.
Omission does not override the account's enterprise/contract policy.

Do not enable priority to recover from a capacity rejection without intentional
owner authority for its billing effect. Priority does not preempt active work,
bypass limits, reserve capacity or guarantee latency. Experimental async compare
rejects positive priority. Review [priority and receipt
semantics](/api-reference/rate-limits.md#request-priority) before changing it.

## What the local examples establish

The maintained failure fixture executes all six JS/Python commands against a
loopback server across invalid credentials, explicit admission failures,
no-face, conflicting IDs, ambiguous transport/parse outcomes, pending responses
and redirects. It checks one compute POST per failing command, no paid priority,
preserved IDs and no sensitive output. Missing credentials cause no network
request. Separate checks exercise the gateway's source billing/no-face/priority
rules and both MCP adapters' unknown-outcome handling.

These are synthetic transport and source-contract checks. They do not run face
models, inspect a customer's ledger, certify deployed billing, or prove a real
client cancelled in-flight inference. A deployment and permitted configured-key
acceptance test remain separate evidence.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.