Sviluppo web
SQLite vs Postgres su un progetto piccolo
Un progetto piccolo con un solo processo applicativo sta in SQLite con WAL: 300.000 righe occupano 26,8 MB e le letture indicizzate restano sotto 0,1 ms. Postgres vince con più scrittori.
In sintesi
- Con un solo processo applicativo e pochi scrittori, SQLite in modalità WAL copre il caso senza un servizio da gestire.
- 300.000 righe occupano 26,8 MB e la lettura indicizzata misura 0,024 ms di mediana contro 15,471 ms senza indice.
- Il limite non è la dimensione: è la concorrenza in scrittura, perché un solo writer per volta può procedere.
Per un progetto piccolo con un solo processo applicativo, SQLite in modalità WAL basta: 300.000 righe occupano 26,8 MB e le letture indicizzate restano sotto un decimo di millisecondo. PostgreSQL conviene quando servono scrittori concorrenti, client in rete o estensioni che SQLite non ha.
Cosa ottieni
- Un file: il database è un file sul disco dell'applicazione, senza servizio, porta o credenziale da configurare.
- Backup in una riga: il comando
.backuplegge uno stato consistente anche con il sito in funzione. - Transazioni ACID: le garanzie su atomicità e isolamento ci sono, con
BEGIN IMMEDIATEper prendere il lock di scrittura subito. - Una licenza che non chiede nulla: pubblico dominio, nessun obbligo di attribuzione o di apertura del codice.
Cosa perdi
- Scrittori concorrenti: uno solo alla volta scrive; gli altri aspettano il lock, e senza
busy_timeoutricevono un errore invece di attendere. - Più host: il file sta su un disco locale. Su un filesystem di rete il locking non è affidabile, quindi due server non condividono lo stesso database.
- Estensioni e repliche: niente PostGIS, nessuna replica in lettura nativa, nessun parallel query.
- Ruoli e permessi: i permessi sono quelli del filesystem, non dell'utente del database.
I numeri del test
| Misura | Valore |
|---|---|
| Righe nella tabella | 300.000 |
| Insert in una transazione | 299 ms |
| File del database | 26,8 MB |
| File WAL della sessione | 14,6 MB |
| Lettura indicizzata, mediana | 0,024 ms |
| Lettura senza indice, mediana | 15,471 ms |
| 5.000 insert senza indici | 5 ms |
| 5.000 insert con tre indici | 85 ms |
| Versione | SQLite 3.51.3, Node 24.15.0 |
Quando conviene migrare
Il segnale non è la dimensione del database, è il numero di processi che scrivono. Due istanze dell'applicazione dietro un load balancer violano già il modello a scrittore singolo, e un jobs worker che scrive mentre il sito scrive crea attese che nessun indice risolve. Aggiungi a questo la richiesta di repliche in lettura, di backup point-in-time o di un'estensione geografica e la migrazione si paga da sola.
Modalità, backup, attese
Tre impostazioni fanno la differenza in produzione: WAL per non bloccare le letture durante una scrittura, un busy_timeout perché le attese diventino attese invece di errori, e il backup con .backup invece della copia del file. Le stesse impostazioni rendono il passaggio a PostgreSQL più semplice, perché la logica applicativa non dipende dal motore.
sqlite3 app.db "PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;"
sqlite3 app.db ".backup 'backup.db'"
sqlite3 app.db "PRAGMA integrity_check;"
Il backup online lascia intatti i file -wal e -shm del database in uso: sono parte dello stato, non rifiuti. Se copi il database a mano mentre l'applicazione scrive, il rischio è un file che apre senza errori ma con pagine incoerenti, e il controllo di integrità è l'unico modo per accorgersene.
Il catalogo EneUI
Una vista sulle righe serve comunque, qualunque sia il motore: in catalogo ci sono i componenti tabella, i blocchi dashboard e il record table di Origin UI, licenza MIT dichiarata a monte. Controllo eseguito il 1 novembre 2026 sul catalogo da 111.985 componenti.
La limitazione
I numeri vengono da una macchina sola, con Node e un disco locale di cui non conosciamo le prestazioni: non sono un confronto fra motori. Non abbiamo misurato il comportamento con più scrittori simultanei né la latenza su un filesystem di rete, che è proprio il caso in cui SQLite peggiora. Se il deploy è serverless, multi-regione o su più container che scrivono, la risposta è PostgreSQL e non c'è misura che la cambi.
Dove continuare
La forma delle query e del contratto è in progettare un'API; le regole di cache che decidono metà della latenza percepita sono in header di cache HTTP. Se stai scegliendo fra stili di API, il confronto con i costi di entrambi è in MCP e REST.
Domande frequenti
SQLite regge un sito in produzione?
Sì, con un solo processo applicativo e un traffico in scrittura moderato. Il limite è la concorrenza: un writer per volta, gli altri attendono o ricevono SQLITE_BUSY.
Quanti dati posso mettere in SQLite?
Il limite teorico è di 281 TB per database, quindi non è la dimensione a decidere. Decidono il numero di scrittori simultanei e la necessità di accesso da più host.
Meglio WAL o journal di default?
WAL in produzione: permette letture mentre una scrittura è in corso e riduce le attese. Introduce i file -wal e -shm, che vanno inclusi nel backup.
Come faccio il backup senza fermare il sito?
Con il comando .backup, che usa l'API di backup online e legge uno stato consistente. Copiare il file con cp mentre si scrive può produrre un backup corrotto.
Quando è ora di passare a PostgreSQL?
Con più processi applicativi, scritture da servizi diversi, richiesta di repliche in lettura o estensioni. A quel punto il costo di migrazione è più basso del costo di restare.