Riscrivere il sistema senza fermare ciò che vende
viteSicure è il brand con cui Bridge Insurance Services vende polizze vita e infortuni online. La collaborazione non è iniziata dal codice, ma da un workshop: a novembre 2022 ho facilitato un Event Storming strategico con tutta l’azienda, per capire come funzionava davvero il business prima di toccare qualsiasi riga di codice. Quando a gennaio 2023 sono entrato stabilmente, il business era già in movimento: vendeva una polizza caso morte di SquareLife e una polizza infortuni di Net Insurance. Il problema era che il software non riusciva a reggere l’ambizione del broker — cioè offrire la polizza migliore tra più compagnie assicurative. E un’applicazione che non supporta più di un carrier per ramo non è un broker: è un rivenditore con due contratti.
Da dove partivamo
L’applicazione esistente fatturava circa un milione di euro all’anno, ma era nata per vendere un solo prodotto e lo mostrava in ogni sua parte:
- Il formato dati era lo stesso ovunque — database, JSON sulle API e frontend — ed era modellato sui dati che servivano a SquareLife per la polizza caso morte.
- L’applicazione infortuni era un copia-incolla di quella caso morte, con i dati nuovi incastrati nelle strutture vecchie e la logica di Net Insurance piegata con mapping fatti solo lato client.
- Il backend era altamente accoppiato: scritture dirette a database nei controller HTTP, servizi che a volte erano semplici raccolte di utility, altre volte misti tra accesso al DB e mapping dei dati, client verso i sistemi esterni procedurali con chiamate HTTP, scritture su DB e regole di business tutte mescolate.
- Il framework usato era custom, creato dalla prima società di consulenza, invasivo e non mantenuto.
- Il frontend usava stati globali che tendevano a disallinearsi dal backend; a ogni cambio pagina veniva spedito tutto lo stato globale al backend con una POST, e le validazioni erano divise tra i due lati con risultati diversi.
- Non c’era un design system: componenti UI incoerenti, attriti d’uso in un’applicazione che il cliente tende a usare una sola volta nella vita.
- Il flusso di pagamento e la firma digitale del contratto erano inconsistenti e fragili, e presenti solo per gli infortuni.
Il risultato era quello che i founder conoscono bene: piccoli bug diffusi, time-to-market che cresce, e la sensazione che ogni nuova feature costi più della precedente.
Cosa non funzionava
Non si poteva né continuare così, né staccare la spina per una riscrittura. Il sistema vecchio fatturava. L’utente finale non dà secondi e terze possibilità a un’applicazione assicurativa: se il flusso di acquisto si incaglia, il lead spesso non torna. E il team era piccolo — due sviluppatori interni, due consulenti esterni, più me e Luca Giovenzana — fractional CTO che faceva anche da PO/PM perché la struttura è leggera.
La domanda non era “rifacciamo tutto?”. Era: come costruiamo un sistema che supporti molti carrier e molti rami assicurativi, senza fermare ciò che già vende?
Cosa abbiamo fatto
1. Discovery del dominio con Event Storming
Il workshop di novembre 2022 è stato anche il modo in cui ci siamo conosciuti: un Event Storming strategico che ho facilitato insieme a Luca, con tutta viteSicure e i due consulenti che allora mantenevano l’applicazione. Prima di parlare di contratti o di codice, abbiamo passato una giornata a guardare insieme come funzionava il business. È il formato con cui preferisco iniziare una collaborazione: un workshop dà valore subito e permette a entrambe le parti di capire se ha senso lavorare insieme.
L’Event Storming è servito a far emergere il dominio reale dal flusso di lavoro dell’azienda, anziché ricavarlo dal codice legacy — il codice racconta come si è evoluto il software, non come funziona il business. Da lì sono usciti i bounded context: sono diventati i moduli di un backend monolitico ma modulare, invece di un’unica “Big Ball of Mud”.
2. Audit e costruzione del team
Dopo il workshop, il passo successivo è stato guardare il codice: a gennaio 2023 Luca è entrato come fractional CTO e io ho fatto un audit del software esistente, valutando anche i consulenti in campo. Il responso è stato chiaro: il backend legacy non era evolvibile. Abbiamo deciso di cambiare fornitore e costruire un team interno.
Sono stati assunti due giovani sviluppatori interni, molto portati ad apprendere, e integrati con due consulenti esterni di una società nota per la qualità del software. È entrato anche un consulente UX/UI designer part-time. Non è stata una squadra di esecutori: è stata una squadra da far crescere intorno al dominio.
3. Stabilizzazione del frontend
Da febbraio a maggio 2023 abbiamo lavorato per togliere i primi attriti senza stravolgere niente: bug non strutturali, UX più pulita, UI uniforme grazie a un design system e a una component library. In parallelo ho fatto le valutazioni tecniche con Luca per decidere come affrontare il backend.
4. Riscrittura incrementale del backend
A maggio 2023 abbiamo deciso di riscrivere il backend ex-novo, ma non in un colpo solo. Grazie all’Event Storming avevamo i bounded context, quindi abbiamo affrontato un BC alla volta. La difficoltà era che il vecchio sistema non era strutturato in modo razionale, con alto accoppiamento e nessuna astrazione: non potevamo semplicemente “tagliare” un pezzo, dovevamo ricostruire le linee di confine da zero.
A giugno e luglio 2023 abbiamo gettato le basi della nuova applicazione, smarcato i dubbi tecnici e implementato il primo BC — il più piccolo. Non l’abbiamo ancora portato in produzione: lato business non aggiungeva abbastanza valore da solo, e c’era ancora la scottatura con la vecchia società di consulenza.
Da agosto a ottobre 2023 abbiamo implementato il secondo BC, incentrato su un nuovo carrier (compagnia assicurativa), così da poter rilasciare su un brand separato questa nuova applicazione. Il punto di non ritorno era raggiunto: l’MVP era pronto. Dopo un mese di validazione interna da parte del business, a novembre la nuova applicazione è andata online sul brand separato, con il solo nuovo carrier. Il brand separato non aveva ancora utenti né fatturato: il rischio era contenuto, e questo ha reso accettabile una validazione breve.
5. Tecnologie e architettura
Il nuovo backend è stato scritto in TypeScript con NestJS e MongoDB — che era già in uso. Il frontend è rimasto React, ma senza stati globali tipo Redux, curando testabilità e pulizia del codice.
A livello di modellazione abbiamo usato DDD tattico: aggregati, entity, value object e domain services dove necessari. Questo ci ha dato le astrazioni giuste per gestire carrier diversi e rami assicurativi diversi con costi di evoluzione contenuti.
A livello architetturale abbiamo adottato l’ architettura esagonale: i carrier sono modellati come porte, e ogni carrier specifico ne è un adapter. In pratica, l’adapter esagonale è l’astrazione sui carrier; dentro quell’astrazione, ogni implementazione specifica è un adapter pattern classico. Questo doppio livello ci ha permesso di aggiungere un nuovo carrier integrando solo la parte che parla con il suo sistema, senza toccare la logica di business.
6. Rilascio in produzione senza big bang
A novembre e dicembre 2023 abbiamo integrato anche il carrier che era solo sulla vecchia applicazione, reso il nuovo frontend “white label” e portato online la nuova applicazione per il brand viteSicure. Non è stato uno switch on-off: è stato un rollout incrementale gestito da un proxy applicativo custom integrato nel frontend della nuova applicazione.
Inizialmente, i clienti atterravano direttamente sulla nuova applicazione, se erano vecchi utenti venivano rediretti in modo trasparente alla vecchia. Nel secondo roll-out, quando atterrava un utente vecchio sul nuovo sistema lo cercavamo nel nuovo e se non lo trovavamo lo migravamo on-the-fly sul nuovo sistema. Infine, abbiamo fatto la migrazione bulk dello storico andando a ritroso mese per mese, l’idea era di migrare prima gli utenti più recenti, perché quelli con più alta probabilità di tornare.
La vecchia applicazione è rimasta in produzione per le polizze infortuni e per altre funzionalità. Lo smantellamento successivo è avvenuto con calma usando lo strangler-fig pattern sia nel backend che nel frontend, pagina per pagina. Avevamo messo al sicuro il business principale — quello che porta più fatturato — e da lì abbiamo potuto evolvere con meno pressione e facendo fette più piccole.
7. Qualità e test
Tutto il nuovo è stato testato seguendo la piramide dei test: unit, integration, component, API, E2E. Il vecchio non ne aveva, quindi l’interoperabilità tra i due sistemi è stata verificata con test E2E black-box. Il lavoro è sempre stato verticale: frontend e backend insieme, mai a strati separati.
8. Cambiare il modo di rilasciare
Il problema non era solo tecnico. Fino al 2022 la cultura di rilascio era consulenziale: lo stakeholder forniva le specifiche, i consulenti sviluppavano per mesi, poi consegnavano un batch di feature e iniziavano due mesi di test e validazione manuali. A quel punto emergevano bug e divergenze tra ciò che si aspettavano e ciò che faceva davvero il software. La frequenza di rilascio era inferiore a una volta a settimana.
Il primo cambiamento è stato pratico: abbiamo introdotto test E2E automatici in pipeline per i flussi principali (sulla vecchia applicazione legacy), e ogni fix è stato rilasciato singolarmente appena pronto, invece di aspettare il batch mensile.
Le nuove feature hanno richiesto più tempo. Abbiamo impiegato circa 6 mesi per portare il lead time delle piccole feature a una o due settimane, perché dovevamo contemporaneamente risolvere i problemi tecnici e far evolvere la cultura aziendale verso un approccio lean e agile: feedback continui dagli stakeholder, esperimenti in produzione con utenti reali, piccoli incrementi sono arrivate con i tempi giusti, senza forzare i ritmi anche quando il team di prodotto scalpitava.
Per i rilasci più grossi sul brand che già fatturava — per esempio un nuovo carrier — ci è voluto oltre un anno per costruire la fiducia necessaria a farli uscire senza l’attrito di una validazione finale di mesi. Non è stato un cambiamento di toolchain: è stato un cambiamento di rapporto tra team e business e acquisizione di fiducia.
Cosa è cambiato
- Prima versione della nuova piattaforma per la polizza caso morte: online a novembre 2023, dopo 5 mesi di sviluppo (giugno–ottobre) e un mese di validazione interna da parte del business, su un brand separato e con un solo carrier.
- Secondo carrier (quello storico, integrato sulla nuova piattaforma tra novembre e dicembre): circa 2 mesi di sviluppo, perché dovevamo trovare e validare le astrazioni giuste e costruire il meccanismo che propone il prodotto più adatto tra quelli disponibili.
- Carrier successivi: circa 1 mese ciascuno, grazie alle astrazioni consolidate.
- Nuova linea di prodotto (polizze infortuni): circa 2 mesi.
- Migrazione completata senza mai fermare il business: il vecchio sistema ha continuato a vendere mentre il nuovo entrava in produzione, cliente per cliente.
- Bug ridotti: con la vecchia azienda di consulenza oltre l’ 80% dei commit e dei rilasci erano bug fix. In 3 mesi abbiamo ridotto drasticamente il numero di bug arretrati, e siamo scesi sotto il 20% quando la polizza caso morte della vecchia applicazione è stata dismessa.
- Tempo di rilascio ridotto: da 2 mesi di test manuali prima di ogni rilascio a 1–2 settimane di lead time sulle piccole feature in circa 6 mesi; dai batch mensili ai fix rilasciati singolarmente appena pronti.
- Fiducia sui rilasci grossi: oltre un anno per arrivare a rilasciare un nuovo carrier senza la lunga fase di validazione finale che caratterizzava il passato.
Cosa mi ha insegnato
Questa collaborazione è avvenuta mentre il mio modo di lavorare stava ancora prendendo forma. Non era ancora la partnership di 6 mesi con le tre fasi descritte oggi nel sito. Eppure qui ci sono alcuni degli elementi che poi sono diventati centrali: partire dal dominio con Event Storming, lavorare in verticale, non fermare il business, costruire un team intorno al codice.
Ho imparato che si può riscrivere un legacy senza il grande fermo, ma solo se il team e il business crescono insieme. E che il dominio deve guidare il codice, non il contrario.
Approfondimenti
Questa è solo metà della storia: l’altra metà è creare e far crescere il team da zero. Il workshop da cui sono nati i confini del nuovo sistema è raccontato in l’Event Storming come punto di partenza, il modo in cui abbiamo organizzato il codice intorno al dominio in due storie a confronto.