# Caching CORS preflights: hundreds of milliseconds per call

> A practical note on preflight caching, custom auth headers, and why OPTIONS requests quietly dominate app latency on slower connections.

- Category: Engineering
- Published: 2026-04-17
- Authors: Om Gate
- Canonical: https://videodb.io/blog/cors-preflight-cache
- HTML: https://videodb.io/blog/cors-preflight-cache · Markdown: https://videodb.io/blog/cors-preflight-cache.md
- Tags: frontend-performance, api, latency

---
## What we saw
Browser apps often pay for an extra network request before the real API request. If the request uses a custom auth header, a non-simple content type, or a method such as `PUT`, `PATCH`, or `DELETE`, the browser sends an `OPTIONS` preflight first.

That preflight is correct browser behavior, but it can quietly dominate perceived latency. In one measurement, repeated preflight calls were taking more than 250 ms each before the real request even started.

## Why it happens
A preflight asks the server whether a cross-origin request is allowed for a specific origin, method, and set of headers. If the server says yes, the browser sends the real request.

```http
OPTIONS /sessions HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type, x-access-token
```

If your application makes many authenticated calls during startup, the browser may be doing a matching preflight for each endpoint. The API looks slow even if the backend handler is fast.

## What we changed
Cache successful preflight responses with `Access-Control-Max-Age`. In Flask-CORS, this is a one-line change.

```python
CORS(
    app,
    origins="*",
    methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
    allow_headers="*",
    max_age=86400,
)
```

The browser can now reuse the preflight result for the same origin, endpoint, method, and headers instead of asking again on every call.

## What it did to the numbers
| Case | Preflight behavior | Observed overhead |
|---|---|---|
| Before | Repeated OPTIONS calls | 250 ms plus per API call |
| After | Cached preflight result | Skipped on repeat calls |

## What we would tell another team
If a browser app calls a public API with custom headers, inspect the network waterfall for `OPTIONS`. The fastest handler cannot help if every request is preceded by an avoidable round trip.

## Cite this work

Om Gate, "Caching CORS preflights: hundreds of milliseconds per call", VideoDB Labs, April 2026.

```bibtex
@article{gate2026caching,
  author = {Om Gate},
  title = {Caching CORS preflights: hundreds of milliseconds per call},
  journal = {VideoDB Labs},
  year = {2026},
  month = {apr},
  note = {https://videodb.io/blog/cors-preflight-cache},
}
```
