Questo è il seguito di SQLite vs Postgres per un prodotto indie. Lì la regola era: SQLite basta finché hai un processo che scrive e un disco persistente. Qui la domanda cambia. Cosa succede quando SQLite esce dal file e va in rete? Le opzioni gestite sono due, Turso e Cloudflare D1, contro la strada classica di un Postgres gestito come Neon o Supabase. Il pezzo è costruito solo su documentazione e listini ufficiali letti il 28 ottobre 2026. Non ho fatto test né benchmark, e non ci sono numeri di latenza miei.
In breve:
- D1 è SQLite gestito dentro Cloudflare: lo interroghi da un Worker con un binding, costa a righe lette e scritte, ha Time Travel per 30 giorni incluso e repliche di lettura senza costi extra. Il limite duro è 10 GB per database.
- Turso è SQLite (libSQL o il nuovo motore Turso Database) raggiungibile via HTTP da qualunque runtime, con repliche dentro l'app e ripristino a un punto nel tempo. Dal 2 ottobre 2026 è in acquisizione da Supabase.
- Un Postgres gestito costa di più in partenza e ti chiede connessioni e pooler, ma ti dà estensioni, più servizi sugli stessi dati e un formato che porti da un fornitore all'altro.
- La domanda giusta non è quale sia il più veloce. È dove gira il tuo codice, quanto vale ogni byte di dato e quanto ti costa uscire.
Il problema che stanno risolvendo
SQLite su un solo disco ha tre limiti per un prodotto in produzione. Il file sta su una macchina, quindi le istanze effimere non lo condividono. Il backup va fatto bene, mentre l'app scrive. Le scritture sono serializzate.
Turso e D1 tengono il dialetto SQLite e spostano il file su un servizio gestito. Backup, repliche e accesso da più istanze diventano un problema del fornitore. In cambio accetti un protocollo, un client e un listino che non sono più quelli di un file.
Il Postgres gestito risolve gli stessi tre limiti con un'altra architettura: un server, connessioni di rete, un dialetto diverso. È la strada che il pezzo precedente consigliava quando il deploy è distribuito.
Le tre opzioni a confronto
Dati letti il 28 ottobre 2026 dalle pagine ufficiali. Prezzi in dollari, al mese.
Cloudflare D1 | Turso Cloud | Postgres gestito (Neon, Supabase) | |
|---|---|---|---|
Motore | SQLite gestito da Cloudflare | libSQL (fork di SQLite) o Turso Database (riscrittura) | Postgres |
Da dove lo interroghi | Worker con binding; REST API e Wrangler per gestione e import | HTTP da qualunque runtime, Workers compresi; replica locale nell'app | Connessione Postgres, pooler; Neon ha un driver HTTP e WebSocket; da Workers anche con Hyperdrive |
Piano gratuito | 5 milioni di righe lette e 100.000 scritte al giorno, 5 GB in tutto | 100 database, 5 GB, 500 milioni di righe lette e 10 milioni scritte al mese | Neon: 100 CU-ora e 1 GB per progetto. Supabase: 500 MB, progetto in pausa dopo una settimana di inattività |
Primo piano a pagamento | Workers Paid, minimo $5 per account: 25 miliardi di righe lette, 50 milioni scritte, 5 GB | Developer $5,99 ($4,99 con pagamento annuale): 9 GB, 2,5 miliardi di righe lette, 25 milioni scritte | Neon Launch: nessun minimo, $0,106 per CU-ora e $0,35 per GB-mese. Supabase Pro: da $25, con $10 di crediti compute |
Oltre la quota | $0,001 per milione di righe lette, $1 per milione scritte, $0,75 per GB-mese | Developer: $1 per miliardo lette, $1 per milione scritte, $0,75 per GB | Neon: compute a consumo, egress oltre 500 GB a $0,10 per GB. Supabase: disco oltre 8 GB a $0,125 per GB |
Ripristino a un punto nel tempo | Time Travel incluso: 30 giorni su Paid, 7 su Free | 1 giorno Free, 10 Developer, 30 Scaler, 90 Pro | Neon: 6 ore Free, fino a 7 giorni Launch, fino a 30 Scale. Supabase Pro: backup giornalieri per 7 giorni, PITR come add-on da circa $100 |
Repliche di lettura | Da attivare per database: una replica in ogni region supportata, senza costi extra, con Sessions API | Embedded Replicas nell'app, o Turso Sync | Neon: ogni replica è una compute in più. Supabase: Read Replicas |
Limite che pesa | 10 GB per database, non aumentabile; un database esegue una query alla volta | Storage e righe per piano, poi a consumo | Compute e connessioni da dimensionare |
Il dettaglio che cambia la lettura della tabella: su D1 e Turso paghi righe, su Neon paghi tempo di compute. Una query senza indice su D1 conta tutte le righe scansionate, anche se ne restituisce poche. Su Neon la stessa query costa il tempo in cui la compute resta accesa.
Cloudflare D1: SQLite accanto al Worker
D1 vive dentro la piattaforma di Cloudflare. Il codice lo raggiunge con un binding, senza connessioni da aprire. La pagina query a database elenca tre strade: binding dei Workers, REST API e comandi Wrangler. La REST API lavora soprattutto sul piano di controllo, cioè creazione e gestione. Se il tuo backend non gira su Workers, D1 non è pensato per te.
Il listino di D1 non ha costi per egress né per ore di compute. Paghi righe lette, righe scritte e storage oltre i 5 GB inclusi. Il minimo è l'abbonamento Workers Paid da $5 per account, che copre anche Workers, KV e Durable Objects.
I limiti, aggiornati il 24 ottobre 2026, sono il punto da leggere prima di scegliere. Un database arriva al massimo a 10 GB e la documentazione dice che il limite non si può alzare. Ogni database è single-threaded ed elabora una query alla volta: con query da 1 ms il tetto è circa 1.000 query al secondo. Cloudflare lo dichiara: D1 è progettato per scalare su molti database piccoli, per utente o per tenant, fino a 50.000 per account su Paid.
Ogni database D1 è sostenuto da un singolo Durable Object. Se il tuo carico è fatto di stato per utente con scritture frequenti, vale la pena guardare anche i Durable Objects direttamente, come nel pezzo sul rate limiting su Workers.
Repliche di lettura e Sessions API
Senza repliche, ogni query va al database primario in una sola location. Con la read replication, che attivi per database da dashboard o REST API, D1 crea copie di sola lettura in ogni region supportata: ENAM, WNAM, WEUR, EEUR, APAC e OC. Le scritture vanno sempre al primario. Le repliche non costano di più: paghi le stesse righe lette e scritte.
Le repliche funzionano solo con la Sessions API. Una sessione porta con sé un bookmark, e una replica serve la query solo quando è aggiornata almeno a quel punto. Così leggi le tue scritture anche se la replica è in ritardo. Lo schema della documentazione, ridotto (non l'ho eseguito):
export default {
async fetch(request, env) {
// riparte dal bookmark del client, se c'è
const bookmark = request.headers.get("x-d1-bookmark") ?? "first-unconstrained";
const session = env.DB.withSession(bookmark);
const { results } = await session
.prepare("SELECT id, title FROM posts ORDER BY id DESC LIMIT 10")
.all();
const res = Response.json(results);
res.headers.set("x-d1-bookmark", session.getBookmark() ?? "");
return res;
},
};Un limite dichiarato: la Sessions API esiste solo nel binding dei Workers, non nella REST API. Disattivare le repliche richiede fino a 24 ore.
Backup: Time Travel
Time Travel è sempre attivo e non costa nulla in più. Riporti il database a qualunque minuto degli ultimi 30 giorni su Paid, 7 su Free. Il ripristino è distruttivo: sovrascrive il database e cancella le query in corso. Puoi annullarlo tornando al bookmark precedente.
Per una copia fuori da Cloudflare serve wrangler d1 export. La documentazione segnala tre limiti: niente export con tabelle virtuali (come FTS5), l'export blocca le altre richieste, e i numeri a 64 bit passano dalla precisione di JavaScript. Il ragionamento completo è nel pezzo su backup di D1 con Time Travel ed export.
Un dettaglio per chi ha utenti europei: un database D1 può essere creato con la giurisdizione eu, che vincola dove gira e salva i dati. Va scelta alla creazione: dopo non si può aggiungere.
Turso: SQLite in rete, anche fuori da Cloudflare
Turso offre due motori. libSQL è il fork di SQLite, con lo stesso formato di file e la stessa API, e la documentazione lo indica per i carichi critici di oggi. Turso Database è una riscrittura completa di SQLite, che la documentazione raccomanda per i progetti nuovi e descrive con scritture concorrenti senza lock. Sul blog di Turso le scritture concorrenti su Turso Cloud sono indicate, ad agosto 2026, come anteprima. Entrambi girano su Turso Cloud e sono open source.
La differenza pratica con D1 è il protocollo. Turso si raggiunge via HTTP dal client TypeScript, e la reference dell'SDK cita tra gli ambienti supportati Node.js, funzioni serverless e Cloudflare Workers. Puoi quindi usarlo da Vercel, da un VPS o da un Worker senza cambiare database.
Repliche dentro l'app
Le Embedded Replicas tengono una copia locale del database dentro l'applicazione. Le letture partono dal file locale, le scritture vanno al primario in cloud e poi tornano nella replica. Chi scrive legge subito le proprie scritture; le altre repliche le vedono al sync successivo. La configurazione dalla documentazione (non eseguita):
import { createClient } from "@libsql/client";
const client = createClient({
url: "file:local.db", // replica locale
syncUrl: process.env.TURSO_URL, // primario su Turso Cloud
authToken: process.env.TURSO_TOKEN,
syncInterval: 60, // sync automatico in secondi
});Serve un disco locale, quindi ha senso su VPS, container con volume e app mobili. Non nei Worker. Per i progetti nuovi Turso raccomanda Turso Sync, con push() e pull() espliciti. Sui conflitti la regola documentata è "last push wins": vince l'ultimo push.
Backup e branch
Il ripristino a un punto nel tempo crea un nuovo database, non sovrascrive quello esistente. Devi cambiare la stringa di connessione dell'app e usare un nuovo token o un token di gruppo. I branch funzionano allo stesso modo e si prestano a un database per pull request. Il listino dice che ripristini e branch non aggiungono costi d'uso, ma contano nella quota di database.
Per portare i dati fuori, turso db export scarica uno snapshot in un file SQLite. La documentazione avverte che lo snapshot può non contenere le ultime modifiche.
Una nota su Turso Cloud
Una piccola differenza dal SQLite locale: su Turso Cloud PRAGMA user_version è in sola lettura, secondo la pagina Limitations. Se ci tieni la versione delle migrazioni, serve una tabella dedicata.
La notizia più grande è un'altra. Il 2 ottobre 2026 Turso ha annunciato l'acquisizione da parte di Supabase. Il post promette che la piattaforma continua, che il codice resta open source e che arriverà un percorso verso Postgres dentro Supabase. Per chi sceglie oggi è un dato di lock-in da pesare: il prodotto c'è, la direzione dei prossimi mesi dipende da un altro fornitore.
Postgres gestito: la strada lunga ma standard
Neon fattura a consumo, senza minimo mensile. La compute scala a zero dopo 5 minuti di inattività. Il listino stima circa $15 al mese per un carico intermittente da 140 CU-ora e 1 GB. Se la tieni sempre accesa alla taglia minima da 0,25 CU servono circa 182,5 CU-ora: sul piano Launch sono circa $19,35 di sola compute, un conto mio sul listino. Le repliche di lettura sono compute aggiuntive e consumano CU-ora.
Supabase parte da $25 al mese sul piano Pro, con $10 di crediti che coprono un'istanza Micro, 8 GB di disco e backup giornalieri per 7 giorni. Il ripristino a un punto nel tempo è un add-on da circa $100 al mese per 7 giorni. Durante un ripristino da backup il progetto non è raggiungibile. Se usi Supabase anche per l'autenticazione, il pezzo sulle policy RLS copre la parte che conta di più.
Il costo di Postgres non è solo in fattura. Da funzioni serverless devi gestire connessioni e pooler. Neon offre un driver serverless su HTTP e WebSocket. Su Cloudflare c'è Hyperdrive, incluso nei piani Workers, che tiene il pool vicino al database.
In cambio hai estensioni come pgvector e PostGIS, più servizi che scrivono sugli stessi dati, e un database che si sposta da un fornitore all'altro senza cambiare dialetto.
Lock-in: quanto costa uscire
- D1 usa il dialetto SQLite, e l'export produce un file
.sql. Il lock-in vero è nel codice: binding, Sessions API e bookmark esistono solo nei Workers. - Turso esporta in un file SQLite e il motore è open source. Il client e le repliche sono suoi, e la proprietà dell'azienda è appena cambiata.
- Postgres gestito è il formato più portabile. Il lock-in sta nei servizi intorno: auth, storage, funzioni, branch.
Uscire da SQLite verso Postgres, in una direzione o nell'altra, vuol dire riscrivere le parti di SQL che usano funzioni del dialetto. Un ORM aiuta, ma non toglie tutto. Per la parte ORM c'è il confronto Drizzle vs Prisma con D1 e SQLite.
Quale scegliere
- D1 se il backend è già su Workers, ogni database resta sotto i 10 GB e puoi dividere i dati per utente o tenant. Il backup a 30 giorni incluso è un vantaggio reale per un progetto piccolo.
- Turso se vuoi SQLite ma il codice gira fuori da Cloudflare, su un VPS, su Vercel o in un'app mobile, o se ti servono repliche dentro l'app e molti database piccoli. Pesa l'acquisizione: leggi cosa annuncia Supabase nei prossimi mesi.
- Postgres gestito se più servizi condividono i dati, se ti servono estensioni, o se il database supererà i 10 GB. Costa qualche decina di dollari in più al mese e un pooler.
Se stai ancora scegliendo la piattaforma, la scelta del database segue quella dell'hosting: il confronto Vercel vs Cloudflare vs VPS parte da lì. Per i file, lo stesso ragionamento su egress e API è in R2 vs S3.
Cosa conviene fare adesso
- Scrivi dove girerà il codice tra un anno: solo Workers, un VPS, più piattaforme. È il criterio che elimina un'opzione prima dei prezzi.
- Stima la dimensione del database più grande. Se può superare i 10 GB e non si divide per utente, D1 è fuori.
- Su D1 o Turso, guarda
rows_readnelle tue query più frequenti: un indice mancante si vede subito in fattura. - Prova un ripristino prima di andare in produzione, con Time Travel, un branch Turso o un backup Postgres. Un backup mai ripristinato è una speranza.
- Rileggi i listini il giorno in cui decidi. Questi sono del 28 ottobre 2026 e cambiano.
SQLite non è più solo un file. Ma appena va in rete, scegli anche un protocollo, un client e un fornitore. È quella la parte da confrontare.
Domande frequenti
01Turso o D1: qual è la differenza principale?
Dove li interroghi. D1 si usa da un Worker con un binding, e la REST API serve soprattutto alla gestione. Turso si raggiunge via HTTP da qualunque runtime e può tenere una replica locale dentro l'app. Tutti e due usano il dialetto SQLite e fatturano righe lette, righe scritte e storage.
02Quanto costa D1 in produzione?
Serve il piano Workers Paid, minimo $5 al mese per account. Include 25 miliardi di righe lette, 50 milioni di righe scritte e 5 GB di storage al mese. Oltre: $0,001 per milione di righe lette, $1 per milione scritte, $0,75 per GB-mese. Egress e repliche di lettura non costano extra.
03D1 ha un limite di dimensione?
Sì: 10 GB per database su Workers Paid e 500 MB su Free, e Cloudflare scrive che il limite di 10 GB non si può aumentare. D1 è pensato per molti database piccoli, fino a 50.000 per account su Paid, aumentabili su richiesta.
04Cosa cambia per Turso con l'acquisizione da parte di Supabase?
Secondo l'annuncio del 2 ottobre 2026 la piattaforma continua, database e API funzionano come prima e il motore resta open source. È previsto un percorso verso Postgres dentro Supabase. Per chi sceglie oggi è un fattore di lock-in da tenere d'occhio.
05Come funzionano i backup di D1 e Turso?
D1 ha Time Travel sempre attivo: ripristino a qualunque minuto degli ultimi 30 giorni su Paid, sovrascrivendo il database. Turso ha il ripristino a un punto nel tempo da 1 a 90 giorni secondo il piano, e crea un nuovo database. Per una copia fuori dal fornitore servono wrangler d1 export o turso db export.
06Quando conviene un Postgres gestito invece di SQLite in rete?
Quando più servizi scrivono sugli stessi dati, quando ti servono estensioni come pgvector o PostGIS, o quando un singolo database supererà i limiti di D1. Neon parte a consumo senza minimo, Supabase Pro da $25 al mese.



