# No in-memory data stores used as production databases

- **Pattern:** `ab-000256` (`ai-slop-half-finished.mock-responses.in-memory-prod-store`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000256
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000256)

## Why it matters

In-memory arrays as databases are the defining prototype artifact of AI-generated code. They work flawlessly in a single-process demo and fail completely the moment a second request hits a different process, the server restarts, or the platform auto-scales. Every write is silently discarded on restart — no error, no warning. Per CWE-1188 (Insecure Default Initialization), the defect is that the 'database' initializes to an empty slice of process memory rather than a durable store. Any data entered by real users — signups, orders, payments, messages — vanishes on the next deploy.

## Severity rationale

Critical because the data loss is total, silent, and guaranteed on every server restart, making the application functionally unusable for any production workload.

## Remediation

Replace the module-scope collection with a real database client. Even a local SQLite file persists across restarts. In `src/lib/users.ts` (or wherever the in-memory store lives), delete the array declaration and rewrite every read/write through Prisma, Drizzle, or your existing ORM:

```ts
// Remove this:
const users: User[] = []
export const addUser = (u: User) => users.push(u)
export const getUsers = () => users

// Replace with:
import { prisma } from '@/lib/db'
export const addUser = (u: User) => prisma.user.create({ data: u })
export const getUsers = () => prisma.user.findMany()
```

If you have no database yet, add `prisma` + `@prisma/client`, run `prisma init`, write a minimal schema for the collection, and `prisma migrate dev`.

## Detection

- **ID:** `in-memory-prod-store`
- **Severity:** `critical`
- **What to look for:** Count all module-scope variable declarations in non-test source files that match these patterns: `const X: Y[] = []`, `let X: Y[] = []`, `const X = new Map()`, `const X = new Set()`, `const X: Record<string, Y> = {}`, `let X: Record<string, Y> = {}` where X is a plural noun suggesting a data collection (`users`, `posts`, `items`, `products`, `orders`, `customers`, `sessions`, `todos`, `messages`, `tasks`, `events`, `bookings`, `comments`). For each match, check whether the declared collection is mutated (pushed to, assigned to, deleted from) by at least 1 function in the same module AND referenced/read from a function in a routing file OR a file with an API handler. Count all module-scope in-memory "databases" found.
- **Pass criteria:** 0 module-scope in-memory data stores are used as primary data sources by routing or API code. Report: "Scanned X module-scope collection declarations, 0 used as primary data stores."
- **Fail criteria:** At least 1 module-scope collection is mutated and queried as a primary data source, with no database client imports in the same file.
- **Do NOT pass when:** The in-memory store is protected by `if (process.env.NODE_ENV === 'test')` but is still reachable at module load time in production — module-scope execution always runs.
- **Skip (N/A) when:** Project has 0 non-test source files containing module-scope collection declarations.
- **Detail on fail:** `"2 in-memory data stores used as primary sources: 'const users: User[] = []' in src/lib/users.ts (pushed to in POST /api/users, read from GET /api/users). Will lose all data on every restart."`
- **Remediation:** In-memory arrays as databases are the canonical AI prototype — they look like state management but disappear on every server restart, fail on multi-instance deployments, and have zero persistence. Replace them with a real database:

  ```ts
  // Bad: src/lib/users.ts
  const users: User[] = []
  export const addUser = (u: User) => users.push(u)
  export const getUsers = () => users

  // Good: use a real database
  // src/lib/users.ts
  import { prisma } from '@/lib/db'
  export const addUser = (u: User) => prisma.user.create({ data: u })
  export const getUsers = () => prisma.user.findMany()
  ```

  Even SQLite is better than in-memory for production. Pick a database, write a schema, migrate the data access layer.

## External references

- cwe CWE-1188

Taxons: placeholder-hygiene, data-integrity

HTML version: https://auditbuffet.com/patterns/ab-000256
