---
title: "Storage Overview"
url: "https://effect-auth.itsbroly.com/storage/"
description: "Choose a database and connect it to effect-auth."
---



Storage is the durable security state behind effect-auth: users, credentials, sessions, verification challenges, OAuth records, passkeys, recovery codes, revocations, and other records required by enabled features. Start by choosing the **database** that fits your runtime and operational needs; then choose how to connect it.

## The three layers [#the-three-layers]

* **Database / storage** is where records live and how they are queried, transacted, backed up, and recovered. Your application owns this infrastructure.
* **Adapter** is the implementation that translates effect-auth operations into database reads and writes. The maintained implementation targets SQLite.
* **Contracts** are the public Effect services such as `UserStore`, `CredentialStore`, `SessionStore`, and `VerificationStore`. They define required behavior independently of any database.

```text
effect-auth features
        |
        v
 public store contracts
        |
        v
 adapter implementation
        |
        v
   your database
```

The distinction matters: selecting SQLite chooses the persistence model, while selecting an Effect-QB executor or a Drizzle bridge chooses the route to the same maintained SQLite store implementation.

## Choose your database [#choose-your-database]

| Database choice                              | Choose it when                                                                  | Integration path                                                                                                |
| -------------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| [Cloudflare D1](/storage/cloudflare-d1/)     | Auth runs on Cloudflare Workers and D1 should hold its state                    | Use the maintained SQLite stores with the D1 binding and executor                                               |
| [SQLite](/storage/sqlite/)                   | You use SQLite on another supported runtime or already have a SQLite connection | Reach the maintained stores directly through an Effect-QB executor, or through the Drizzle Effect SQLite bridge |
| [Custom Database](/storage/custom-database/) | You need a different database, an existing schema, or specialized persistence   | Implement every required public store contract and test its semantics against the real backend                  |

PostgreSQL and MySQL are not currently maintained storage integrations. They can only be used by building a custom database adapter that satisfies the contracts.

## Maintained SQLite paths [#maintained-sqlite-paths]

The maintained store logic is shared rather than duplicated:

```text
SQLite database
   ^                         ^
   | Effect-QB executor      | Drizzle Effect SQLite bridge
   +----------- maintained SQLite stores -----------+
```

Use the direct executor path when effect-auth can receive an Effect-QB SQLite executor. Use the bridge when your application already owns a Drizzle Effect SQLite database and wants to reuse that connection. In both cases, effect-auth supplies the same store behavior; Drizzle does not replace the contracts or schema ownership.

## Contract correctness [#contract-correctness]

A custom adapter must preserve behavior, not merely match TypeScript signatures. That includes missing-record `Option` results, typed failures, uniqueness, expiry and revocation filters, ordering, one-time consumption, and concurrency-safe state transitions. Operations described as a single transition must remain atomic in the chosen database. Run equivalent contract and concurrency tests against the production backend.

## Migrations and operations [#migrations-and-operations]

Your application owns migrations, backups, retention, replication, and recovery. For maintained SQLite stores, apply the ordered, append-only migrations exported by `@effect-auth/core/StorageMigrations` before serving dependent code, and record completed migration IDs in your migration ledger. effect-auth provides migration definitions, but does not run them automatically. Custom databases may use their own schema and migration system as long as every enabled contract remains valid.

Continue with [Cloudflare D1](/storage/cloudflare-d1/), [SQLite](/storage/sqlite/), or [Custom Database](/storage/custom-database/).

