Il costo di innamorarsi della tecnologia
- Cypher si adatta ai dati SEO meglio di SQL — ed è anche ciò che me l'ha fatto trovare facile da amare.
- Tre engine, tre ostacoli, Neo4j troppo server-oriented, Kùzu archiviato a ottobre 2025, FalkorDB su licenza SSPLv1 troppo ambigua per costruirci un prodotto commerciale.
- Il rendering di un grafo lato client serializza l'intero grafo in un payload JSON — i DevTools lo trasformano in una fuga di dati, in contraddizione con la promessa di data ownership.
- Lezione: concentrati nel capire come utilizzare i dati prima di fare qualsiasi altra cosa.
A dicembre mi sono convinto che mi servisse un database a grafo.
Sulla carta il ragionamento filava. I dati SEO sono per loro natura relazionali — le pagine si linkano ad altre pagine, le entità compaiono nelle pagine, i topic si addensano attorno alle entità. Un grafo cattura queste relazioni in modo molto più diretto di una serie di tabelle in un database relazionale.
Il richiamo di Cypher
I database a grafo hanno un linguaggio di query proprio — Cypher — che sta ai grafi come SQL sta alle tabelle, solo che descrivi pattern di relazioni invece di righe e colonne. Per certe domande è espressivo in un modo in cui SQL, semplicemente, non riesce a esserlo.
Volevo poter scrivere "dammi tutte le pagine in cui compare questa entità, ordinate per quanto sono centrali nel grafo dei link interni" in una sola query leggibile. Cypher lo permette in modo naturale. Con SQL, finisci sempre con query annidate e CTEs.
È stato proprio questo dettaglio — Cypher si legge come la domanda — a innescare tutto il filone. Vale la pena dirlo, perché è esattamente lì che è cominciato l'innamoramento.
In cerca di un motore embedded
Mi serviva qualcosa di embedded, che girasse direttamente dentro il processo Python principale, senza server da gestire né un secondo processo da tenere in piedi. Questo ha tagliato fuori subito la scelta più ovvia, e da lì è cominciata una sfilata di candidati: ognuno reggeva un paio di giorni, poi qualcosa lo faceva fuori.
Neo4j — troppo pesante
Neo4j era la risposta scontata, e si è rivelato subito troppo pesante: dipendenza da Docker, architettura a server, pensato per i team e non per una singola macchina che fa girare uno strumento locale. Prodotto eccellente, ma per il mio caso d'uso era della forma sbagliata.
Kùzu — archiviato a metà strada
Kùzu sembrava la risposta giusta: embedded, Python-native, veloce, compatibile con Cypher. Ho passato un paio di giorni sulla documentazione, già a immaginare come l'integrazione nel prodotto finale fosse possibile.
Ma nel cammin di mia lettura ... ho scoperto che il progetto era stato archiviato a ottobre 2025. Di fatto, morto. Un promemoria come "graph DB analitico embedded" è abbastanza piccola da crollare appena un team si ferma.
FalkorDB — il muro della licenza
Restava FalkorDB, un database a grafo costruito sopra Redis, con una variante embedded che girava senza bisogno di un server gestito. Compatibile con Cypher, accessibile da Python, davvero veloce. Sulla carta corrispondeva esattamente al profilo che cercavo.
Solo che il problema successivo era la licenza — SSPLv1 — che crea complicazioni nel momento in cui vuoi costruirci sopra un prodotto commerciale. Ho perso più tempo del dovuto a leggere il testo della licenza per capire se la clausola avesse potuto creare complicazioni al prodotto che sto sviluppando e che vorrei lanciare come SAAS. In tutta franchezza, non penso che avrei avuto problemi, ma non ero sicuro e quindi ho evitato il rischio.
I candidati a confronto
| Engine | Embedded | Cypher | Licenza | Stato del progetto (Dic 2025) | Verdetto |
|---|---|---|---|---|---|
| Neo4j | No (server / Docker) | Sì (nativo) | GPLv3 Community / commerciale | Attivo, ben finanziato | Forma sbagliata — troppo pesante per uno strumento su singola macchina |
| Kùzu | Sì (in-process) | Sì | MIT | Archiviato ottobre 2025 | Progetto fermo a monte — non praticabile |
| FalkorDB | Sì (FalkorDBLite) | Sì (openCypher) | SSPLv1 | Attivo | Licenza ambigua per un prodotto commerciale |
Tre opzioni plausibili, tre ragioni diverse per scartarle. A posteriori, era già lì il primo campanello d'allarme.
Visualizzare il grafo
Un database a grafo serve a poco se non puoi vedere il grafo. Quindi il filone successivo era il rendering. Ho valutato quattro librerie, costruito qualche implementazione di prova, le ho fatte girare per vedere come si comportavano.
| Libreria | Approccio | Punto di forza | Dove fa fatica |
|---|---|---|---|
| Cytoscape.js | Libreria dedicata ai grafi | Algoritmi di layout ricchi, default sensati per i dati di rete | Bundle pesante, scelte di stile poco neutre |
| D3.js | Primitive di visualizzazione di basso livello | Controllo totale, risultati di grande qualità | Curva di apprendimento lunga; lo strato grafo lo scrivi tu |
| vis-network | Componente di rete di più alto livello | La via più rapida per avere un grafo che funziona | Poca flessibilità quando le esigenze crescono |
| Sigma.js | Renderer basato su WebGL | Gestisce grafi di grandi dimensioni senza affanno | Ecosistema più ristretto, curva più ripida sullo styling |
Ognuna aveva i suoi compromessi tra performance, curva di apprendimento e qualità del rendering. Con due di queste avevo già un prototipo funzionante. Il problema della visualizzazione era risolvibile.
La goccia che ha fatto traboccare il vaso
Poi mi sono imbattuto nel problema che ha messo fine a tutto il filone.
Per renderizzare un grafo lato client devi serializzare i dati in un payload JSON. Il che significa che chiunque apra i DevTools del browser può leggere l'intero grafo SEO — ogni pagina, ogni link interno, ogni mappatura tra entità e pagina. Per uno strumento il cui pitch è la data ownership, è una contraddizione troppo grossa per chiudere un occhio.
Puoi offuscare. Puoi paginare. Puoi renderizzare lato server e mandare al client solo immagini. Nessuna di queste vie preserva ciò che rende preziosa la vista a grafo all'origine — un utente che esplora i propri dati in modo interattivo. L'architettura che fa funzionare la visualizzazione è la stessa che fa uscire i dati.
Evidentemente l'uso del database a grafo non e' qualche cosa su cui posso fare affidamento, non ora, non per quello che ho in mente.
La lezione da imparare
Una settimana circa di esplorazione intorno a Natale, senza però giungere a conclusioni definitive. Ma non è stato tempo sprecato, perché ho tratto alcuni insegnamenti che voglio condividere con voi: non lasciate che una bella architettura vi distragga da come si accede ai dati.
L'espressività di Cypher, la parte embedded, le librerie di visualizzazione — prese una a una, erano scelte sensate, e ogni valutazione, sui propri criteri, reggeva. Quel che mi mancava era la domanda che si pone alla fine del pipeline, non all'inizio. "Come fa l'utente a vedere questa roba?" è una di quelle domande che, in silenzio, vincolano tutto quel che le sta a monte. Se me la fossi fatta il primo giorno, mi sarei risparmiato il resto della settimana.
Il problema non è innamorarsi di uno strumento. Il problema è lasciare che quell'innamoramento rimandi la domanda che, posta in tempo, avrebbe chiuso la conversazione molto prima.