Redis is the default `store.kv` image in `dev` and `prod`. `oke docker` matches image
references containing `redis` or `keydb` and derives a password-required server — no
unauthenticated instance.

<Callout title="The one rule">
  The driver id stays `redis` for every Redis-wire image — Redis, Valkey, Dragonfly, or a managed
  provider. Vendor choice lives in `images["store.kv"]`, never in `drivers.store.kv`.
</Callout>

## Quick start

<Steps>

<Step>
### Pin the image

```typescript title="oke.config.ts"
images: {
  "store.kv": "redis:8-alpine",
},
```

</Step>

<Step>
### Required password

```bash title=".env.local (written by oke docker)"
OKE_STORE_KV_PASSWORD=…
REDIS_URL=redis://:…@127.0.0.1:6379
```

The recipe runs:

`redis-server --requirepass "$OKE_STORE_KV_PASSWORD" --maxmemory … --maxmemory-policy …`

</Step>

<Step>
### Optional memory caps

| Variable                        | Default in recipe                                       | Meaning  |
| ------------------------------- | ------------------------------------------------------- | -------- |
| `OKE_STORE_KV_MAXMEMORY`        | `0` (unlimited) in command; stack often sets `256mb`    | Max RSS  |
| `OKE_STORE_KV_MAXMEMORY_POLICY` | `noeviction` in command; stack often sets `allkeys-lru` | Eviction |

</Step>

</Steps>

## Required env

| Variable                        | Required?     | Meaning                                                            |
| ------------------------------- | ------------- | ------------------------------------------------------------------ |
| `OKE_STORE_KV_PASSWORD`         | **Yes**       | `--requirepass` — empty password is not a valid production posture |
| `REDIS_URL`                     | **Yes** (app) | What the `redis` driver opens (`OKE_STORE_KV_URL` also works)      |
| `OKE_STORE_KV_MAXMEMORY`        | Optional      | Cap memory                                                         |
| `OKE_STORE_KV_MAXMEMORY_POLICY` | Optional      | Eviction when at cap                                               |

## Data and backup

The default `store.kv` recipe declares **no named volume**. Process memory is the source of truth;
a container recreate loses those keys.

Keys that must survive go on `{ durable: true }` — a JSONB table on your SQL database, not a
second Redis. See [Store · Durable KV](/docs/elements/store#durable-kv).

## Production note

<Callout title="License note" type="warn">
  Redis ≥8 is dual-licensed RSALv2 / SSPLv1 / AGPLv3. Those terms restrict offering Redis itself as
  a managed service to third parties — running it for your own app is unaffected. Prefer
  [Valkey](/docs/recipes/valkey) when the managed-service restriction matters.
</Callout>

Multi-replica Gate rate counters and Signal need a **shared** Redis URL — an in-process
`memory` driver is per instance. Same shared-store idea as
[Clock](/docs/elements/clock#what-the-runtime-guarantees) for cron exclusivity.

## What the recipe configures

| Field          | Value                                                |
| -------------- | ---------------------------------------------------- |
| Container port | `6379`                                               |
| Healthcheck    | `redis-cli -a <password> ping`, every 5s, 10 retries |
| Connection URL | `redis://:pass@host:6379`                            |

<Callout title="Console Performance">
  Store → KV band → **Performance** reads `INFO` / `SLOWLOG` on this instance. Those commands are
  server-wide, not scoped to `oke:kv:{ns}:`. `memory` (tests) returns `KvStatsUnsupported`.
</Callout>

## Troubleshooting

<Accordions>
<Accordion title="oke boot: redis driver needs REDIS_URL">

Missing `REDIS_URL` fails boot loudly — never a silent fallback to `memory`. Re-run
`oke dev` or export `REDIS_URL` when using a managed host. Under Compose the
message asks whether `oke dev -d` wrote `.env.local`.

</Accordion>
<Accordion title="NOAUTH Authentication required">

`REDIS_URL` is missing the password, or it does not match `OKE_STORE_KV_PASSWORD`.
Format must be `redis://:PASSWORD@host:6379` (colon before the password, empty username).

</Accordion>
</Accordions>

## Learn more

- [Store · KV](/docs/elements/store#kv) — TTL physics, per-driver behavior, license table
- [Valkey](/docs/recipes/valkey) · [Dragonfly](/docs/recipes/dragonfly) — Redis-wire peers
- [Environment variables](/docs/reference/environment-variables) — `REDIS_URL` precedence

## Next

<Cards>
  <Card title="Valkey" description="Permissive-licensed alternative." href="/docs/recipes/valkey" />
  <Card title="Redis Cloud" description="Managed Redis." href="/docs/providers/redis-cloud" />
  <Card
    title="Upstash"
    description="Serverless Redis-protocol option."
    href="/docs/providers/upstash"
  />
</Cards>
