Panoramica
Un sistema di pianificazione che consente a un team di servizi distribuito di accettare prenotazioni su molti professionisti senza mai prenotare due volte, gestire male un fuso orario o duplicare un appuntamento su una ripetizione, con Google Calendar come unica fonte di verità.
Cosa è stato costruito
Una piattaforma di prenotazione posata direttamente su Google Workspace. I clienti scelgono uno slot dalla disponibilità calcolata; la piattaforma riserva, verifica e conferma l'appuntamento come un'unica transazione idempotente, scrivendo l'evento sul Google Calendar del professionista e notificando entrambe le parti. Non esiste un database di riferimento separato: il calendario in cui il team già vive resta autoritativo.
A chi è rivolto
Un'attività di servizi che gestisce diversi professionisti, ciascuno con i propri orari di lavoro, margini e periodi di assenza, che accetta prenotazioni da un modulo web, dall'email e dall'occasionale telefonata inserita a posteriori.
Contesto aziendale
Il processo manuale che ha sostituito perdeva all'incirca uno slot a settimana per doppie prenotazioni e slittamenti di fuso orario: pochi in numero, costosi in fiducia. Il compito della piattaforma era rendere il calendario autoritativo e la prenotazione sicura, senza aggiungere un secondo sistema che sarebbe finito fuori sincrono.
Architettura
Un coordinatore sottile e senza stato davanti a Google Calendar. Una prenotazione è una transazione breve e idempotente — riserva, verifica, conferma — instradata attraverso una coda per singolo professionista, così che la corsa che causa la doppia prenotazione non possa verificarsi.
Perché una coda per professionista
La doppia prenotazione è una corsa tra scrittori concorrenti per una singola risorsa. Anziché ricorrere a lock distribuiti, ogni richiesta per un dato professionista passa attraverso un'unica coda FIFO a consumatore singolo — una primitiva noiosa e debuggabile che rende la corsa impossibile invece che semplicemente recuperabile. La concorrenza tra professionisti resta alta; all'interno di un singolo professionista scende a uno.
Componenti
La piattaforma è costruita da nove componenti. Ognuno è documentato come una propria sezione ingegneristica — perché esiste, la sua architettura, i vincoli e i casi limite che gestisce, i compromessi presi e l'implementazione finale. Espandi uno qualsiasi per leggerlo.
›C1Flusso di prenotazione a più passaggi
- Perché esiste
- Trasforma il "trova un orario" in una sequenza guidata e riprendibile — servizio → professionista → data → slot → dettagli → conferma — che non presenta mai uno slot che non può onorare.
- Architettura
- Un client senza stato pilotato dal motore di disponibilità; ogni passaggio ri-valida rispetto al free/busy in tempo reale, così che uno slot che si riempie a metà flusso venga intercettato prima dell'invio.
- Vincoli
- Deve funzionare da un modulo web, da un link email e da una prenotazione telefonica inserita a mano; nessun passaggio può basarsi sull'orologio del dispositivo del client.
- Casi limite
- Slot occupato tra la visualizzazione e l'invio; re-invio col pulsante indietro; un professionista che va in ferie a metà sessione.
- Compromessi
- Ri-validare ogni passaggio costa una lettura free/busy in più ma elimina il guasto "lo slot che hai scelto non c'è più" alla conferma.
›C2Motore di disponibilità
- Perché esiste
- Calcola le finestre prenotabili per professionista a partire da orari di lavoro, margini, eventi esistenti e assenze — il read model da cui l'intero flusso viene renderizzato.
- Architettura
- Precalcola le finestre a intervalli programmati e sui webhook di modifica del calendario, memorizzandole in cache su Firestore; il flusso legge la cache, non la Calendar API, sul percorso caldo.
- Vincoli
- Deve restare corretto mentre i professionisti modificano direttamente i propri calendari; non deve superare la quota di lettura di Calendar sotto carico.
- Casi limite
- Eventi sovrapposti, blocchi per l'intera giornata, appuntamenti ricorrenti e limiti DST in cui una finestra delle "ore 9" si sposta.
- Compromessi
- Un TTL di cache breve baratta qualche secondo di obsolescenza con un forte calo delle chiamate API; il passaggio di conferma è l'autorità, quindi una breve obsolescenza è sicura.
›C3API di prenotazione (riserva · verifica · conferma)
- Perché esiste
- Il nucleo transazionale: trasforma una richiesta in esattamente un evento di calendario, in sicurezza, anche sotto concorrenza e ripetizioni.
- Architettura
- Ogni richiesta per un professionista passa attraverso la coda FIFO a consumatore singolo di quel professionista;
confirm()controlla il free/busy dentro quella finestra e scrive con una chiave di idempotenza indirizzata al contenuto. - Contratto API
POST /booking → 201 {eventId} | 409 SlotTaken // idempotent: same intent ⇒ same eventId key = sha256(practitionerId, startUTC, clientId)
- Casi limite
- Richieste concorrenti per un singolo slot (serializzate via); ripetizioni di modulo/rete (collassate a un singolo evento tramite il registro); guasto parziale dopo l'inserimento (il commit del registro lo rende sicuro alla riesecuzione).
- Compromessi
- La serializzazione per singolo professionista aggiunge qualche ms di latenza e rimuove la corsa per costruzione — scelta al posto dei lock distribuiti.
›C4Integrazione con Google Calendar
- Perché esiste
- Mantiene Google Calendar come fonte di verità — leggendo il free/busy e scrivendo gli eventi — così che il team non lasci mai lo strumento che già usa.
- Architettura
- Usa la query aggregata
freebusyper la disponibilità (nessun dettaglio dell'evento) eevents.insertper le scritture, marcando ogni evento con la sua chiave di prenotazione in proprietà estese private. - Vincoli
- Quote di lettura al minuto; scope a privilegio minimo; deve sopravvivere ai professionisti che modificano gli eventi a mano.
- Casi limite
- Eventi cancellati manualmente, condivisioni di calendari esterni e riconciliazione quando il calendario e il registro non concordano.
›C5Gestione dei fusi orari
- Perché esiste
- Garantisce che uno slot significhi lo stesso istante per client, professionista e server attraverso i cambi dell'ora legale.
- Architettura
- Memorizza l'istante in UTC e la zona IANA voluta dall'utente come campo separato; i due si ricombinano solo al momento del rendering.
- Casi limite
- Salti di primavera/autunno, zone che osservano l'ora legale in date diverse e client che cambiano la zona del proprio dispositivo dopo la prenotazione.
- Compromessi
- Portarsi dietro una zona esplicita è più da memorizzare di un semplice timestamp, ma è l'unico modo per preservare la promessa "ore 9 a Lisbona."
›C6Autenticazione e autorizzazioni
- Perché esiste
- Permette alla piattaforma di agire sui calendari del dominio con la minima autorità che un team di sicurezza approverà.
- Architettura
- Un service account dedicato con delega a livello di dominio strettamente circoscritta; ogni account risale a un proprietario e a un record di decisione.
- Vincoli
- Nessuno scope ampio; chiavi ruotate a intervalli programmati; accesso rivisto su calendario, non a memoria.
- Compromessi
- Il privilegio minimo comporta più configurazione a monte in cambio di un modello che supera la revisione senza eccezioni.
›C7Notifiche
- Perché esiste
- Conferma, ricorda e annulla sia per il client sia per il professionista senza mai inviare due volte.
- Architettura
- Consegna almeno-una-volta tramite Cloud Tasks con chiavi di idempotenza e una dead-letter queue, così che una ripetizione non invii mai due volte.
- Casi limite
- Throttling del provider, indirizzi rimbalzati e una prenotazione annullata prima che scatti il suo promemoria.
›C8Generazione di Google Meet
- Perché esiste
- Allega un link video funzionante a ogni prenotazione da remoto nel momento in cui l'evento viene creato.
- Architettura
- Richiede i dati della conferenza su
events.insertcosì che il link Meet faccia parte della stessa scrittura atomica della prenotazione. - Casi limite
- Guasti nella creazione della conferenza (la prenotazione deve comunque riuscire) ed eventi riprogrammati che mantengono il loro link.
›C9Reportistica su Google Sheets
- Perché esiste
- Dà all'operatore una vista familiare e in tempo reale di prenotazioni e carico senza una dashboard su misura.
- Architettura
- Sincronizzazione in sola aggiunta dal registro verso un Sheet, trattato come una replica di lettura — mai una fonte di verità.
- Compromessi
- Uno Sheet è limitato e leggermente in ritardo, ma è immediatamente leggibile da un non-ingegnere, che è il punto.
Output visivo
Ciò che il sistema produce davvero per il cliente e per l'operatore. Questi sono reperti dal sistema in esecuzione, ciascuno con didascalia e collegato in modo incrociato al componente che lo crea. Inserisci gli screenshot reali nei riquadri.
Il flusso di prenotazione
Il percorso del cliente in tre passaggi: servizio e tempistica → dati di contatto → data e ora → conferma. Ogni passaggio ri-valida rispetto alla disponibilità in tempo reale.

Screenshot reale dal sistema in esecuzioneComponente: flusso di prenotazione a più passaggi
Il record del lead
Dove atterrano le risposte del passaggio di contatto: una riga aggiunta al Google Sheet — nome, azienda, email di lavoro, sorgente e timestamp di invio. Usa dati anonimizzati o di esempio.

Screenshot reale · dati di esempio / anonimizzatiComponente: reportistica su Google Sheets
Evento di calendario creato
L'API di prenotazione scrive direttamente sul Google Calendar del professionista — titolo, orario, fuso orario, entrambi i partecipanti, un link Google Meet e il contesto dell'intake nella descrizione. La prova che il sistema crea un artefatto di calendario nativo, non una riga di database privato.

Invito e conferma per il cliente
Ciò che il cliente riceve — l'invito e la conferma di Google Calendar, con i dettagli della riunione e il link Meet.

Screenshot reale · oscura i dati del destinatarioComponente: notifiche · generazione di Google Meet
Notifica interna
Ciò che il team vede quando arriva una prenotazione — la notifica interna con il contesto di qualificazione catturato e il flusso di lavoro di origine.
Screenshot reale · anonimizzatoComponente: notifiche
Guasto e recupero
Gli stati che dimostrano un pensiero orientato alla produzione: uno slot occupato tra la visualizzazione e l'invio, e la ripetizione riuscita che segue. A sinistra: conflitto. A destra: recupero.
Componente: API di prenotazione (disponibilità e concorrenza)
Impatto
Risultati oggettivi derivati dal mettere la piattaforma in produzione — prove, non marketing.
- Business
- Sostituito uno stack di pianificazione Calendly-più-Zapier con un unico sistema di proprietà.
- Rimosso il costo ricorrente dell'abbonamento di terze parti e il collante che connetteva gli strumenti.
- Cliente
- Conferma immediata e affidabile nel momento della prenotazione.
- Meno guasti di pianificazione — nessuno slot offerto che non possa essere onorato.
- Operazioni
- Prenotazioni duplicate eliminate.
- Gestione dei fusi orari automatizzata da capo a fondo.
- Inserimento manuale a calendario rimosso dalla giornata del team.
- Ingegneria
- Un'unica fonte di verità — nessun database di prenotazione parallelo che possa divergere.
- Scritture idempotenti e sicure alla ripetizione; meno parti in movimento da operare.
- Scala
- ~4.000 prenotazioni / mese.
- Zero doppie prenotazioni da quando è arrivata la serializzazione v2.
Documenti tecnici
Record ingegneristici cronologici scritti durante la costruzione della piattaforma — le decisioni, i vicoli ciechi e gli incidenti così come sono accaduti. Dai più recenti.
Case study
Una retrospettiva sulla piattaforma dal punto di vista aziendale — perché esiste, l'approccio adottato e come è andata a finire.
- Problema
- Un team di servizi gestiva il proprio calendario a mano e perdeva circa uno slot a settimana per doppie prenotazioni ed errori di fuso orario — poco costoso da contare, costosissimo in fiducia dei clienti.
- Obiettivo
- Rendere il calendario autoritativo e la prenotazione sicura, operabile da una sola persona, senza un secondo sistema di riferimento.
- Vincoli
- Google Calendar resta la fonte di verità; sicurezza a privilegio minimo; corretto sotto concorrenza e ripetizioni; entro le quote della Calendar API.
- Approccio
- Un coordinatore sottile e senza stato davanti alla Calendar API; serializzazione per singolo professionista per rimuovere la corsa; idempotenza indirizzata al contenuto per rimuovere i duplicati; UTC-più-intento per il tempo.
- Architettura
- Intake → validazione all'edge → coda FIFO per singolo professionista → coordinatore riserva/verifica/conferma → Google Calendar, con un piccolo registro di idempotenza. Nessun database di prenotazione parallelo.
- Compromessi
- Scelta una coda noiosa e dimostrabilmente corretta al posto dei lock distribuiti; accettati alcuni secondi di obsolescenza della disponibilità per un grande risparmio di quota; mantenuto lo stato nella piattaforma che già lo possiede.
- Esito
- In produzione da feb 2024, ~4.000 prenotazioni/mese, zero doppie prenotazioni da quando è arrivata la serializzazione v2; "la mia prenotazione è andata a buon fine?" è diventato un non-evento perché le ripetizioni sono sicure.
- Lezioni
- Serializza la risorsa contesa; non bloccare il mondo.
- L'idempotenza è una funzionalità, non una salvaguardia.
- Lascia che la piattaforma mantenga lo stato che già possiede.
- Futuro
- Un flusso di riprogrammazione self-service, e spostare la pulizia del TTL del registro dal cron alla scadenza del documento.
