System Logs

TX-7CB5 // projects

Access → Postgres, ohne dass jemand was merkt

Wie ein 70'000-Adressen-Bestand und 20'000+ Reservationen vom Access-Formular auf eine Nuxt-Postgres-App umgezogen sind — und welche Features dabei bewusst auf der Strecke geblieben sind.

2026.04.15/// 3 min read
> sys.log | category: projects | tags: Postgres / Nuxt / Migration / Blindekuh
Table of contents

Beim Reservationstool für die Blindekuh-Restaurants war die Ausgangslage simpel: eine Access-Datenbank, die seit Jahren tut, bis sie nicht mehr tut. Reservationen liessen sich nicht mehr sauber löschen, das Frontend wurde unbenutzbar, der Adressbestand zu gross.

Die Migration ging nicht primär um Technik — sondern um die Frage, was übernommen wird und was nicht.

Die Access-Falle

Access ist als Tool für genau einen Use-Case grossartig: ein Mensch, ein File, ein Formular. Sobald über Jahre Features dazukommen, wird die Datenbank zur Logik-Sammlung — und die Logik liegt in den Formularen, nicht im Schema. Wer migriert, migriert nicht eine DB, sondern ein über Jahre gewachsenes Verhalten.

Jedes Feature musste einzeln nachvollzogen werden:

  • Welche Felder werden wirklich gebraucht?
  • Welche Workflows sind aktiv, welche nur historisch?
  • Welche „Spezialfälle" sind echte Spezialfälle und welche bloss Workarounds für Access-Limits?

Ergebnis: einiges flog raus. Nicht aus Faulheit, sondern weil es sonst die alte Komplexität auf neuer Plattform reproduziert hätte.

Mandanten als Modellierungsentscheid

Basel und Zürich gehören zur gleichen Organisation, arbeiten aber operativ getrennt. Im Access-Setup war das mit doppelten Files / doppelter Pflege gelöst.

Im neuen Modell sind beide Standorte eigene Mandanten — getrennte Reservationen, getrennte Tische, getrennte Veranstaltungen. Stammdaten wie Adressen können geteilt werden, müssen aber nicht. Kein generisches Multi-Tenancy-Framework, sondern ein Schema, das genau diesen einen Fall sauber abbildet.

70'000 Adressen, davon viele Karteileichen

Der Adressbestand war der unangenehmste Teil. Viele Einträge alt, viele doppelt, einige unvollständig. Migration heisst hier:

  • Mapping von Access-Spalten auf das neue Schema
  • Deduplizierung wo eindeutig (gleiche E-Mail, gleicher Name, gleiche Adresse)
  • Markierung wo nicht eindeutig — der Restaurant-Betrieb entscheidet manuell
  • Keine automatische Löschung, keine Bereinigung im Migrations-Skript

Lieber 70'000 Adressen mit Quality-Flags als 40'000 Adressen, von denen 5'000 ungerechtfertigt rausgeflogen sind.

Stack: bewusst klein

Nuxt 3, Postgres, Tailwind, Docker. Mehr nicht. Kein ORM-Mega-Setup, keine separate Admin-UI, keine ausgelagerte Job-Queue.

Der Use-Case rechtfertigt das nicht. Reservationen sind Lese-/Schreib-Operationen auf überschaubarem Volumen — was zählt, ist Zuverlässigkeit, nicht horizontale Skalierung.

Was übrig bleibt

  • Reservationen müssen nicht mehr gelöscht werden, weil das System dafür nicht mehr zu klein wird
  • ~20'000 Reservationen seit Go-Live ohne Drama
  • Beide Standorte produktiv im täglichen Betrieb

Die wichtigste Lektion: Eine Migration ist nicht erfolgreich, wenn die neue Plattform alle alten Features hat. Sie ist erfolgreich, wenn die neue Plattform nur die Features hat, die wirklich gebraucht werden — und die laufen.

signal routing // hardware patchbay

Linked Transmissions

signal.tags
PostgresNuxtMigrationBlindekuh
tx.next_sequence

standalone transmission

related.ports
01 linked