Redis
Postgres keeps what is true. Redis keeps what every copy of the API has to share while it runs:
| What | Read more |
|---|---|
| The job queue, with BullMQ | Background jobs |
| Events to everyone connected to a workspace | Realtime |
| The assistant’s answers while they are written | AI features |
| Rate limits: signing in, API keys, and your own | below |
| A cache for your own features | below |
Losing what is in Redis loses no data: queued jobs are in Postgres until BullMQ has them, an event is a nudge to look again, and an answer can be asked for again. Back it up anyway, for the jobs BullMQ is holding: Railway’s Redis keeps its data on a volume.
Run it
Section titled “Run it”bun run services:up starts it with Postgres and Mailpit; REDIS_URL points at it. On Railway it
is a service of the project, and the API reads its REDIS_URL: see Railway.
On another host, Redis 7 or later (the kit is tested on 8), or Valkey. /api/health and bun run deploy:check say
when the API cannot reach it.
Every key the app writes starts with app:, through RedisService.key(). Use it for keys of your
own, so they never meet BullMQ’s or the kit’s.
Rate limits
Section titled “Rate limits”RateLimiter counts in Redis, so a limit holds however many copies of the API run:
const { allowed, retryAfter } = await this.limits.consume(`export:${workspace.id}`, { max: 10, window: 60,});if (!allowed) throw new HttpException(`Try again in ${retryAfter} seconds.`, 429);Better Auth’s limits on signing in go through it as well, in production, as they did in memory before: see Auth.
CacheService caches for one workspace at a time, so one workspace’s entries can never be read
through another’s:
const cache = this.cache.forWorkspace(workspace.id);const report = await cache.wrap('report:2026-10', 300, () => this.buildReport(workspace.id));await cache.delete('report:2026-10');Values are kept as JSON for the seconds you give. clear() forgets a workspace’s entries. The kit
caches nothing of its own: reach for it when something is slow and may be a little out of date.