RealEstateAI
Bottega

Abbiamo rifatto il CRM con Claude, una tabella alla volta

Da un sistema no-code su Airtable a un'applicazione nostra su Postgres, senza mai spegnere il vecchio. Cosa ha funzionato, cosa si è rotto e le regole che ne sono uscite.

2 ottobre 2026 · 7 min

Un banco di lavoro di notte con un portatile e una planimetria (immagine generata con l'AI)AI · immagine generata

Per anni il nostro CRM è stato un sistema costruito sopra Airtable: otto basi, circa centoquaranta tabelle, una settantina di viste. Funzionava, e proprio per questo era difficile toccarlo. Quest'estate abbiamo cominciato a rifarlo da capo, come applicazione nostra su Postgres, scritta in gran parte lavorando con Claude. Non è finita, e lo diciamo subito: alcune tabelle arrivano ancora copiate dal vecchio sistema. Ma è il posto dove oggi lavoriamo tutti, ed è abbastanza avanti da poter raccontare cosa abbiamo imparato.

Perché non abbiamo spento il vecchio e acceso il nuovo

Un'agenzia non può fermarsi un weekend per migrare. I clienti scrivono, le visite si fissano, i portali mandano richieste a qualunque ora. Così abbiamo scelto la strada più lenta: il nuovo sistema nasce accanto al vecchio, e le tabelle passano una alla volta.

All'inizio una copia a senso unico porta i dati da Airtable a Postgres: ogni mezz'ora le tabelle vive (contatti, visite, chiamate, immobili), di notte tutto il resto. Ogni tabella ha un suo calendario di «taglio». Tagliare vuol dire una cosa sola e precisa: togliere quella tabella dalla copia. E prima di farlo deve esistere, nel nuovo sistema, il posto dove modificarla. Una tabella che ha ancora bisogno del vecchio per essere corretta non è tagliata, qualunque cosa dica il piano.

Lo diciamo perché ci è successo: il taglio della tabella più importante, quella dei contatti, era fissato per una data precisa di fine agosto. È stato rimandato lo stesso giorno, perché un pezzo di lavoro che pensavamo di lasciare al vecchio sistema abbiamo deciso di portarlo tutto nel nuovo. Il calendario si è allungato, la regola no.

La copia che cancella

Il primo guasto serio è arrivato dalla parte più innocua: la copia. Per restare fedele, a ogni giro la copia elimina dal nuovo database le righe che su Airtable non esistono più. Giusto, finché nessuno scrive nel nuovo. Appena abbiamo cominciato a scrivere qui, una riga salvata la sera spariva alle tre di notte, senza errori e senza log, perché «non c'era più» sull'altro lato.

La soluzione è stata doppia: le righe nate nel nuovo sistema portano un contrassegno che la copia rispetta, e ogni modifica fatta qui finisce in un registro che, dopo ogni copia, la riapplica. Riga e registro si scrivono nella stessa transazione: o tutte e due, o nessuna.

Le regole che abbiamo pagato

Un solo canale di pubblicazione: git push. All'inizio si pubblicava a mano, da una cartella locale. Con più sessioni di lavoro in parallelo, chi pubblicava per secondo rimetteva online il proprio disco, e il lavoro dell'altro spariva dalla produzione pur restando nella storia del codice. È successo due volte, sul vecchio e sul nuovo. Oggi il progetto è collegato al repository: un push sul ramo principale costruisce e pubblica, e nessuno pubblica dal proprio computer. Prima di ogni push si controlla che il ramo remoto non sia andato avanti; se è andato avanti, si fonde e si ricontrolla. Una trappola collaterale: se l'autore dei commit non è riconosciuto dal servizio di hosting, la build resta bloccata in silenzio. Il push riesce e sembra solo che «non si sia aggiornato».

Le caselle vuote non sono false, sono NULL. In Airtable una casella non spuntata è semplicemente vuota. Copiata in Postgres diventa NULL. E in SQL «non fatta» non è vero per un NULL: è sconosciuto. La prima query che cercava le attività non completate restituiva zero righe invece di trentasette. Il guaio vale per decine di colonne, quindi la regola è meccanica: si scrive is not true, mai not. Parente stretto: un confronto con NULL non è falso, è NULL, e nei conteggi «non letto / non fatto» il numero esce plausibile e sbagliato proprio nel caso che interessa.

Le date si formattano dentro il database. Portate fuori come oggetti data, scivolavano al giorno prima per via del fuso. Ora si formattano in SQL e basta.

I nomi delle colonne non si indovinano. Si chiede al database prima di scrivere una query. Quattro nomi «ovvi» su quattro erano sbagliati.

Ogni scrittura verso il vecchio sistema si dichiara, e si rilegge. Per un periodo il nuovo sistema deve scrivere anche su Airtable, perché alcuni processi del vecchio leggono ancora lì. Abbiamo imparato due cose. La prima: queste scritture vanno dichiarate in testa al modulo che le fa, con la tabella, il motivo e chi le legge. La seconda: una risposta 200 non è una prova. Ci è capitato che l'API rispondesse «ok» e che, rileggendo, il valore fosse ancora quello di prima. Da allora ogni scrittura di questo tipo rilegge il campo e, se non coincide, lo dice in chiaro, con il rifiuto spiegato e non un generico «riprova».

L'invisibilità, che non è perdita

C'è un difetto più sottile della perdita di dati: il dato c'è, ma chi lavora ancora dall'altra parte non lo vede. Una funzione nuova creava un dossier di follow-up solo nel nuovo database. Il cliente risultava segnato come prioritario, ma il motore dei promemoria, che girava ancora sul vecchio, non lo vedeva. Risultato: la stellina accesa e nessun follow-up, mai. Adesso ogni modulo che scrive deve dire cosa vede il vecchio sistema e cosa no. Dove l'invisibilità fa danno, si scrive anche di là.

Il documento che mentiva

La lezione più strana riguarda le istruzioni, non il codice. Ad agosto avevamo scritto, nelle istruzioni del progetto, che dal nuovo sistema non si sarebbe mai scritto sul vecchio. Un mese dopo, contando, il codice lo faceva in ventisette moduli diversi, tutti per buone ragioni. Un «mai» violato ventisette volte non protegge niente. Insegna che il documento mente, e fa sbagliare in due direzioni: chi ci crede duplica una scrittura che esisteva già, chi non ci crede ne apre una nuova senza dichiararla. Abbiamo riscritto la regola com'era davvero, con la data della decisione vecchia barrata e lasciata leggibile, perché spiega com'è fatto il codice di allora.

Contare prima di costruire

Prima di rifare una sezione, si guarda com'era nel vecchio sistema e si contano le righe. Una sezione che sembrava un progetto intero erano diciassette schede. Un'altra, che sembrava marginale, conteneva centinaia di trascrizioni di telefonate che nessuno guardava. Il nome di una cosa non dice quanto pesa. E si legge il vecchio codice dalla versione pubblicata, non dalla copia locale: la nostra era indietro di centinaia di commit, e il numero cresceva.

Com'è lavorare così con Claude

Quasi tutto il codice nuovo è nato in sessioni con Claude. Ha funzionato bene sul volume: sezioni intere riscritte in giorni. Ma le regole sopra non le ha inventate il modello. Sono arrivate dai guasti, e ognuna è diventata una riga nelle istruzioni che ogni sessione legge prima di toccare qualcosa. Il valore non sta nel far scrivere codice a una macchina. Sta nel tenere un quaderno onesto di cosa si è rotto, e nel farlo leggere a chiunque lavori dopo, persona o modello.

#crm#migrazione#postgres#airtable#claude

Continua a leggere