---
title: Redis
description: The recommended production store. Live streams are pushed, not polled.
---

```ts server/orders.ts
import { createServer } from 'experimental-a2/server'
import { redis } from 'experimental-a2/store-redis'
import { orders } from '@/contracts'

export const ordersServer = createServer({
  contract: orders,
  store: redis({ url: process.env.REDIS_URL }),
  consumers: [
    /* ... */
  ],
})
```

```package-install
npm i ioredis
```

Works on a single Redis or Valkey instance and on non-cluster providers such as
Upstash, which is durable by default (use its TCP `rediss://` URL). There's
nothing to set up: A2 creates its keys as it writes. For rotating credentials or
custom TLS and reconnect settings, use the same store on node-redis:
[Valkey](/stores/valkey).

## Options

| Option | |
| --- | --- |
| `url` | creates an `ioredis` client |
| `client` | your own `ioredis` client instead |
| `keyPrefix` | isolates several apps on one Redis. Default `'a2'`; no braces |
| `clock`, `ids` | test seams for timestamps and generated event ids |

## Upgrade

The store records its key layout in `<keyPrefix>:schema`, and refuses a prefix
marked with another one with `STORE_NOT_CONFIGURED`. A release that changes
the layout says what to do on its [upgrade page](/upgrades/overview). This
release names every key differently from earlier ones, so give the store a
fresh `keyPrefix`.

## How it works

- Each session is a Redis Stream, and every key of a session shares one hash
  tag.
- Every write is one atomic script over its session's keys. On Upstash, which
  runs a script under a database-wide lock by default, A2 marks each script to
  lock only its session's keys. Redis and Valkey run one command at a time, so
  A2 keeps scripts short instead.
- Every write publishes a wake-up after its script, so live streams are
  push-driven, and connections scale with your processes, not with your
  viewers.
- A wake-up is disposable: a safety re-read recovers a lost one within ten
  seconds.

## Cost per command

On providers that bill per command, such as Upstash, appending an event with a
consumer and running it takes 19 commands, and an idle live stream takes 6 a
minute.
