Start / Projekte / Buchungsplattform

Typeform, Calendly & Zapier durch eine einzige Buchungsplattform ersetzt

Ein selbst betriebenes System ersetzte drei wiederkehrende SaaS-Abos – Typeform, Calendly und Zapier – und verlagerte den gesamten Buchungs-Workflow in Google Workspace, an jedem Schritt anpassbar und von keinem externen Anbieter abhängig.

Status Im Produktivbetrieb · v3.2
Umfang~4,000 Buchungen / Monat
KerntechnologienGoogle Calendar API · Google Sheets API · Google Apps Script · TypeScript
01

Überblick

Ein Terminplanungssystem, mit dem ein verteiltes Serviceteam Buchungen über viele Behandler hinweg annehmen kann, ohne je doppelt zu buchen, eine Zeitzone falsch zu behandeln oder einen Termin bei einer Wiederholung zu duplizieren – mit Google Calendar als einziger Quelle der Wahrheit.

Was gebaut wurde

Eine Buchungsplattform, direkt auf Google Workspace aufgesetzt. Kunden wählen einen Slot aus berechneter Verfügbarkeit; die Plattform reserviert, verifiziert und bestätigt den Termin als eine einzige idempotente Transaktion, schreibt das Ereignis in den Google Calendar des Behandlers und benachrichtigt beide Seiten. Es gibt keine separate führende Datenbank – der Kalender, in dem das Team ohnehin lebt, bleibt maßgeblich.

Für wen es ist

Ein Dienstleistungsunternehmen mit mehreren Behandlern, jeder mit eigenen Arbeitszeiten, Puffern und Abwesenheiten, das Buchungen aus einem Webformular, per E-Mail und dem gelegentlichen, nachträglich eingetragenen Telefonanruf annimmt.

Geschäftlicher Kontext

Der manuelle Prozess, den es ersetzte, verlor durch Doppelbuchungen und Zeitzonenfehler rund einen Slot pro Woche – gering in der Zahl, teuer im Vertrauen. Aufgabe der Plattform war es, den Kalender maßgeblich und die Buchung sicher zu machen, ohne ein zweites System hinzuzufügen, das aus dem Takt geraten würde.

02

Architektur

Ein schlanker, zustandsloser Koordinator vor Google Calendar. Eine Buchung ist eine kurze, idempotente Transaktion – reservieren, verifizieren, bestätigen – geleitet durch eine Warteschlange pro Behandler, sodass das Rennen, das Doppelbuchungen verursacht, gar nicht erst auftreten kann.

ClientWebformular / E-Mail-Aufnahme
EdgeCloud Function – validieren + TZ normalisieren
WarteschlangeCloud Tasks – FIFO pro Behandler
↓ eine Buchung nach der anderen, pro Behandler ↓
Koordinatorreservieren → verifizieren → bestätigen
LedgerFirestore – Idempotenzschlüssel (TTL)
Quelle der WahrheitGoogle Calendar – freebusy + Ereignisse

Warum eine Warteschlange pro Behandler

Doppelbuchung ist ein Rennen zwischen nebenläufigen Schreibern um eine Ressource. Statt zu verteilten Sperren zu greifen, läuft jede Anfrage für einen bestimmten Behandler durch eine FIFO-Warteschlange mit einem einzigen Konsumenten – ein langweiliges, debugbares Primitiv, das das Rennen unmöglich macht, statt es nur behebbar. Die Nebenläufigkeit über Behandler hinweg bleibt hoch; innerhalb eines Behandlers fällt sie auf eins.

03

Komponenten

Die Plattform ist aus neun Komponenten aufgebaut. Jede ist als eigener Engineering-Abschnitt dokumentiert – warum sie existiert, ihre Architektur, die Einschränkungen und Randfälle, die sie behandelt, die eingegangenen Trade-offs und die finale Implementierung. Klappe eine beliebige auf, um sie zu lesen.

C1Mehrstufiger Buchungsablaufkundenseitig
Warum sie existiert
Verwandelt „eine Zeit finden“ in eine geführte, fortsetzbare Sequenz – Leistung → Behandler → Datum → Slot → Details → Bestätigung –, die nie einen Slot anbietet, den sie nicht einhalten kann.
Architektur
Ein zustandsloser Client, angetrieben von der Verfügbarkeits-Engine; jeder Schritt validiert erneut gegen live free/busy, sodass ein Slot, der sich mitten im Ablauf füllt, vor dem Absenden erkannt wird.
Einschränkungen
Muss aus einem Webformular, einem E-Mail-Link und einer manuell eingetippten Telefonbuchung funktionieren; kein Schritt darf sich auf die Geräteuhr des Clients verlassen.
Randfälle
Slot zwischen Anzeige und Absenden vergeben; erneutes Absenden per Zurück-Button; ein Behandler, der mitten in der Sitzung in den Urlaub geht.
Trade-offs
Das erneute Validieren jedes Schritts kostet einen zusätzlichen free/busy-Read, beseitigt aber den Fehler „der gewählte Slot ist weg“ beim Bestätigen.
C2Verfügbarkeits-EngineRead-Modell
Warum sie existiert
Berechnet buchbare Fenster pro Behandler aus Arbeitszeiten, Puffern, bestehenden Ereignissen und Abwesenheiten – das Read-Modell, aus dem der gesamte Ablauf gerendert wird.
Architektur
Berechnet Fenster planmäßig und bei Kalenderänderungs-Webhooks vor und cacht sie in Firestore; der Ablauf liest auf dem heißen Pfad den Cache, nicht die Calendar API.
Einschränkungen
Muss korrekt bleiben, während Behandler ihre eigenen Kalender direkt bearbeiten; darf unter Last das Calendar-Read-Kontingent nicht überschreiten.
Randfälle
Überlappende Ereignisse, ganztägige Blockaden, wiederkehrende Sperren und DST-Grenzen, an denen ein „9 Uhr“-Fenster sich verschiebt.
Trade-offs
Eine kurze Cache-TTL tauscht ein paar Sekunden Veraltung gegen einen großen Rückgang an API-Aufrufen; der Bestätigungsschritt ist die Autorität, daher ist kurze Veraltung sicher.
C3Buchungs-API (reservieren · verifizieren · bestätigen)Kern
Warum sie existiert
Der transaktionale Kern: verwandelt eine Anfrage in genau ein Kalenderereignis, sicher, selbst unter Nebenläufigkeit und Wiederholungen.
Architektur
Jede Anfrage für einen Behandler läuft durch dessen FIFO-Warteschlange mit einem einzigen Konsumenten; confirm() prüft free/busy innerhalb dieses Fensters und schreibt mit einem inhaltsadressierten Idempotenzschlüssel.
API-Vertrag
POST /booking  → 201 {eventId}  | 409 SlotTaken
// idempotent: same intent ⇒ same eventId
key = sha256(practitionerId, startUTC, clientId)
Randfälle
Nebenläufige Anfragen für einen Slot (wegserialisiert); Formular-/Netzwerk-Wiederholungen (durch das Ledger auf ein Ereignis zusammengefasst); Teilausfall nach dem Einfügen (der Ledger-Commit macht es wiederholsicher).
Trade-offs
Serialisierung pro Behandler fügt ein paar ms Latenz hinzu und entfernt das Rennen konstruktionsbedingt – gewählt statt verteilter Sperren.
C4Google-Calendar-IntegrationWorkspace
Warum sie existiert
Hält Google Calendar als Quelle der Wahrheit – liest free/busy und schreibt Ereignisse – sodass das Team nie das Werkzeug verlässt, das es ohnehin nutzt.
Architektur
Nutzt die aggregierte freebusy-Abfrage für die Verfügbarkeit (keine Ereignisdetails) und events.insert für Schreibvorgänge und versieht jedes Ereignis in privaten erweiterten Eigenschaften mit seinem Buchungsschlüssel.
Einschränkungen
Read-Kontingente pro Minute; Least-Privilege-Scopes; muss überstehen, dass Behandler Ereignisse von Hand bearbeiten.
Randfälle
Manuell gelöschte Ereignisse, externe Kalenderfreigaben und Abgleich, wenn Kalender und Ledger nicht übereinstimmen.
C5Zeitzonen-HandhabungKorrektheit
Warum sie existiert
Garantiert, dass ein Slot für Kunde, Behandler und Server über Sommerzeitwechsel hinweg denselben Zeitpunkt bedeutet.
Architektur
Speichert den Zeitpunkt in UTC und die vom Nutzer beabsichtigte IANA-Zone als separates Feld; die beiden werden erst beim Rendern wieder kombiniert.
Randfälle
Lücken bei Vor-/Zurückstellung, Zonen, die DST an unterschiedlichen Daten beachten, und Kunden, die nach der Buchung ihre Gerätezone ändern.
Trade-offs
Eine explizite Zone mitzuführen ist mehr zu speichern als ein bloßer Zeitstempel, aber es ist der einzige Weg, das Versprechen „9 Uhr in Lissabon“ zu wahren.
C6Authentifizierung & BerechtigungenSicherheit
Warum sie existiert
Lässt die Plattform mit der geringsten Autorität, die ein Sicherheitsteam abnimmt, auf den Kalendern der Domäne agieren.
Architektur
Ein dedizierter Service-Account mit eng gefasster domänenweiter Delegation; jeder Account lässt sich zu einem Eigentümer und einem Entscheidungsrecord zurückverfolgen.
Einschränkungen
Keine breiten Scopes; Schlüssel planmäßig rotiert; Zugriff auf einem Kalender geprüft, nicht aus dem Gedächtnis.
Trade-offs
Least-Privilege bedeutet mehr Konfiguration vorab im Austausch für ein Modell, das die Prüfung ohne Ausnahmen besteht.
C7BenachrichtigungenZustellung
Warum sie existiert
Bestätigt, erinnert und storniert für Kunde und Behandler, ohne je zweimal zu senden.
Architektur
At-least-once-Zustellung über Cloud Tasks mit Idempotenzschlüsseln und einer Dead-Letter-Queue, sodass eine Wiederholung nie doppelt sendet.
Randfälle
Provider-Drosselung, unzustellbare Adressen und eine Buchung, die storniert wird, bevor ihre Erinnerung ausgelöst wird.
C8Google-Meet-ErzeugungWorkspace
Warum sie existiert
Hängt an jede Remote-Buchung im Moment der Ereigniserstellung einen funktionierenden Videolink an.
Architektur
Fordert Konferenzdaten bei events.insert an, sodass der Meet-Link Teil desselben atomaren Schreibvorgangs wie die Buchung ist.
Randfälle
Fehler bei der Konferenzerstellung (die Buchung muss trotzdem gelingen) und verschobene Ereignisse, die ihren Link behalten.
C9Google-Sheets-ReportingOps
Warum sie existiert
Gibt dem Betreiber eine vertraute, live aktualisierte Ansicht von Buchungen und Auslastung ohne ein maßgeschneidertes Dashboard.
Architektur
Append-only-Synchronisierung vom Ledger in ein Sheet, behandelt als Read-Replika – nie als Quelle der Wahrheit.
Trade-offs
Ein Sheet ist begrenzt und leicht verzögert, aber es ist für einen Nicht-Techniker sofort lesbar, und darum geht es.
04

Visuelles Ergebnis

Was das System für Kunde und Betreiber tatsächlich produziert. Dies sind Exponate aus dem laufenden System – jedes beschriftet und mit der Komponente verlinkt, die es erzeugt. Setze die echten Screenshots in die Rahmen ein.

Der Buchungsablauf

Die dreistufige Kundenreise: Leistung & Zeit → Kontaktdaten → Datum und Uhrzeit → Bestätigung. Jeder Schritt validiert erneut gegen die Live-Verfügbarkeit.

Der Buchungsablauf

Echter Screenshot aus dem laufenden SystemKomponente: Mehrstufiger Buchungsablauf

Der Lead-Datensatz

Wo die Antworten des Kontaktschritts landen: eine an das Google Sheet angehängte Zeile – Name, Firma, geschäftliche E-Mail, Quelle und Zeitstempel der Einreichung. Anonymisierte oder Beispieldaten verwenden.

Der Lead-Datensatz

Echter Screenshot · Beispiel- / anonymisierte DatenKomponente: Google-Sheets-Reporting

Kalenderereignis erstellt

Die Buchungs-API schreibt direkt in den Google Calendar des Behandlers – Titel, Zeit, Zeitzone, beide Teilnehmer, ein Google-Meet-Link und der Aufnahmekontext in der Beschreibung. Beleg, dass das System ein natives Kalender-Artefakt erzeugt, keine private Datenbankzeile.

Kalenderereignis erstellt

Komponente: Buchungs-API · Calendar-Integration

Kundeneinladung & -bestätigung

Was der Kunde erhält – die Google-Calendar-Einladung und -Bestätigung, mit Meeting-Details und dem Meet-Link.

Kundeneinladung & -bestätigung

Echter Screenshot · Empfängerdaten schwärzenKomponente: Benachrichtigungen · Google-Meet-Erzeugung

Interne Benachrichtigung

Was das Team sieht, wenn eine Buchung eintrifft – die interne Benachrichtigung mit dem erfassten Qualifizierungskontext und dem Quell-Workflow.

Echter Screenshot – interne Buchungsbenachrichtigung

Echter Screenshot · anonymisiertKomponente: Benachrichtigungen

Fehler & Wiederherstellung

Die Zustände, die Produktivdenken beweisen: ein zwischen Anzeige und Absenden vergebener Slot und die erfolgreiche Wiederholung, die folgt. Links: Konflikt. Rechts: Wiederherstellung.

Echter Screenshot – Slot-vergeben- / Konfliktzustand
Echter Screenshot – erfolgreiche Wiederholung / Wiederherstellung

Komponente: Buchungs-API (Verfügbarkeit & Nebenläufigkeit)

05

Wirkung

Objektive Ergebnisse, die aus dem Produktivbetrieb der Plattform hervorgingen – Belege, keine Werbung.

Geschäft
  • Ersetzte einen Scheduling-Stack aus Calendly plus Zapier durch ein einziges selbst betriebenes System.
  • Beseitigte die wiederkehrenden Drittanbieter-Abokosten und den Kleber, der die Werkzeuge verband.
Kunde
  • Sofortige, zuverlässige Bestätigung im Moment der Buchung.
  • Weniger Terminplanungsfehler – kein angebotener Slot, der nicht eingehalten werden kann.
Betrieb
  • Doppelbuchungen beseitigt.
  • Zeitzonen-Handhabung durchgängig automatisiert.
  • Manuelle Kalendereinträge aus dem Alltag des Teams entfernt.
Engineering
  • Eine einzige Quelle der Wahrheit – keine parallele Buchungsdatenbank, die aus dem Takt gerät.
  • Wiederholsichere, idempotente Schreibvorgänge; weniger bewegliche Teile im Betrieb.
Umfang
  • ~4,000 Buchungen / Monat.
  • Null Doppelbuchungen, seit die v2-Serialisierung live ging.
06

Technische Dokumente

Chronologische Engineering-Records, geschrieben während des Baus der Plattform – die Entscheidungen, Sackgassen und Vorfälle, wie sie geschahen. Neueste zuerst.

07

Fallstudie

Eine Retrospektive auf die Plattform aus geschäftlicher Sicht – warum sie existiert, der gewählte Ansatz und wie es ausging.

Problem
Ein Serviceteam führte seinen Kalender von Hand und verlor durch Doppelbuchungen und Zeitzonenfehler etwa einen Slot pro Woche – billig zu zählen, teuer im Kundenvertrauen.
Ziel
Den Kalender maßgeblich und die Buchung sicher machen, von einer Person betreibbar, ohne ein zweites System of Record.
Einschränkungen
Google Calendar bleibt die Quelle der Wahrheit; Least-Privilege-Sicherheit; korrekt unter Nebenläufigkeit und Wiederholungen; innerhalb der Calendar-API-Kontingente.
Ansatz
Ein schlanker, zustandsloser Koordinator vor der Calendar API; Serialisierung pro Behandler, um das Rennen zu entfernen; inhaltsadressierte Idempotenz, um Duplikate zu entfernen; UTC-plus-Absicht für die Zeit.
Architektur
Aufnahme → Edge-Validierung → FIFO-Warteschlange pro Behandler → reservieren/verifizieren/bestätigen-Koordinator → Google Calendar, mit einem kleinen Idempotenz-Ledger. Keine parallele Buchungsdatenbank.
Trade-offs
Eine langweilige, beweisbar korrekte Warteschlange statt verteilter Sperren gewählt; Sekunden an Verfügbarkeits-Veraltung für eine große Kontingent-Ersparnis akzeptiert; den Zustand in der Plattform belassen, die ihn ohnehin besitzt.
Ergebnis
Im Produktivbetrieb seit Feb 2024, ~4,000 Buchungen/Monat, null Doppelbuchungen seit die v2-Serialisierung live ging; „ist meine Buchung durchgegangen?“ wurde zum Nicht-Ereignis, weil Wiederholungen sicher sind.
Lektionen
  • Serialisiere die umkämpfte Ressource; sperre nicht die ganze Welt.
  • Idempotenz ist ein Feature, keine Absicherung.
  • Lass die Plattform den Zustand behalten, den sie ohnehin besitzt.
Zukunft
Ein Self-Service-Umbuchungsablauf und das Verlagern der TTL-Aufräumung des Ledgers von Cron auf Dokumentablauf.
← Alle Projekte