SnapOtter verwendet PostgreSQL 17 mit [Drizzle ORM](https://orm.drizzle.team/) (pg-core / node-postgres) für die Datenpersistenz. Das Schema ist in `apps/api/src/db/schema.ts` definiert.
Die Verbindung wird über die Umgebungsvariable `DATABASE_URL` konfiguriert (Standard `postgres://snapotter:snapotter@postgres:5432/snapotter`). In Docker Compose speichert der Postgres-Container seine Daten im benannten Volume `SnapOtter-pgdata`.
## Tabellen {#tables}
### users {#users}
Speichert Benutzerkonten. Wird beim ersten Start automatisch aus `DEFAULT_USERNAME` und `DEFAULT_PASSWORD` erstellt.
Persistente Dateibibliothek. Ein gespeicherter Edit wird standardmäßig als eigenständige Root-Zeile eingefügt ("Als neu speichern": `version` 1, `parentId` null, sodass das Original weiterhin gelistet bleibt), oder als übergeordnet verknüpfte Version, wenn du das Original überschreibst (`parentId` gesetzt, `version` erhöht, das Original wird abgelöst). Die Spalte `toolChain` erfasst die angewendeten Werkzeuge.
Oberflächenzustand pro Benutzer, abgelegt unter einem Präferenznamen. Speichert die angehefteten Tools der Startseite, die über `PUT /api/v1/preferences` geschrieben werden.
| Spalte | Typ | Hinweise |
|---|---|---|
| `userId` | text | FK auf users, kaskadierendes Löschen. Zusammen mit `key` der Primärschlüssel |
| `key` | text | Name der Präferenz. Zusammen mit `userId` der Primärschlüssel |
| `value` | jsonb | Inhalt der Präferenz |
| `updatedAt` | timestamp | Zeitpunkt des letzten Schreibvorgangs |
Dieser Datenbank-Dump enthält keine gespeicherten Bibliotheksobjekte im `/data/files`- oder dauerhaften BullMQ-Status in Redis. Sichern und wiederherstellen Sie diese mit dem koordinierten Verfahren in [Sicherheit und Härtung](/de/guide/security#backup-and-recovery).
Kopieren Sie kein Live-PostgreSQL-Datenverzeichnis mit `tar`. Verfassen Sie Volume-Namen mit Präfixen nach Projekt. Lösen Sie daher die gemounteten Volume-IDs von `docker inspect` oder Ihrer Speicherplattform auf, anstatt die wörtliche Bezeichnung `SnapOtter-pgdata` anzunehmen.
### Migration von 1.x (SQLite) {#migrating-from-1-x-sqlite}
Das Upgrade von SnapOtter 1.x hat einen eigenen Leitfaden: siehe [Upgrade von 1.x auf 2.0](./upgrading). Kurz gesagt: Verwende dein bestehendes Volume `/data` weiter, und 2.0 erkennt und importiert `/data/snapotter.db` beim ersten Start automatisch (oder setze `SQLITE_MIGRATE_PATH`, um explizit darauf zu verweisen). Sichere zuerst das gesamte Volume `/data`, nicht nur `snapotter.db`: 1.x nutzt den SQLite-WAL-Modus, sodass ein gestoppter Container einen Großteil seiner Daten oft in `snapotter.db-wal` neben einer fast leeren `snapotter.db` ablegt.