# How it works

> The CDN read path, local evaluation, and 10-second polling.

Most feature flag services put an API server in front of every flag check: your
app asks the server "is this flag on?" and waits for an answer. Switchbox doesn't.
Your flag configuration is published as a **static JSON file on Cloudflare's
edge**, and the SDK reads it from there — never from our API.

## The write path

When you toggle a flag, change a rule, or edit a value in the dashboard, the API
does two things:

1. Writes the change to its database (the source of truth).
2. Regenerates the **entire** config for that environment as a JSON file and
   uploads it to the CDN, at a path derived from the environment's SDK key.

This happens on every mutation. There's no separate "publish" button — saving *is*
publishing.

## The read path

Your app's SDK fetches that JSON file and caches it in memory. From then on:

- **Evaluation is local.** When you call `enabled()` or `getValue()`, the SDK
  evaluates the flag's rules and rollout against the cached config, in-process.
  There is no network round-trip per check — it's sub-millisecond.
- **The config refreshes in the background.** A poller re-fetches the file every
  10 seconds (configurable). A change you make in the dashboard reaches your app
  within one poll interval.
- **Polls are conditional, so an unchanged config costs no bandwidth.** The SDK
  remembers the version identifier (`ETag`) the edge gave it and sends it back on
  the next poll. If nothing changed, the edge answers with an empty `304 Not
  Modified` and no config body. You pay for the payload on the first fetch, not
  every 10 seconds. Nothing to configure.
- **Reads are served from the edge, never from our API.** The file sits on
  Cloudflare and is served by a Cloudflare Worker close to your users. Our API
  server is only ever in the write path.

## What this buys you

- **No added latency.** Flag checks don't touch the network, so they can't slow
  down a request.
- **Resilience.** If the CDN read fails — or our API is down entirely — the SDK
  keeps serving the **last config it successfully fetched**. Your flags keep
  working. If the SDK has *never* fetched a config (e.g. the network was down at
  startup), `enabled()` returns `false` and `getValue()` returns the default you
  pass in. No exceptions are thrown into your request path.
- **CDN-scale reads.** Read traffic is static-file GETs on Cloudflare's edge, not
  database queries, so it scales the way a CDN does.

## The trade-off to know about

Because delivery is poll-based, **changes are not instant** — a toggle takes up to
your poll interval (~10 seconds by default) to reach every running client. This is
the deliberate cost of keeping the read path off our servers. For the vast
majority of flag use cases — rollouts, kill switches, targeting — that's
imperceptible. If you need a hard guarantee that a value has propagated, wait one
poll interval before depending on it.

## Next

- [Environments & SDK keys](/docs/concepts/environments) — how the per-environment
  key maps to a file on the CDN.
- [Evaluation order](/docs/reference/evaluation-order) — the exact precedence the
  SDK follows.
