Backup di D1: Time Travel, export e cosa fare prima che ti serva

D1 ha già un backup: Time Travel è sempre attivo, gratis, e torna a qualsiasi minuto degli ultimi 30 giorni (7 sul Free). Però ripristina tutto e in place. L'export è la copia che controlli tu. Cosa copre ciascuno e il runbook da scrivere prima che serva.

Francesco Pio Nocerino6 minCloudflare
Backup di D1: Time Travel, export e cosa fare prima che ti serva
Indice

Questo pezzo è per chi ha un'app su Cloudflare Workers con i dati in D1 e non ha mai provato a ripristinarli. D1 ha già un sistema di backup, sempre attivo. Il punto è sapere cosa copre, cosa no, e cosa preparare prima del giorno in cui serve.

In breve: Time Travel è il ripristino point-in-time di D1: è sempre attivo, non costa nulla e torna a qualsiasi minuto degli ultimi 30 giorni sul piano Workers Paid, 7 sul Free. Però sovrascrive l'intero database in place e non crea copie. L'export con wrangler d1 export produce un file .sql che controlli tu, da tenere oltre la finestra o da ripristinare su un database nuovo. Serve tutti e due, più un runbook scritto prima: quale comando, quale bookmark, chi lo lancia.

La domanda giusta

Non "D1 fa i backup?". Li fa. È: da quale errore mi protegge, per quanto tempo, e cosa perdo quando ripristino?

Un DELETE senza WHERE scoperto dopo dieci minuti è un problema diverso da una tabella corrotta scoperta dopo due mesi. Le due cose hanno strumenti diversi.

Time Travel: il backup che c'è già

La documentazione di Time Travel, aggiornata il 21 aprile 2026, è chiara su tre punti. Non va attivato. La cronologia e i ripristini non hanno costi aggiuntivi. Non devi pianificare nulla: D1 crea da solo i punti di ripristino.

Un bookmark è l'identificativo di uno stato del database in un preciso momento. Si ottiene da un timestamp Unix o RFC3339, e la conversione è deterministica: lo stesso timestamp dà sempre lo stesso bookmark. I bookmark più vecchi della finestra di conservazione non valgono più.

Prima di tutto verifica che il database sia sul backend giusto. Serve Wrangler 3.4.0 o successivo, e wrangler d1 info deve mostrare version: production. I database dell'alpha usavano un sistema a snapshot, e l'accesso a quei backup è stato rimosso dal 1° luglio 2025.

I comandi sono due. info restituisce il bookmark attuale, o quello di un momento passato con --timestamp. restore riporta il database a quel bookmark e sovrascrive tutto.

npx wrangler d1 time-travel info mio-db
npx wrangler d1 time-travel info mio-db --timestamp="2026-10-12T14:00:00+02:00"
npx wrangler d1 time-travel restore mio-db --bookmark=<bookmark>

Il restore restituisce un altro bookmark, quello dello stato subito prima del ripristino. Annotalo: è il tuo annulla. Ripristinare a un bookmark non cancella quelli più vecchi, quindi se hai scelto il minuto sbagliato puoi tornare ancora più indietro.

La finestra dipende dal piano. La pagina principale parla di 30 giorni, ma la pagina dei limiti di D1 precisa: 30 giorni su Workers Paid, 7 sul piano Free. In più c'è un tetto di 10 ripristini ogni 10 minuti per database.

Cosa Time Travel non copre

Qui sta la parte che si scopre tardi.

  • Ripristina tutto, in place. La documentazione lo definisce un'operazione distruttiva. Se vuoi recuperare una sola tabella, con Time Travel perdi anche tutte le scritture buone successive al punto scelto.
  • Niente copia da ispezionare. Oggi Time Travel non permette di clonare il database in uno nuovo. La documentazione lo indica come funzione futura. Non puoi guardare lo stato di ieri senza tornarci.
  • Query interrotte. Durante il restore le query in corso vengono cancellate e il client riceve un errore. È un piccolo downtime, da comunicare.
  • La finestra è corta. Un errore scoperto dopo 8 giorni sul Free, o dopo 31 sul Paid, non si recupera.
  • Stessa piattaforma. La cronologia vive dentro D1. La documentazione non descrive il recupero di un database eliminato con wrangler d1 delete. Io su quel caso non conterei su Time Travel.

Un dettaglio per chi cerca un'alternativa dal codice: il metodo dump() del binding D1 funziona solo sui database dell'alpha. Per gli altri la strada è l'export.

Export: la copia che controlli tu

L'export di D1 produce un file SQL con schema e dati. È la copia che puoi tenere dove vuoi e per quanto vuoi. Il primo comando esporta tutto il database, il secondo una sola tabella, il terzo solo lo schema.

npx wrangler d1 export mio-db --remote --output=./backup/mio-db-2026-10-12.sql
npx wrangler d1 export mio-db --remote --table=orders --output=./backup/orders.sql
npx wrangler d1 export mio-db --remote --no-data --output=./backup/schema.sql

Tre limiti dalla documentazione, da sapere prima di affidarti all'export:

  • Niente tabelle virtuali. Se usi FTS5 per la ricerca full-text, l'export del database non è supportato. Il workaround indicato è cancellare le tabelle virtuali, esportare e ricrearle.
  • Blocca il database. Un export in corso blocca le altre richieste. Va lanciato quando il traffico è basso.
  • Numeri grandi. I valori numerici passano dalla precisione dei numeri JavaScript. Un int64 molto grande può tornare meno preciso.

Il ripristino da export si fa con wrangler d1 execute --file, con un limite di 5 GiB per file. Il vantaggio rispetto a Time Travel è che puoi ripristinare su un database nuovo, guardare i dati e recuperare solo le righe che servono:

npx wrangler d1 create mio-db-restore
npx wrangler d1 execute mio-db-restore --remote --file=./backup/mio-db-2026-10-12.sql

Se l'import fallisce sulle foreign key, la documentazione suggerisce PRAGMA defer_foreign_keys = true. Se un INSERT è troppo lungo, va spezzato in più statement.

Export automatico su R2 con Workflows

Un export manuale lo fai il giorno della migrazione. Uno automatico ti copre i mesi in cui non ci pensi.

Cloudflare documenta un esempio con Workflows, aggiornato il 2 giugno 2026. Un Workflow con un campo schedules parte ogni notte e chiama l'endpoint REST di export di D1. Poi aspetta che il dump sia pronto e lo salva in un bucket R2. Serve un token API con il permesso di export, salvato come secret. La pagina stessa avverte che l'esempio è semplificato e che in produzione servono più controlli.

Il costo da guardare è lo storage. Dal listino R2, aggiornato il 1° ottobre 2026: 0,015 dollari per GB al mese in Standard, 0,01 in Infrequent Access, con 10 GB-mese inclusi e uscita dati gratuita. Il conto è dimensione del dump per numero di copie. Una regola di lifecycle sul bucket cancella i dump vecchi senza script.

Time Travel, export, copia esterna

Criterio

Time Travel

Export manuale

Export schedulato su R2

Da attivare

no, sempre attivo

lo lanci tu

Workflow da scrivere

Finestra

30 giorni Paid, 7 Free

quanto tieni il file

quanto tieni i dump

Granularità

qualsiasi minuto

il momento dell'export

una volta per run

Ripristino

in place, tutto il DB

anche su un DB nuovo

anche su un DB nuovo

Una sola tabella

no

sì, a mano

sì, a mano

Costo

nessuno aggiuntivo

nessuno

storage R2

Impatto

query in volo cancellate

blocca le richieste durante l'export

come l'export, ogni notte

La regola pratica: Time Travel per l'errore scoperto subito, l'export per tutto quello che va oltre la finestra o richiede di guardare i dati prima di toccarli.

Il runbook da tenere nel repo

Il backup che non hai mai ripristinato è un'ipotesi. Un runbook breve, in un file RUNBOOK-D1.md accanto alle migrazioni, trasforma l'ipotesi in una procedura. Questo è uno schema generico da adattare, non una ricetta universale:

1. Database: mio-db, binding DB. `wrangler d1 info mio-db` deve dire version: production.
2. Finestra Time Travel: 30 giorni (Paid) o 7 (Free). Scrivi quale.
3. Prima di ogni migrazione: `wrangler d1 time-travel info mio-db`, annota il bookmark.
4. Migrazione rischiosa: export completo in ./backup/, fuori da git.
5. Errore recente: `wrangler d1 time-travel restore mio-db --bookmark=<bookmark>`.
6. Dopo il restore: annota il bookmark di undo che restituisce.
7. Errore su poche righe: ripristina l'export su mio-db-restore e copia solo quelle.
8. Copie oltre la finestra: Workflow notturno verso il bucket d1-backups.
9. Prova di ripristino su mio-db-restore: una volta al mese.
10. Chi può lanciare un restore, e con quale token.

Il punto 4 conta: un dump contiene i dati degli utenti. Va nel bucket o in uno storage cifrato, non nel repository. Nel repo resta la procedura, non i dati.

Cosa conviene fare adesso

  • Lancia wrangler d1 info su ogni database e controlla version: production.
  • Scrivi da qualche parte se sei su Free o Paid: la finestra di Time Travel cambia da 7 a 30 giorni.
  • Prima della prossima migrazione, annota il bookmark con time-travel info. Costa dieci secondi.
  • Fai un export e ripristinalo su un database di prova. È l'unico modo di sapere che funziona.
  • Se usi FTS5, verifica prima come esportare: le tabelle virtuali bloccano l'export.
  • Se i dati valgono più di 7 o 30 giorni di storia, metti in piedi l'export schedulato su R2.

Se stai costruendo lo stack da zero, il pezzo su Workers, D1 e R2 mette D1 nel suo contesto. Se stai ancora scegliendo il database, SQLite vs Postgres per un prodotto indie parla anche di backup e operazioni. Per il confronto tra piattaforme c'è Vercel vs Cloudflare vs VPS, e per gli altri vincoli di Workers il pezzo sul rate limiting.

[ DOMANDE FREQUENTI ]

Domande frequenti

01Cloudflare D1 fa i backup automaticamente?

Sì. Time Travel è sempre attivo e registra la cronologia del database senza configurazione e senza costi aggiuntivi. Permette di tornare a qualsiasi minuto degli ultimi 30 giorni su Workers Paid, o degli ultimi 7 sul piano Free.

02Posso ripristinare una sola tabella con Time Travel?

No. Time Travel ripristina l'intero database in place e sovrascrive anche le scritture successive al punto scelto. Per recuperare una tabella o poche righe serve un export, da ripristinare su un database separato.

03L'export di D1 blocca il database?

Sì. La documentazione dice che un export in corso blocca le altre richieste al database. Conviene lanciarlo nelle ore di traffico basso, anche quando è schedulato.

04Come tengo un backup di D1 per più di 30 giorni?

Con export periodici salvati fuori da D1. L'esempio ufficiale usa un Workflow schedulato che chiama l'API di export e salva il dump in un bucket R2.

Condividi