Chiamare D1 un “database at the edge” crea un'aspettativa che l'architettura non soddisfa pienamente. L'immagine mentale è di SQLite in esecuzione simultaneamente in tutti i 300 data center Cloudflare, con le sue query che rispondono dal punto geograficamente più vicino all'utente. La realtà è più limitata: esiste una regione primaria in cui avvengono tutte le scritture e le repliche di lettura sparse sulla rete che ricevono queste scritture con un ritardo fino a 60 secondi. Se la tua banca principale è in Nord America e scrivi da un Worker che opera a San Paolo, la scrittura impiega da 80 a 150 millisecondi andata e ritorno prima di essere confermata. Quickstart non lo menziona.
La vera architettura di D1
D1 utilizza SQLite come motore di database, lo stesso SQLite che viene eseguito nei browser, nei dispositivi mobili e nelle applicazioni desktop. Oltre a questo motore, Cloudflare ha creato un livello di replica: un'istanza primaria riceve tutte le scritture e propaga le modifiche per leggere le repliche distribuite sulla rete globale.
Quando crei un banco D1, scegli (o lascia che Cloudflare scelga automaticamente) la tua regione principale. Questa scelta determina dove atterrano gli scritti. Una lettura effettuata da un Worker in esecuzione a San Paolo può essere fornita da una replica vicina, con una latenza aggiuntiva compresa tra 5 e 20 millisecondi rispetto al tempo di esecuzione del Worker. Una scrittura effettuata dallo stesso Worker va alla regione primaria e, se questa regione è Us-East-1, il viaggio di andata e ritorno richiede solo da 80 a 150 ms di rete prima di ricevere la conferma.
Il tempo di propagazione della replica è rilevante in produzione: una scrittura sul primario può richiedere fino a 60 secondi per apparire su tutte le repliche. Durante questo intervallo, un lavoratore che legge da una replica obsoleta vede i dati di pre-scrittura. Questo comportamento è chiamato coerenza finale: la replica convergerà allo stato corretto, ma non immediatamente.
Il problema di coerenza che incontrerai nella produzione
Lo schema che rompe con la coerenza finale è la scrittura seguita immediatamente dalla lettura. Crei un utente, reindirizza alla pagina del profilo e la query che carica il profilo raggiunge una replica che non ha ancora ricevuto l'INSERT. Il risultato è un profilo vuoto, o un errore 404, o uno stato incoerente che l'utente vede e non capisce.
Questo problema esiste in qualsiasi database con replica, ma con D1 appare senza preavviso perché l'astrazione di associazione nasconde quale replica viene consultata. Cloudflare ha creato la Sessions API proprio per questo caso: all'interno della stessa sessione D1, una scrittura garantisce che la lettura successiva vedrà i dati scritti, indipendentemente da quale replica serve la query.
L'API Sessions funziona creando una sessione con env.DB.withSession(). All'interno del callback, tutte le query condividono il contesto della sessione e D1 garantisce che le letture post-scrittura restituiscano dati aggiornati. Per i flussi che combinano scrittura e lettura immediata (creazione di account, impostazione di aggiornamenti, completamento degli ordini) l'utilizzo dell'API Sessions è il percorso diretto per evitare incoerenze visibili all'utente.
Per i flussi puramente di sola lettura, come elenchi e dashboard, la coerenza finale non è un problema: i dati possono essere ritardati per alcuni secondi senza alcun impatto evidente.
Prezzo reale: quando il piano gratuito non basta più
Il livello gratuito di D1 offre 5 GB di spazio di archiviazione, 5 milioni di righe lette al giorno e 100mila righe scritte al giorno. Questi numeri sembrano generosi in astratto, ma il costo di lettura di D1 non si basa sulle righe restituite, ma sulle righe esaminate dal motore del database.
Una query che esegue la scansione di 100mila righe per restituirne 5mila consuma 100mila letture, non 5mila. Un'applicazione con mille utenti attivi che effettuano query di elenchi senza indici adeguati può esaurire 5 milioni di letture giornaliere in poche ore. Il livello gratuito è sufficiente per lo sviluppo, gli strumenti interni a basso volume e la prototipazione, non per le applicazioni con traffico di utenti reali.
Quando il livello gratuito non è sufficiente, il passaggio successivo richiede il piano Workers Paid (5 dollari al mese per la piattaforma) più i costi variabili di D1: 0,001 dollari per milione di righe lette, 1 dollaro per milione di righe scritte e 0,75 dollari per GB al mese di storage. Il costo di scrittura ha un funzionamento aritmetico semplice: un flusso di registrazione che inserisce 10 righe per utente ammonta a 10 dollari di costi di scrittura per ogni milione di utenti registrati. Per le applicazioni in rapida crescita, questo numero appare prima del previsto.
Il costo delle letture dipende quasi completamente dalla qualità degli indici. Con indici adeguati, una query che restituisce 20 righe legge 20 righe. Senza indici, la stessa query può leggere 500mila righe e costare 500 volte di più.
Come pianificare la regione primaria prima di creare la banca
La regione primaria D1 è una decisione irreversibile nella creazione della banca. Non è possibile spostare il database primario in un secondo momento: l'alternativa è esportare i dati, creare un nuovo database nella regione desiderata e importarli. Ciò rende la scelta della regione una delle poche decisioni sull'infrastruttura che richiede un'attenta considerazione prima di scrivere la prima riga di codice.
La regola pratica: la regione primaria dovrebbe essere dove ha origine la maggior parte della scrittura. Per un prodotto brasiliano con utenti brasiliani, Worker probabilmente viene eseguito sul PoP di San Paolo (GRU) o simile. Cloudflare offre southamerica-east1 come opzione della regione primaria D1: la scelta di questa regione per un prodotto brasiliano riduce la latenza di scrittura da 80-150 ms a 5-20 ms.
Per verificare quale regione ha più senso, misura la latenza di rete del Worker per la regione candidata utilizzando un semplice fetch con timestamp prima e dopo. Il costo di una scelta sbagliata della regione primaria non appare in fase di sviluppo: appare quando l'applicazione è in produzione e ogni scrittura aggiunge 100 ms di latenza notevole per l'utente.
Nella pianificazione iniziale è compreso anche il limite di 2 GB per banca e 10 banche nel piano a pagamento. Se l'applicazione tende a crescere oltre i 2 GB, è necessario pensare al partizionamento dei dati tra più banchi D1 prima che arrivino i primi dati; il refactoring di questo partizionamento in un secondo momento, con i dati in produzione, richiede molto più lavoro.
Leggi anche
- Cloudflare KV: cosa significa distribuzione globale quando è necessario scrivere
- D1 nella produzione: prestazioni, limiti e cosa non è scalabile da solo
- Migrazioni in D1: come modificare lo schema e cosa succede quando va storto
- Oggetti durevoli di Cloudflare: stato coerente all'edge: cosa cambia veramente
- Operatori Cloudflare in produzione: cosa cambia dopo hello world
- Cloudflare Workers vs Pages: la differenza che conta prima di scegliere
