skip to content

questions

3

How much data can you actually store in a single HTTP cookie, roughly how many cookies will a browser keep per domain, and what happens when you exceed those limits?

level: juniorimportance: should knowfreq 45%

answer

  1. ~4096 bytes per cookie, name+value+attributes
  2. ≥50 per domain by RFC; Chrome ~180
  3. over the limit = silent drop, no error
  4. eviction: expired first, then least recently used
  5. total Cookie header hits proxy 8 KB limits first

basics

~20 s

Roughly 4096 bytes for the whole Set-Cookie name plus value (attributes count in modern browsers), and at least 50 cookies per domain — Chrome allows about 180. Over the limit the browser silently ignores the Set-Cookie or evicts old cookies; you get no error.

solid answer

~50 s

RFC 6265 says a browser must support at least 4096 bytes per cookie (name + value + attributes), at least 50 cookies per domain, and at least 3000 cookies total. Real browsers land near that: ~4096 bytes per cookie, Chrome ~180 cookies per domain with a per-domain byte cap, plus a global cap in the low thousands. The failure mode is what matters in interviews: it is **silent**. An oversized `Set-Cookie` is simply not stored — no exception, no console error in most engines, and `document.cookie` just does not change. When the per-domain count is exceeded the browser evicts cookies, typically the least recently used or already-expired ones, so an unrelated cookie disappears. Practical consequence: cookies are for small identifiers, not payloads. Store an opaque session id and keep the data server-side, or use localStorage/IndexedDB for non-credential client state. Every cookie is also re-sent on every matching request, so size is a bandwidth and latency cost too.

code

http · 6 lines
http
HTTP/1.1 200 OK
Set-Cookie: blob=AAAA...(5000 bytes)...; Path=/

GET /next HTTP/1.1
Host: app.example.com
Cookie: theme=dark

go deeper

for a junior

Say ~4 KB per cookie and dozens per domain, and that oversized cookies are silently dropped — then note cookies are for ids, not data.

for a middle

Add that name, value and attributes all count, that eviction removes other cookies when the per-domain count is exceeded, and contrast with localStorage.

for a senior

Connect browser limits to server and proxy header limits, cookieless asset domains, and the fact that silent failure means you must measure header size in production.

for a principal

Treat the total per-request cookie budget as a platform constraint you allocate across teams — who is allowed to set cookies on the apex domain, and what the enforcement is.

## The numbers RFC 6265 sets *minimums* a user agent should support, not hard maxima: - at least **4096 bytes** per cookie, counting name, value and attributes together; - at least **50 cookies per domain**; - at least **3000 cookies total**. Browsers implement close to this. Treat 4096 bytes as the practical per-cookie ceiling. Chrome additionally enforces roughly 180 cookies per domain and a per-domain byte budget; Firefox and Safari have comparable caps. None of this is worth memorising precisely — what interviewers want is the order of magnitude (kilobytes, not megabytes) and the awareness that the limit is per cookie *and* per domain. A subtlety: the byte count is of the serialised cookie, and cookie values are typically percent-encoded or base64. A 3000-byte JWT becomes noticeably larger once encoded, and a UTF-8 name or value costs more than one byte per character. ## What failure looks like This is the part candidates get wrong. Exceeding limits does **not** raise an error. - **Oversized single cookie**: the browser drops the `Set-Cookie` header. The response still succeeds with its original status; the cookie simply never appears in the jar. If it was the session cookie, the next request is unauthenticated and the user bounces back to login — a confusing bug that looks like an auth failure. - **Too many cookies for the domain**: the browser makes room by evicting, usually expired cookies first, then least-recently-used ones. A cookie you set an hour ago can vanish because an unrelated feature wrote 40 new ones. - **Too much total data sent**: even if the browser stores everything, it concatenates all matching cookies into one `Cookie` request header. Servers and proxies cap total header size (commonly 8 KB per header block), so the request itself starts failing — typically `431 Request Header Fields Too Large`, or a `400` from an edge proxy — before any browser limit is hit. ## Design consequences **Cookies are identifiers, not storage.** The canonical design is a short opaque session id (tens of bytes) with state in a server-side store. That keeps the request header small and lets you revoke server-side. **Self-contained tokens are the usual bloat source.** A JWT with roles, permissions and profile claims can reach 2–4 KB, and it is re-sent on every request to the domain — including static assets, unless those live on a cookieless host. Two such cookies plus analytics cookies will exceed a proxy's header limit. **Prefer other storage for non-credentials.** `localStorage` (~5 MB per origin) and IndexedDB exist for client state that the server does not need on every request. The trade-off is that they are readable by JavaScript, so they are wrong for session credentials — which is exactly why credentials stay in an `HttpOnly` cookie and everything else does not go into cookies at all. **Serve static assets from a cookieless domain** (or a separate host that never receives your cookies) so kilobytes of cookies are not attached to every image request. **Do not shard a large value across several cookies.** Splitting a 12 KB token into three cookies defeats the per-cookie limit but multiplies request-header cost and creates a partial-write failure mode where one shard is evicted and the value becomes unreconstructable. **Instrument it.** Because failures are silent, teams catch cookie bloat late. Log total `Cookie` header size at the edge, alert on the p99, and after setting a critical cookie verify it round-trips rather than assuming the `Set-Cookie` took effect.

  • Your app must keep 20 KB of user preferences on the client. Where do you put it and why not a cookie?
    Use localStorage or IndexedDB, keyed by the user, and let the server read it only when it needs to. A cookie cannot hold 20 KB at all, and even if split it would be re-sent on every single request to the domain, wasting bandwidth on every asset fetch and risking proxy header limits.

A cookie is a luggage tag, not the suitcase. Write the claim number on the tag and leave the contents at the desk.

saying these in an interview costs you the question

  • Thinking a too-large Set-Cookie throws an error or returns a non-2xx status
  • Quoting 4096 bytes as a per-domain rather than per-cookie limit
  • Assuming attributes like Path and Expires do not count toward the size
  • Splitting a large token across many cookies as a normal solution
  • Believing cookies are a reasonable general-purpose client storage mechanism

context

open as a page

What do the `__Host-` and `__Secure-` name prefixes on an HTTP cookie mean, and what do browsers enforce when they see them?

level: middleimportance: should knowfreq 45%

basics

~20 s

They are cookie-name conventions browsers enforce. __Secure- makes the browser reject the Set-Cookie unless it has the Secure attribute and came over HTTPS. __Host- adds two rules: no Domain attribute and Path=/, so the cookie is host-only and no subdomain can set it.

open as a page

Some users of a web app suddenly get HTTP 431 Request Header Fields Too Large (or a 400 from the CDN) on every request, and clearing cookies fixes it. How do you diagnose and permanently fix this?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Accumulated cookies pushed the Cookie request header past the proxy or server header limit. Measure total cookie bytes per user, find the writer that keeps adding cookies, cap and expire them, shrink the session cookie to an opaque id, and serve assets from a cookieless host.

open as a page