Vue d'ensemble
Un système de planification qui permet à une équipe de services distribuée de prendre des réservations auprès de nombreux praticiens sans jamais doubler une réservation, mal gérer un fuseau horaire ou dupliquer un rendez-vous lors d'une nouvelle tentative — avec Google Calendar comme unique source de vérité.
Ce qui a été construit
Une plateforme de réservation posée directement sur Google Workspace. Les clients choisissent un créneau parmi les disponibilités calculées ; la plateforme réserve, vérifie et confirme le rendez-vous en une seule transaction idempotente, écrivant l'événement dans le Google Calendar du praticien et prévenant les deux parties. Il n'y a pas de base de données de référence distincte — l'agenda dans lequel l'équipe vit déjà reste la référence.
À qui il s'adresse
Une entreprise de services faisant travailler plusieurs praticiens, chacun avec ses propres horaires de travail, tampons et congés, prenant des réservations depuis un formulaire web, par e-mail et par l'occasionnel appel téléphonique saisi après coup.
Contexte métier
Le processus manuel qu'elle a remplacé perdait environ un créneau par semaine à cause des doubles réservations et des décalages de fuseau horaire — peu nombreux, mais coûteux en confiance. Le rôle de la plateforme était de rendre l'agenda faisant autorité et la réservation sûre, sans ajouter un second système qui finirait par se désynchroniser.
Architecture
Un coordinateur mince et sans état devant Google Calendar. Une réservation est une transaction courte et idempotente — réserver, vérifier, confirmer — acheminée à travers une file d'attente par praticien, afin que la concurrence qui provoque la double réservation ne puisse pas se produire.
Pourquoi une file d'attente par praticien
La double réservation est une concurrence entre écrivains simultanés pour une même ressource. Plutôt que de recourir à des verrous distribués, chaque requête pour un praticien donné passe par une file d'attente FIFO à consommateur unique — une primitive ennuyeuse et débogable qui rend la concurrence impossible plutôt que simplement réparable. La concurrence entre praticiens reste élevée ; au sein d'un même praticien, elle tombe à un.
Composants
La plateforme est bâtie à partir de neuf composants. Chacun est documenté comme sa propre section d'ingénierie — pourquoi il existe, son architecture, les contraintes et cas limites qu'il gère, les compromis retenus et l'implémentation finale. Dépliez-en un pour le lire.
›C1Flux de réservation multi-étapes
- Pourquoi il existe
- Transforme « trouver un horaire » en une séquence guidée et reprenable — service → praticien → date → créneau → détails → confirmation — qui ne présente jamais un créneau qu'elle ne peut pas honorer.
- Architecture
- Un client sans état piloté par le moteur de disponibilité ; chaque étape se revalide en temps réel contre le free/busy, si bien qu'un créneau qui se remplit en cours de flux est détecté avant la soumission.
- Contraintes
- Doit fonctionner depuis un formulaire web, un lien e-mail et une réservation téléphonique saisie à la main ; aucune étape ne peut se fier à l'horloge de l'appareil du client.
- Cas limites
- Créneau pris entre l'affichage et la soumission ; re-soumission par le bouton retour ; un praticien partant en congé en cours de session.
- Compromis
- Revalider chaque étape coûte une lecture free/busy supplémentaire, mais élimine l'échec « le créneau que vous avez choisi n'est plus disponible » au moment de la confirmation.
›C2Moteur de disponibilité
- Pourquoi il existe
- Calcule les fenêtres réservables par praticien à partir des horaires de travail, tampons, événements existants et congés — le modèle de lecture à partir duquel tout le flux s'affiche.
- Architecture
- Précalcule les fenêtres selon une planification et sur les webhooks de changement d'agenda, en les mettant en cache dans Firestore ; le flux lit le cache, et non l'API Calendar, sur le chemin critique.
- Contraintes
- Doit rester correct pendant que les praticiens modifient directement leurs propres agendas ; ne doit pas dépasser le quota de lecture Calendar sous charge.
- Cas limites
- Événements qui se chevauchent, blocs d'une journée entière, blocages récurrents et frontières DST où une fenêtre « 9 h » se décale.
- Compromis
- Un TTL de cache court échange quelques secondes d'obsolescence contre une forte baisse des appels d'API ; l'étape de confirmation fait autorité, donc une brève obsolescence est sans danger.
›C3API de réservation (réserver · vérifier · confirmer)
- Pourquoi il existe
- Le cœur transactionnel : transforme une requête en exactement un événement d'agenda, en toute sûreté, même sous concurrence et nouvelles tentatives.
- Architecture
- Chaque requête pour un praticien passe par la file d'attente FIFO à consommateur unique de ce praticien ;
confirm()vérifie le free/busy à l'intérieur de cette fenêtre et écrit avec une clé d'idempotence adressée par le contenu. - Contrat d'API
POST /booking → 201 {eventId} | 409 SlotTaken // idempotent: same intent ⇒ same eventId key = sha256(practitionerId, startUTC, clientId)
- Cas limites
- Requêtes simultanées pour un même créneau (sérialisées et éliminées) ; nouvelles tentatives de formulaire/réseau (fusionnées en un seul événement via le registre) ; échec partiel après l'insertion (la validation du registre le rend sûr au rejeu).
- Compromis
- La sérialisation par praticien ajoute quelques ms de latence et supprime la concurrence par construction — choisie plutôt que des verrous distribués.
›C4Intégration Google Calendar
- Pourquoi il existe
- Maintient Google Calendar comme source de vérité — en lisant le free/busy et en écrivant les événements — pour que l'équipe ne quitte jamais l'outil qu'elle utilise déjà.
- Architecture
- Utilise la requête agrégée
freebusypour la disponibilité (sans détail d'événement) etevents.insertpour les écritures, marquant chaque événement de sa clé de réservation dans des propriétés étendues privées. - Contraintes
- Quotas de lecture à la minute ; portées au moindre privilège ; doit survivre aux praticiens modifiant les événements à la main.
- Cas limites
- Événements supprimés manuellement, partages d'agenda externes et réconciliation lorsque l'agenda et le registre divergent.
›C5Gestion des fuseaux horaires
- Pourquoi il existe
- Garantit qu'un créneau désigne le même instant pour le client, le praticien et le serveur à travers les changements d'heure d'été.
- Architecture
- Stocke l'instant en UTC et la zone IANA voulue par l'utilisateur dans un champ distinct ; les deux ne se recombinent qu'au rendu.
- Cas limites
- Trous d'avance/de recul horaire, zones qui observent le DST à des dates différentes, et clients changeant le fuseau de leur appareil après la réservation.
- Compromis
- Porter une zone explicite est plus lourd à stocker qu'un simple horodatage, mais c'est la seule manière de préserver la promesse « 9 h à Lisbonne ».
›C6Authentification et permissions
- Pourquoi il existe
- Permet à la plateforme d'agir sur les agendas du domaine avec la moindre autorité qu'une équipe de sécurité acceptera de valider.
- Architecture
- Un compte de service dédié avec une délégation à l'échelle du domaine étroitement délimitée ; chaque compte remonte à un propriétaire et à un registre de décision.
- Contraintes
- Aucune portée large ; clés renouvelées selon une planification ; accès revu sur un calendrier, et non de mémoire.
- Compromis
- Le moindre privilège demande davantage de configuration en amont, en échange d'un modèle qui passe la revue sans exceptions.
›C7Notifications
- Pourquoi il existe
- Confirme, rappelle et annule pour le client comme pour le praticien, sans jamais envoyer deux fois.
- Architecture
- Diffusion au moins une fois via Cloud Tasks avec des clés d'idempotence et une file de rebut, si bien qu'une nouvelle tentative n'envoie jamais en double.
- Cas limites
- Limitation par le fournisseur, adresses en échec de remise, et une réservation annulée avant le déclenchement de son rappel.
›C8Génération de Google Meet
- Pourquoi il existe
- Attache un lien vidéo fonctionnel à chaque réservation à distance au moment de la création de l'événement.
- Architecture
- Demande les données de conférence lors de
events.insertpour que le lien Meet fasse partie de la même écriture atomique que la réservation. - Cas limites
- Échecs de création de conférence (la réservation doit tout de même aboutir) et événements reprogrammés conservant leur lien.
›C9Reporting Google Sheets
- Pourquoi il existe
- Donne à l'opérateur une vue familière et en direct des réservations et de la charge, sans tableau de bord sur mesure.
- Architecture
- Synchronisation en ajout seul depuis le registre vers un Sheet, traité comme une réplique de lecture — jamais comme une source de vérité.
- Compromis
- Un Sheet est limité et légèrement en retard, mais il est instantanément lisible par un non-ingénieur, ce qui est tout l'intérêt.
Rendu visuel
Ce que le système produit réellement pour le client et l'opérateur. Ce sont des pièces issues du système en fonctionnement — chacune légendée et reliée au composant qui la crée. Déposez les vraies captures d'écran dans les cadres.
Le flux de réservation
Le parcours client en trois étapes : service et horaire → coordonnées → date et heure → confirmation. Chaque étape se revalide contre la disponibilité en direct.

Vraie capture d'écran du système en fonctionnementComposant : Flux de réservation multi-étapes
La fiche de prospect
Où atterrissent les réponses de l'étape de contact : une ligne ajoutée au Google Sheet — nom, entreprise, e-mail professionnel, source et horodatage de soumission. Utilisez des données anonymisées ou d'exemple.

Vraie capture d'écran · données d'exemple / anonymiséesComposant : Reporting Google Sheets
Événement d'agenda créé
L'API de réservation écrit directement dans le Google Calendar du praticien — titre, heure, fuseau horaire, les deux participants, un lien Google Meet et le contexte d'accueil dans la description. La preuve que le système crée un artefact d'agenda natif, et non une ligne de base de données privée.

Invitation et confirmation du client
Ce que reçoit le client — l'invitation et la confirmation Google Calendar, avec les détails de la réunion et le lien Meet.

Vraie capture d'écran · masquer les coordonnées du destinataireComposant : Notifications · Génération de Google Meet
Notification interne
Ce que voit l'équipe quand une réservation arrive — la notification interne avec le contexte de qualification capturé et le flux source.
Vraie capture d'écran · anonymiséeComposant : Notifications
Échec et reprise
Les états qui prouvent une pensée orientée production : un créneau pris entre l'affichage et la soumission, et la nouvelle tentative réussie qui suit. À gauche : le conflit. À droite : la reprise.
Composant : API de réservation (disponibilité et concurrence)
Impact
Résultats objectifs issus de la mise en production de la plateforme — des preuves, pas du marketing.
- Business
- A remplacé une pile de planification Calendly-plus-Zapier par un seul système possédé.
- A supprimé le coût d'abonnement tiers récurrent et la glu reliant les outils.
- Client
- Confirmation immédiate et fiable au moment de la réservation.
- Moins d'échecs de planification — aucun créneau proposé qui ne puisse être honoré.
- Opérations
- Réservations en double éliminées.
- Gestion des fuseaux horaires automatisée de bout en bout.
- Saisie manuelle dans l'agenda retirée du quotidien de l'équipe.
- Ingénierie
- Une unique source de vérité — aucune base de données de réservation parallèle qui dérive.
- Écritures idempotentes, sûres au rejeu ; moins de pièces mobiles à exploiter.
- Échelle
- ~4,000 réservations / mois.
- Zéro double réservation depuis l'arrivée de la sérialisation v2.
Documents techniques
Dossiers d'ingénierie chronologiques écrits pendant la construction de la plateforme — les décisions, impasses et incidents tels qu'ils se sont produits. Du plus récent au plus ancien.
Étude de cas
Une rétrospective sur la plateforme du point de vue métier — pourquoi elle existe, l'approche adoptée et comment cela s'est passé.
- Problème
- Une équipe de services gérait son agenda à la main et perdait environ un créneau par semaine à cause des doubles réservations et des erreurs de fuseau horaire — peu coûteux à compter, coûteux en confiance client.
- Objectif
- Rendre l'agenda faisant autorité et la réservation sûre, exploitable par une seule personne, sans second système de référence.
- Contraintes
- Google Calendar reste la source de vérité ; sécurité au moindre privilège ; correct sous concurrence et nouvelles tentatives ; dans les limites des quotas de l'API Calendar.
- Approche
- Un coordinateur mince et sans état devant l'API Calendar ; sérialisation par praticien pour supprimer la concurrence ; idempotence adressée par le contenu pour supprimer les doublons ; UTC-plus-intention pour l'heure.
- Architecture
- Accueil → validation en périphérie → file d'attente FIFO par praticien → coordinateur réserver/vérifier/confirmer → Google Calendar, avec un petit registre d'idempotence. Aucune base de données de réservation parallèle.
- Compromis
- Choix d'une file d'attente ennuyeuse et prouvée correcte plutôt que de verrous distribués ; acceptation de quelques secondes d'obsolescence de disponibilité pour une forte économie de quota ; état conservé dans la plateforme qui le possède déjà.
- Résultat
- En production depuis Feb 2024, ~4,000 réservations/mois, zéro double réservation depuis l'arrivée de la sérialisation v2 ; « ma réservation est-elle bien passée ? » est devenu un non-événement, parce que les nouvelles tentatives sont sûres.
- Enseignements
- Sérialisez la ressource en contention ; ne verrouillez pas le monde entier.
- L'idempotence est une fonctionnalité, pas un garde-fou.
- Laissez la plateforme conserver l'état qu'elle possède déjà.
- Suite
- Un flux de reprogrammation en libre-service, et le déplacement du nettoyage TTL du registre depuis cron vers l'expiration des documents.
