> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useduro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Test & Live Modes

> Two physically separate worlds. The key prefix is the switch.

Duro has two modes — `test` and `live` — and they are **separate Postgres schemas**, not a flag on a row. A test key cannot read, write, or bill anything in live.

```mermaid theme={null}
flowchart LR
    SKT["sk_test_…"] --> SANDBOX[("sandbox schema<br/>your test data")]
    SKL["sk_live_…"] --> LIVE[("live schema<br/>real customers, real money")]
    SANDBOX -. cannot reach .-x LIVE
```

## How mode is chosen

| Caller                 | Mode comes from                           |
| ---------------------- | ----------------------------------------- |
| Secret/publishable key | the prefix (`_test_` / `_live_`)          |
| OAuth token            | the client id prefix                      |
| Hosted checkout        | the token (`cs_<mode>_…`)                 |
| Customer portal        | an explicit `?mode=` (defaults to `live`) |

You never pass a `mode` parameter to the merchant API — it's implied by your key. Use a test key while building, swap to a live key to go to production. The request bodies and responses are identical.

<Note>
  Because the data is physically partitioned, there's no "test transaction" cluttering your live tables and no risk of a forgotten filter exposing test data to production reads. The isolation is structural. See the [data model](/architecture/data-model).
</Note>

## Going live

1. Complete KYC in the dashboard (CAC, MEMART, status report). An unverified tenant is capped at ₦1,000,000 in total revenue.
2. Once approved, your tenant's tier becomes `verified` and the cap lifts.
3. Mint a `sk_live_` key and point your integration at it. Nothing else changes.
