Gestionale su misura: quando il foglio Excel non basta più
Un gestionale su misura al posto del foglio di calcolo: cosa ho costruito, perché non un SaaS e l'incidente che ha tenuto giù l'hosting per nove ore.
Un foglio di calcolo regge finché a compilarlo è una persona sola, che si ricorda le regole non scritte e non sbaglia una riga. Poi la colonna delle quantità smette di corrispondere alla realtà, nessuno la aggiorna più e il file diventa un archivio di numeri falsi: il momento in cui serve un gestionale su misura non arriva quando i dati crescono, arriva quando l’attrito di inserirli supera il valore di averli.
Questo caso è il mio, non di un cliente: Tracker Scorte è l’app con cui traccio cosa entra ed esce da frigo, freezer e dispensa di casa. Lo racconto perché è l’unico progetto di cui posso mostrare tutto - decisioni, codice, incidenti di produzione compresi - e perché il problema è esattamente quello di un magazzino piccolo gestito a Excel. È in produzione su un sottodominio protetto da autenticazione, con 416 articoli caricati al primo avvio, e mi ha fatto pagare in prima persona ogni scorciatoia che avevo preso.
⚠️ Il problema vero: non i dati, l’attrito di inserirli
L’inventario numerico preciso è la prima causa di abbandono di questi sistemi. Chi tiene il magazzino su un foglio lo sa: finché si registra il carico si fa, quando bisogna scalare i pezzi consumati uno a uno si smette. Un inventario che nessuno aggiorna, poi, è peggio di nessun inventario, perché nel frattempo ci si era fidati.
Le domande a cui volevo rispondere, però, non hanno bisogno delle quantità esatte:
- cosa mi manca e va ricomprato;
- cosa resta fermo da troppo tempo e sto per buttare;
- cosa ricompravo sempre e non rientra più.
Sono le stesse tre domande di un magazzino di ricambi o di un laboratorio: cosa manca, cosa marcisce, cosa non gira più.
✅ La scelta di modello: eventi, non giacenze
Da qui la decisione che regge tutto il resto: si registrano entrata e uscita come eventi in append, e lo stato “c’è / non c’è” si deriva dal log, senza contare le unità. È il modello fissato nell’ADR 0001 del progetto, con una motivazione comportamentale prima che tecnica: si ottengono gli stessi tre segnali con una frazione della fatica di inserimento.
Sopra il log si calcolano gli stati derivati, che poi sono la parte utile: abituale (entra con regolarità), mancante (abituale ma oggi assente, alimenta la lista della spesa), da consumare (presente ma fermo oltre la cadenza attesa della sua categoria), abbandonato (lo ricompravi sempre e non rientra da molto). L’unità di conto non è il codice a barre ma l’articolo canonico: due marche di pelati sono lo stesso articolo, altrimenti il segnale “non lo ricompro più” non si accorgerebbe mai di niente.
Un inventario a quantità è più preciso sulla carta e più falso nella realtà, perché nessuno lo aggiorna. Meglio un dato grezzo che resta vero di un dato fine che smette di esserlo.
Perché non un SaaS già pronto
La domanda onesta da farsi prima di scrivere una riga di codice è se qualcosa di pronto basti. Nel mio caso no, per tre ragioni che si ripresentano identiche in azienda:
- Il modello dati non era negoziabile. Le app di dispensa in circolazione ragionano a quantità e scadenze; il segnale che mi serve nasce dal log di eventi e dalla cadenza per categoria. Adattarsi al modello di qualcun altro significa rinunciare proprio alla cosa per cui stai adottando lo strumento.
- I dati restano miei. Cosa compri e con che frequenza è un dato intimo, e in azienda il consumo interno è un pezzo di strategia. Qui il database è un file SQLite sul mio hosting, e la scelta dichiarata nel progetto è di non rivendere a nessuno i consumi individuali.
- La superficie era piccola. Non serviva una piattaforma: serviva la cattura veloce da telefono, l’elenco per luogo e tre liste derivate. Sotto una certa dimensione il su misura costa meno del canone, e sopra quella soglia scala meglio.
Vale il criterio che uso per automatizzare i processi ripetitivi di una PMI: frequenza per tempo per rischio d’errore. Se il conto non torna, il software su misura non si fa. Se torna, si fa piccolo.
🛠️ Cosa ho costruito (poco e giusto)
L’MVP è deliberatamente magro: un server Hono in TypeScript, database SQLite via better-sqlite3, client leggero servito da Vite, nessun framework di frontend pesante e nessun servizio esterno obbligatorio. Gira dietro Passenger su hosting CloudLinux, su Node 24, con autenticazione basic davanti a tutto e il database vivo fuori dalla cartella del repo, così il deploy via git pull non tocca mai i dati veri (il file versionato resta solo come seed del primo avvio).
La cattura è la parte su cui ho speso di più, perché è l’unico punto in cui il sistema chiede fatica a chi lo usa: il codice a barre si decodifica in locale dalla fotocamera - per questo servivano HTTPS vero e un sottodominio pubblico, non la rete di casa - e l’articolo canonico viene dedotto dalla label grezza solo la prima volta, poi il mapping resta in cache. Il resto è riuso: la modalità “controllo”, che riallinea un ripiano dopo un periodo senza registrazioni, non ha aggiunto né tabelle né endpoint, sta tutta nell’interfaccia sopra quello che già c’era, con le uscite messe in stage e scritte solo alla conferma.
Il pezzo semantico, cioè interpretare una label mai vista, è l’unico che chiama un modello linguistico, ed è progettato per degradare da solo: se quel canale non risponde, l’app non si ferma, ripiega sulla label così com’è, marca la voce come da rivedere e il nome si corregge a mano alla conferma. Scansione, eventi, inventario e segnali non passano mai da lì. Questa era una decisione presa in anticipo e messa per iscritto (ADR 0003), non una toppa a posteriori: sapere quale funzione può sparire senza portarsi dietro il resto distingue un gestionale che regge da uno che cade insieme al suo fornitore.
⚠️ L’incidente: quattordici thread di troppo e nove ore di disservizio
Poi le cose si rompono, e questa è la parte che di solito non si racconta.
L’app in produzione girava in TypeScript interpretato a runtime, come in sviluppo: comodo, un passaggio in meno nel deploy. Quel runtime però teneva aperto un servizio di compilazione da 14 thread, sempre acceso. Sullo stesso account dell’hosting giravano tre applicazioni Node: sommando i processi, l’account ha esaurito il tetto di task del contenitore (circa 60 nella configurazione CloudLinux) e a quel punto non è caduta l’app di dispensa, è caduto un altro servizio dello stesso account, rimasto giù per nove ore.
Il servizio che si è rotto non era quello che aveva il difetto. È la firma tipica dei limiti di risorse condivise: il sintomo appare dove il vicino è più fragile, non dove sta la causa.
Il fix, applicato il 22 luglio 2026, è stato smettere di interpretare il codice in produzione: il server viene compilato in un bundle con esbuild in fase di deploy, e il file di avvio usa il bundle se esiste, ricadendo sul runtime interpretato solo in sviluppo. Il conteggio dei thread dell’account è passato da 57 a 40. Nessuna riscrittura, nessun cambio di hosting: un passaggio in più nel deploy.
🛠️ Gli altri due inciampi, per onestà
Nello stesso periodo ne sono usciti altri due, entrambi di ambiente e non di codice:
- Il modulo nativo del database non partiva. I binari precompilati di
better-sqlite3pretendono una libreria di sistema più recente di quella della distribuzione dell’hosting, e il caricamento falliva secco. Soluzione durevole: ricompilarlo dal sorgente a ogni installazione, con toolchain e Python fissati nella configurazione di deploy. - Un deploy morto a metà, con il sito apparentemente su. Lo script che abilita la toolchain di compilazione invoca
rpm, che dentro il contenitore dell’hosting non esiste; l’errore uccideva la shell remota dopo l’installazione dei pacchetti e prima del riavvio. Risultato: modulo nativo rotto sul disco e vecchio processo ancora in memoria a servire le richieste. Sarebbe caduto al primo riavvio, in un momento a caso. Il fix sono due righe nello script di deploy, ma la lezione sta altrove: un deploy che non riavvia davvero non è un deploy riuscito, ed è per questo che lo smoke test dopo la pubblicazione non è burocrazia.
Il risultato
- L’app è in produzione dal 18 luglio 2026 su un sottodominio dedicato con autenticazione, raggiungibile dal telefono ovunque, con il database vivo fuori dal repo e il deploy in un comando.
- Il primo avvio è partito con 416 articoli caricati; dopo la pulizia, quelli realmente in uso sono circa 350, e sono dati veri, non un dataset di prova.
- Le tre domande di partenza - cosa manca, cosa consumare, cosa ho smesso di ricomprare - hanno una risposta calcolata dal log, senza che io abbia mai contato un pezzo.
- La funzione semantica degrada da sola: se il canale AI non risponde si continua a lavorare, e un nome si corregge a mano.
La lezione, trasferita a un’azienda
Il valore di questo caso non è l’app: è il metodo, che su un magazzino aziendale resta identico.
Scegli il modello dati sul comportamento reale, non sull’ideale. Se il processo richiede una precisione che nessuno manterrà, il gestionale su misura fallisce esattamente come il foglio che sostituisce.
Costruisci poco. L’MVP che regge risponde a tre domande, non a trenta. Le altre si aggiungono dopo, quando il sistema viene usato tutti i giorni e ti dice da solo cosa manca.
Decidi in anticipo cosa può rompersi. Mettere per iscritto quale funzione è sacrificabile, e cosa fa il software quando quella funzione non c’è, vale più di qualsiasi promessa di continuità.
Il rischio non sta nel codice, sta nell’ambiente. Le tre cose andate storte qui sono tutte fuori dall’applicazione: limiti di risorse del contenitore, librerie di sistema, uno script di deploy che moriva in silenzio. Chi vende un gestionale e non dice chi lo tiene in piedi sta vendendo metà del lavoro.
Un gestionale su misura non è un progetto che finisce alla consegna: vive su un server, si rompe in modi che non avevi previsto e va tenuto. Se il tuo foglio di calcolo ha smesso di dire la verità, il primo passo è capire quale dato sei davvero disposto a inserire ogni volta, lo stesso ragionamento che applico prima di automatizzare un processo ripetitivo. Raccontami come lavorate oggi da uno dei canali qui sotto: ti dico se serve software o se basta togliere un passaggio.
❓ Domande frequenti
Quando conviene un gestionale su misura invece di un SaaS?
Serve tracciare le quantità esatte in un inventario?
Cosa succede se la parte AI di un gestionale non risponde?
Perché un problema di hosting ha buttato giù un servizio diverso da quello difettoso?
Hai un progetto in testa?
Raccontami cosa ti serve o cosa non funziona. Rispondo entro 24 ore, senza preventivi a scatola chiusa.