An API can respond quickly while the browser still waits for permission to send the request. Diagnose the two exchanges separately: the preflight asks whether a cross-origin request is allowed; the application request does the work. Their combined duration depends on the network and infrastructure. There is no universal 200 ms preflight penalty.
This is a troubleshooting method, not a report of a measured client incident.
What triggers a preflight
A cross-origin JSON POST usually triggers a preflight because application/json is not a safelisted content type. A manually supplied Authorization header also requires permission. GET, HEAD and POST can avoid preflight only when the other safelisting conditions are satisfied.
CORS governs what browsers let scripts read and, for preflighted requests, whether they send the application request. It does not authenticate callers. Some cross-origin requests can reach a server without a preflight, so CORS is not a substitute for CSRF protection or authorization. MDN’s CORS guide explains these boundaries.
Read the exchange before changing the policy
Suppose a dashboard at https://app.example.com posts JSON to https://api.example.com/orders. The relevant preflight fields look like this:
OPTIONS /orders HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
An API that deliberately allows this dashboard could respond:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Max-Age: 600
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
These are illustrative headers, not a complete API implementation. The actual POST response also needs its applicable CORS headers, including on errors. Match the incoming origin against an explicit allowlist; never reflect an arbitrary Origin as approval. Merge Vary with existing values.
If the application uses credentialed cross-origin cookies, it also needs the appropriate credentials policy. A wildcard allowed origin does not work with the browser’s credentials mode set to include. Do not remove authentication or change cookie settings merely to eliminate OPTIONS.
Cache deliberately
Access-Control-Max-Age controls the browser’s preflight cache, which is separate from an ordinary HTTP response cache. An omitted value does not mean every request must preflight: the documented default is five seconds. Browser limits can shorten a larger configured duration. MDN documents the default and browser caps.
Choose a duration that fits how quickly an origin or method permission may need to be revoked. Then test both a fresh browser context and repeated requests. One successful warm request does not prove that a new visitor avoids the round trip.
A useful investigation worksheet
For each failing request, record the initiating page origin, target URL, method, requested headers, credentials mode, OPTIONS status, application status and the layer that produced each response.
| Observation | Next check |
|---|---|
| OPTIONS redirects | Inspect the API’s canonical URL and gateway routing |
| OPTIONS is unauthorized | Check whether authentication middleware incorrectly requires a session for permission discovery |
| POST returns 401 but JavaScript sees only a CORS failure | Ensure the error response carries the allowed origin’s response headers |
| Browser fails while a command-line request succeeds | Compare browser policy separately from API authentication |
| Latency remains after a warm preflight | Profile the application, connection setup and upstream services |
Keep permission discovery free of application side effects. The POST still authenticates the caller and validates access to the requested resource.
A same-origin backend route may simplify the browser boundary, but it introduces a proxy that must preserve authorization, timeouts and useful errors. Evaluate that architecture on its whole request path. The goal is a comprehensible, measured policy—not disguising JSON as text or weakening the API until the browser stops complaining.

Sardar Mukhshaf
Full-Stack & DevOps Engineer
I build scalable web applications, secure backend systems, and production-ready cloud infrastructure. My engineering focus spans interface design, API architecture, deployment pipelines, and observability. Follow for more deep dives into system architecture, performance engineering, and emerging technologies.
More from the practice
Keep the useful ideas close.
Follow new articles with your preferred RSS reader.
Open the RSS feed ↗


