CodexHowSupport Us

Flex and Batch Cost the Same but Aren't Identical

The mistake

Assuming Flex and Batch are two names for one product because they're priced identically for every text model that offers both — and then picking whichever comes to mind first, expecting the same behavior from either.

Why this happens

The tables really are numerically identical, published separately and matching row for row, both at a 50% discount to Standard. "Same price, so same product" is a reasonable inference, and nothing in either name heads it off.

Why it matters

They are different ways of making a request. Batch takes a file of requests, runs them asynchronously and commits to completing within a fixed 24-hour window, against its own rate-limit pool. Flex is an ordinary synchronous Responses or Chat Completions call with service_tier set to flex: you wait on the response like any other request, it can be noticeably slower, and it can occasionally fail with resource unavailability — OpenAI suggests raising your client timeout for it. A job moved to Flex "because it's the same as Batch" can surface timeouts and retries that Batch would never have shown, and a job moved to Batch "because it's the same as Flex" gives up a synchronous response it may have needed.

The fix

Choose on the shape of the work, not the price. Large, deadline-tolerant jobs you can submit as a file — nightly backfills, bulk evaluation — belong on Batch, for its fixed window and separate rate-limit pool. Synchronous calls that can tolerate latency and the occasional retry — evaluations run inline, enrichment inside an existing pipeline — fit Flex, with a longer timeout and retry handling in place. Flex is in beta with limited model availability, so check that your model offers it.

Telling which one you're already using

Look at how the work is submitted. If your code uploads a file, creates a batch and polls for results, it's on Batch, and its requests count against Batch's separate limits. If it makes ordinary Responses or Chat Completions calls with service_tier set to flex, it's on Flex, and it lives with whatever timeout and retry behavior your client has. For synchronous calls, the response's own service_tier field reports the tier that actually processed the request. Mixed setups are common and fine — a nightly Batch job and an inline Flex evaluation in the same codebase, each matched to its own shape.

See also

Every service tier, Standard to Ultrafast lays out every tier, and the Batch API reference lists Batch's own limits.

Verified 2026-10-28 against CodexHow facts module (src/data/facts/) — see /about/#accuracy.