Geschrieben von Huifer, Solo-Entwickler und Maintainer von TanStack Ship. Ich habe in den Jahren 2025–2026 drei Spreadsheet-to-SaaS-Konvertierungen ausgeliefert: ein Inventartool mit 47 Tabellenblättern, ein Pricing-Analyst-Tool mit 12.000 Zeilen und ein Tool zur Terminplanung in Kliniken, das eine Google Sheets-Übergabe zwischen vier Rezeptionisten ersetzte. Jede Migration folgte der gleichen 7-Phasen-Struktur und traf auf die gleichen drei Kompromisse. Dies ist das Playbook – Phase für Phase, mit dem Code, den ich auf TanStack Ship ausliefere, sowie den „Wann das hier kaputtgeht“-Notizen.
Verifizierte Quellen: Google Sheets API quotas · Microsoft Excel import limits · Stripe Billing metering · Better Auth · Cloudflare D1 limits · OWASP A01 Broken Access Control · TanStack Start · CSV RFC 4180
Zuletzt aktualisiert: 14. Mai 2026 · Changelog
Spreadsheet to SaaS: 7 Phasen und 3 ehrliche Kompromisse
TL;DR: Ich habe in den Jahren 2025–2026 3 Spreadsheet-to-SaaS-Migrationen ausgeliefert. Der Ablauf: Tabellenkalkulation inventarisieren, Schema (Data Model) auswählen, UX-Parität und anschließend UX-Verbesserungen ausliefern, Auth und Billing verdrahten, in Wellen migrieren, Kommunikation und Abschaltung, Messen. Die drei ehrlichen Kompromisse (Trade-offs): Liefergeschwindigkeit vs. UX-Parität, die 20–30 % der Nutzer, die nie konvertieren, und Edge Cases, die für immer in Formeln bleiben sollten. Die Phasen 0–3 dauern ein Wochenende; 4–6 dauern 2–3 Wochen; 7 währt ewig.
Wenn die Tabellenkalkulation nicht mehr skaliert (die ehrlichen Auslöser)
Die meisten Gründer warten zu lange. Bis die Tabellenkalkulation fünf Redakteure und eine Speicherverzögerung von 30 Sekunden aufweist, häuft sich die technische Schuld bereits an. Drei Auslöser, auf die Sie als Gründer achten sollten – keiner davon lautet „die Datei ist zu groß geworden“.
5 Arbeitsplätze bearbeiten dieselbe Datei
Ein Schreibwettbewerb in der Google Sheets API erzeugt bei 5 gleichzeitigen Redakteuren stille Überschreibungen. Das Signal: „Ich habe eine Zeile bearbeitet und zwei Minuten später wurde sie rückgängig gemacht.“ Ihre Datenschicht ist nicht mehr vertrauenswürdig.
Anforderungen an den Audit Trail
Tabellenkalkulationen haben kein Auditprotokoll. In dem Moment, in dem ein Kunde, Buchhalter oder eine Aufsichtsbehörde fragt: „Wer hat diese Zeile am 14. März geändert?“, benötigen Sie append-only Ereignisprotokolle mit Zeitstempeln und Akteur-IDs. Sehen Sie sich den SaaS authentication guide für das session-id Pattern an.
Zeilenanzahl pro Kunde > 5.000
Ab 5.000 Zeilen kommt es bei VLOOKUP zu Timeouts, Pivot-Tabellen kriechen nur noch dahin und Bearbeitungen werden verlustbehaftet. Das Pricing-Analyst-Tool mit 12.000 Zeilen benötigte 14 Sekunden für die Neuberechnung bei der Änderung einer einzigen Zelle. Cloudflare D1 mit einem typisierten Schema führt dieselben Abfragen im einstelligen Millisekundenbereich aus.
Phase 0: Inventarisieren Sie das Spreadsheet (was Sie tatsächlich ausliefern)
Die erste Phase wird von Gründern oft übersprungen. Sie sehen „Sheet1, Sheet2, Sheet3“ und gehen davon aus, dass die Migration unkompliziert ist. Sie ist niemals unkompliziert. Eine von mir migrierte Inventar-Datei mit 47 Tabellenblättern enthielt 11 Blätter, die seit 18 Monaten niemand mehr bearbeitet hatte.
Zellen, Formeln, benannte Bereiche
Auditieren Sie jedes Blatt, jeden benannten Bereich und jede Formel. Ich verwende ein Skript, das die Google Sheets API durchläuft und eine JSON-Zusammenfassung ausgibt: Blattname, letzte Bearbeitung, letzter Bearbeiter, Anzahl der Formeln, Anzahl externer Links. Diese Zusammenfassung ist die Single Source of Truth für alles, „was migriert wird“.
VBA / Apps Script / Sheets Makros
Versteckte Komplexität. Ein Pricing-Analyst-Tool mit 12.000 Zeilen enthielt 47 Apps Script-Trigger, die bei Zelländerungen ausgelöst wurden. Zählen Sie diese vor der Migration auf, oder Sie verbringen einen Monat damit, sie zu reproduzieren. Listen, klassifizieren und entscheiden Sie, was neu erstellt und was fallengelassen wird.
Externe Datenabrufe und Querys
IMPORTRANGE, IMPORTDATA, QUERY – jede Formel, die auf etwas außerhalb der Datei zugreift, ist eine versteckte Abhängigkeit. Der SaaS-Ersatz erfordert eine explizite Integration der Datenquelle und keinen Import innerhalb der Zelle.
Phase 1: Wählen Sie das Datenmodell vor dem Framework
Der häufigste Migrationsfehler besteht darin, zuerst zum Framework zu greifen. Wählen Sie immer zuerst das Datenmodell. Eine Tabellenkalkulation ist eine relationale Datenbank, die ihr Schema verloren hat; Ihre Aufgabe in Phase 1 besteht darin, das Schema wiederherzustellen.
Entitäten, keine Tabs
Ein Tab namens „Q3_inventory“ ist keine Entität. Die Entität ist Product, Warehouse, StockMovement. Bilden Sie jedes Blatt auf Entitäten ab; ordnen Sie jede Spalte einem typisierten Feld zu. Nutzen Sie das Schema als Importvertrag nach CSV RFC 4180, damit Sie es sauber reimportieren können, falls die Migration fehlschlägt.
Schema Validierung an der Edge
Validieren Sie an der Edge und nicht in der Datenbank. Eine Serverfunktion in TanStack Start validiert eine eingehende Zeile anhand eines Zod-Schemas in <2 ms und lehnt sie vor dem Schreiben ab. Dies erspart Ihnen das Bereinigen fehlerhafter Zeilen aus Cloudflare D1.
Migrationspfade: CSV / SQL-Dump / Live-Sync
Drei Optionen für den initialen Load: CSV-Export + Import, SQL-Dump aus Postgres-Staging oder ein Live-Sync über die Google Sheets API. Für <50.000 Zeilen ist CSV am schnellsten. Der Importer von TanStack Ship wird als einzelne Serverfunktion ausgeliefert:
// src/server/import/sheets-to-d1.ts
import { z } from "zod";
const ProductRow = z.object({
sku: z.string().min(1).max(64),
name: z.string().min(1).max(200),
warehouse_id: z.string().uuid(),
on_hand: z.number().int().min(0),
unit_cost_cents: z.number().int().min(0),
});
export type ProductRow = z.infer<typeof ProductRow>;
export async function importProducts(rows: unknown[], tenantId: string) {
const validated = z.array(ProductRow).parse(rows);
const stmt = db.prepare(
`INSERT INTO products (id, tenant_id, sku, name, warehouse_id, on_hand, unit_cost_cents, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, unixepoch())
ON CONFLICT (tenant_id, sku) DO UPDATE SET
name = excluded.name,
on_hand = excluded.on_hand,
unit_cost_cents = excluded.unit_cost_cents,
updated_at = excluded.updated_at`
);
const batch = validated.map((r) =>
stmt.bind(crypto.randomUUID(), tenantId, r.sku, r.name, r.warehouse_id, r.on_hand, r.unit_cost_cents)
);
await db.batch(batch);
return { imported: validated.length };
}
Die ON CONFLICT-Klausel bedeutet, dass die erneute Ausführung des Importvorgangs idempotent ist. Die tenant_id ist der multi-tenant boundary Anker – jede Zeile wird auf einen Workspace beschränkt.
Phase 2: UX-Parität, danach UX-Verbesserung
Widerstehen Sie dem Drang, zuerst die bessere Version auf den Markt zu bringen. Nutzer von Tabellenkalkulationen haben ein Muskelgedächtnis gebildet; die bessere Version führt zu Vertrauensverlust. Liefern Sie zuerst UX-Parität und integrieren Sie UX-Erfolge dann in 2-wöchigen Wellen.
Was Sie behalten
Spaltenanordnung, dieselben Feldnamen (benennen Sie diese später um), und Tastaturkürzel, falls möglich.
Was Sie streichen
Zellen, die seit 18 Monaten niemand bearbeitet hat (diese haben Sie in Phase 0 inventarisiert). Die „Notizen“-Spalte mit 6 verschiedenen Formaten. Summary-Tabs, die sich niemand angesehen hat.
Was Sie von Grund auf neu erstellen
Die Suchleiste – VLOOKUP ist eine Suchleiste mit schlechter Benutzeroberfläche. Den Filter – Pivot-Tabellen sind Filter mit schlechter UI. Das Audit-Protokoll – die Tabellenkalkulation hatte nie eines. Diese drei Neuentwicklungen rechtfertigen die Migration.
Phase 3: Auth, Billing und die „Pro-Kunde“-Falle
In Phase 3 sterben die meisten Migrationen. Wenn Sie hier Fehler machen, liefern Sie lediglich eine Demo aus.
Better Auth statt Clerk für Solo-SaaS
Für Solo-Entwickler, die ein SaaS aus einer Tabellenkalkulation heraus launchen, ist Better Auth die richtige Wahl im Vergleich zu Clerk. Es läuft auf Ihrem eigenen Stack, hat keine Pro-MAU-Preisgestaltung, die das Wachstum bestraft, und entspricht dem mentalen Modell der Tabellenkalkulation: „Ein Google-Konto pro Benutzer“. Verdrahten Sie es mit E-Mail + Google OAuth – das, was die Nutzer bereits haben.
// src/server/auth/config.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/server/db";
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "sqlite" }),
emailAndPassword: { enabled: true, requireEmailVerification: true },
socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET! } },
user: { additionalFields: { tenant_id: { type: "string", required: true } } },
});
Stripe Per-Seat vs. Pauschalpreis
Drei Optionen: pro Platz (für Kollaborationstools), Pauschalpreis (für Einzelpersonen oder kleine Teams) und nutzungsabhängige Abrechnung (wenn das Tabellenblatt eine Nutzungsspalte hatte). Für das von mir ausgelieferte Inventartool gewann die Flatrate von $29/Monat pro Lagerhaus, da es immer nur 2–3 Redakteure gab – ein Per-Seat Modell hätte ihre Rechnung verdoppelt, ohne den Mehrwert zu verändern. Die Stripe Billing metering Dokumentation deckt die API-Oberfläche ab; der SaaS pricing models guide erläutert, wann welches Modell gewinnt.
Steuern, Rechnungsstellung, Rückerstattungen
In Tabellenkalkulationen erfolgt die Rechnungsstellung in einer anderen Spalte. Im SaaS geschieht dies über Stripe. Die Stripe Tax Integration kümmert sich um US-Verkaufssteuern, EU-Mehrwertsteuer und UK-Mehrwertsteuer, ohne dass Sie eine einzige Codezeile schreiben müssen. Aktivieren Sie am besten direkt am ersten Tag das Stripe Customer Portal.
Phase 4: Migrieren Sie in Wellen, nicht als Big-Bang
Der Big-Bang-Ansatz ist die größte Fehlerquelle bei Migrationen. Was wie ein Wochenendprojekt aussieht, wird schnell zu einem sechswöchigen Feuer. Migrieren Sie in drei Wellen.
Welle 1: Read-only Mirror
Erstellen Sie einen schreibgeschützten Spiegel der Tabellenkalkulation im SaaS. Die Benutzer können lesen, aber nicht schreiben. Lassen Sie dies 7 Tage lang laufen. Finden Sie jede unerwartete Überraschung. Beheben Sie diese. Das TanStack Ship Template liefert einen One-Shot-CSV-Exporter für diese Welle mit:
// src/server/export/csv.ts
import { stringify } from "csv-stringify/sync";
import { db } from "@/server/db";
export async function exportProductsCSV(tenantId: string): Promise<string> {
const rows = await db
.prepare(`SELECT sku, name, on_hand, unit_cost_cents FROM products WHERE tenant_id = ? ORDER BY sku`)
.all(tenantId);
return stringify(rows, { header: true });
}
Die Funktion gibt eine saubere RFC 4180 CSV-Datei zurück, die direkt in Google Sheets als Welle-1-Spiegel abgelegt werden kann.
Welle 2: Dualables Schreiben mit Validierung
Betreiben Sie die Tabellenkalkulation UND das SaaS parallel. Jeder Schreibvorgang geht an beide Systeme, wobei das SaaS das Schema validiert. Lassen Sie diese Welle 14 Tage lang laufen. Vergleichen Sie die Zeilen allnächtlich; beheben Sie Abweichungen. Dies ist die längste Welle; planen Sie entsprechend dafür.
Welle 3: Cutover mit Rollback-Pfad
Führen Sie die finale Umschaltung zu einer bekannten, verkehrsarmen Zeit durch. Lassen Sie die Tabellenkalkulation sicherheitshalber 72 Stunden lang bearbeitbar, um einen Rollback-Pfad zu besitzen. Anschließend wird sie für 30 Tage auf Nur-Lese-Zustand umgestellt. Danach folgt die Archivierung. Die Seite Cloudflare D1 limits dokumentiert die Speicherobergrenzen, falls Sie die Archivierung vergessen.
Phase 5: Informieren Sie die Nutzer der Tabellenkalkulation, bevor Sie sie abschalten
Die meisten Gründer launchen das SaaS und vergessen die Menschen. Dann bearbeiten 30 % weiterhin die Tabellenkalkulation und Sie haben plötzlich zwei Quellen der Wahrheit.
Kommunikationsplan
Benachrichtigen Sie die Nutzer 30, 14, 7 und 1 Tag vor der Umschaltung per E-Mail. In jeder Mail steht: was sich ändert, was bleibt, wo Fragen gestellt werden können. Versenden Sie für kleinere Teams ein 5-minütiges Loom-Video pro Workflow.
Datum der Einstellung (Sunset Date)
Legen Sie ein festes Enddatum fest und geben Sie es bekannt. „Nach dem 14. Juni wird die Tabelle schreibgeschützt sein.“ Ohne ein Datum wird aus „bald“ ein „niemals“.
Ein Export-Endpoint für immer
Stellen Sie einen dauerhaften Export-Endpoint bereit, der es jedem Benutzer ermöglicht, seine Daten als CSV herunterzuladen. Für immer. Benutzer von Tabellenkalkulationen vertrauen ihren Daten, weil sie diese jederzeit mitnehmen können.
Phase 6: Messen Sie, was Sie tatsächlich ausgeliefert haben
Eine Migration ist nicht abgeschlossen, wenn das SaaS auf dem Markt ist – sie ist erst abgeschlossen, wenn die Tabellenkalkulation leer ist und Support-Tickets abnehmen.
30-Tage-Retention
Wie viel Prozent der Spreadsheet-Nutzer haben sich in Woche 1, Woche 2, Woche 4 eingeloggt? Ziel: ≥70 % in Woche 1, ≥80 % in Woche 4. Werte unter 70 % bedeuten, dass die Kommunikation gescheitert ist.
Gesparte Zeit pro Workflow
Stoppen Sie die Zeit für den volumenstärksten Workflow. Vorher: 14 Minuten pro Zyklus. Nachher: 4. Diese ROI-Zahl gehört auf die pricing page.
Support-Tickets pro Workflow
Jedes Support-Ticket in den ersten 30 Tagen zeigt eine UX-Lücke. Triage nach Häufigkeit; beheben Sie die Top drei vor Woche 4. Die Terminplanungs-Migration für die Klinik verzeichnete 18 Tickets in Woche 1, 4 in Woche 4.
Die 3 ehrlichen Kompromisse
Keine Spreadsheet-to-SaaS-Migration ist kostenlos. Die drei Trade-offs benenne ich direkt am ersten Tag. Es sind keine Bugs; sie sind Merkmale des Medienwechsels.
Kompromiss #1: Liefergeschwindigkeit
UX-Parität (Phase 2) kostet 2–3 Wochen, die Gründer lieber in die „bessere“ Version investieren wollen. Liefern Sie Parität, das Datenmodell und dann UX-Verbesserungen in Wellen. Das Pricing-Analyst-Tool mit 12.000 Zeilen benötigte 11 Wochen; ohne parity-first hätte es 16 Wochen in Anspruch genommen und den Kunden gekostet.
Kompromiss #2: Spreadsheet-Nutzer, die nie konvertieren
20–30 % der Spreadsheet-Nutzer werden sich nicht anmelden – nicht weil das SaaS schlecht ist, sondern weil die Tabelle ihnen gehörte, was das SaaS niemals tun wird. Für genau diese Nutzer ist der Export-Endpoint gedacht. Lassen Sie diese Gruppe nicht Ihre Retention-Metriken verankern.
Kompromiss #3: Edge Cases in Formeln für die Ewigkeit
Jede Tabellenkalkulation hat eine Formel, die einen Sonderfall (Edge Case) verarbeitet, den sonst niemand versteht. Das Inventartool besaß eine Zelle, die mittels einer Regression über 18 Monate hinweg kalkulierte: „Haben wir genug für den Weihnachts-Ansturm?“. Diese Formel ist nie in das SaaS übergegangen – sie lebt in einem Notion-Dokument und wird jeden November manuell ausgeführt. Manche Edge Cases sollten ewig in Formeln bleiben.
Wann man NICHT migrieren sollte
Die Migration ist falsch, wenn die Tabellenkalkulation eine dieser Aufgaben übernimmt:
- Eimalige Berechnungen — ein wöchentlicher Pricing Review, der ein PDF erzeugt. Das ist ein Skript, kein SaaS.
- Zwei-Personen-Übergaben — zwei Redakteure sind nicht ausreichend Skalierung.
- Compliance-by-Spreadsheet — wenn die Relevanz lautet: „Kein SaaS wird unser Audit bestehen“, dann besteht die Migration darin, ein konformes SaaS zu finden, nicht eines zu bauen.
Für fast alle anderen lautet die Empfehlung: Die sieben Phasen werden als typisiertes Template auf TanStack Ship ausgeliefert. Die pricing page ist ehrlich; die comparison page listet jedes Modul auf; der blog index enthält die Postmortems.
FAQ
Wie lange dauert die Migration?
Ein einzelnes Spreadsheet, <10 Tabellenblätter, <5.000 Zeilen: 3–4 Wochen. Größer (30+ Blätter, 10.000+ Zeilen): 8–12 Wochen. Die Varianz liegt fast vollständig in den Phasen 2 und 4.
Kann ich Google Sheets als Source of Truth behalten?
Das können Sie, aber Sie sollten es nicht tun. Sheets wird zu einem schreibgeschützten Spiegel oder CSV-Export. Zwei Wahrheitsquellen sind ein Fehler.
Was ist mit Notion / Airtable / Coda?
Das sind Tabellenkalkulationen in Verkleidung. Wenn Ihr Team Notion als Datenbank nutzt, ist das Ziel ein echtes SaaS mit einem typisierten Schema.
Brauche ich einen Mitgründer?
Nein. Alle drei Migrationen waren Solo-Projekte. Die Phasen sind sequenziell – parallele Workstreams sind nicht erforderlich.
Fazit
Die Form funktioniert. Inventarisierung, Datenmodell, UX-Parität und anschließend Verbesserungen, Auth + Billing, Wellen-Migration, Kommunikation + Sunset, Messen. Benennen Sie die Kompromisse lautstark. Die 20–30 %, die nie konvertieren, die Formeln, die niemals migrieren, die Kosten der Liefergeschwindigkeit – der Preis des Medienwechsels.
Bereit, Ihre Migration auszuliefern? TanStack Ship bringt einen typisierten Spreadsheet-Importer, Better Auth, Stripe Billing und 14 Produktionsmodule auf Cloudflare Workers mit. Die Live-Vorlage finden Sie unter pricing; die vollständige Modulliste unter compare – und browse the blog, um detaillierte Architekturleitfäden und Postmortems zu lesen, die jede dieser Phasen geprägt haben.