Backups
Testa il tuo backup di Supabase prima del giorno in cui serve
Come testare il tuo backup di Supabase: ripristinarlo in un progetto di prova, contare le righe, accedere e cercare la riga che manca a un file troncato.

In breve
- Per testare un backup di Supabase, ripristinalo in un progetto che non conta, confronta i numeri di righe con il database in produzione e accedi come te stesso. Solo un ripristino distingue un file buono da uno rotto.
- Abbiamo troncato un dump a metà di una tabella e l'abbiamo ricaricato con le opzioni che raccomanda Supabase. psql ha finito senza alcun errore, e le tabelle sono tornate incomplete.
- Fai la prova una volta adesso, poi ogni tre mesi e dopo ogni cambiamento nel modo in cui viene fatto il backup, e annota la data ogni volta.
Da qualche parte c'è un file con dentro il tuo database. Una GitHub Action ne scrive uno ogni notte, oppure hai lanciato una volta i tre comandi di backup di Supabase, oppure il tuo piano fa copie giornaliere. Ha il nome giusto e più o meno la dimensione che ti aspetteresti. Nessuno l'ha mai aperto.
Ecco la parte che le guide di configurazione rimandano a dopo: un backup che non è mai stato ripristinato è una promessa, non una copia. L'unico modo per testare un backup di Supabase è ripristinarlo, apposta, in un posto dove non conta, e guardare cosa torna. Un dump troncato a metà, un dump senza nemmeno una riga e un dump del progetto sbagliato stanno tutti nello storage con esattamente l'aspetto di uno buono.
Pensa a una prova di evacuazione. Un edificio la fa in una mattina qualunque, quando non brucia niente, perché nessuno dovrebbe scendere quelle scale per la prima volta il giorno in cui si riempiono di fumo. Fuori, qualcuno fa l'appello sulla lista di chi era dentro, e qualcuno annota la data sul foglio vicino alla porta. Una prova di ripristino è la stessa cosa: fare il percorso, contare, annotare.
Come faccio a sapere se il mio backup di Supabase funziona davvero?
Ripristinalo e guarda. È l'unico test che esista, perché niente nel file in sé separa un backup buono da uno rotto.
La prova prende la tua copia più recente, la ricarica in un progetto che non conta e fa tre domande al risultato. C'è ogni tabella, con più o meno tante righe quante quella in produzione? La riga più recente è della notte in cui è stata fatta la copia? Riesci ad accedere come te stesso? Un file buono risponde sì a tutte e tre, e ogni modo in cui un backup va storto ne fallisce almeno una.
Cinque modi in cui un backup è sbagliato e sembra giusto lo stesso
Tutti e cinque finiscono nella notte senza errori, e tutti e cinque lasciano un file con il solito nome nel solito posto. Si distinguono solo quando il file viene ricaricato.
| Cosa non va nel file | Come ci arriva, di solito | Il passo della prova che lo scopre |
|---|---|---|
| Si ferma a metà | Uno script che passa pg_dump a gzip riporta cosa ha fatto gzip. Un dump morto a metà viene salvato, e il job dice che è andato tutto bene. Un disco pieno o un caricamento che si è arreso fanno lo stesso | La riga finale, poi i conteggi |
| Ha le tue tabelle e nessuna delle righe | supabase db dump è stato lanciato senza --data-only, e così scrive solo la struttura | I conteggi: ogni tabella a zero |
| Ha le righe e nessuno degli account | Il dump ha nominato solo il tuo schema, e i tuoi utenti vivono in uno chiamato auth | La ricerca di auth.users, poi l'accesso |
| Sono i dati di un altro progetto | La connection string punta a una copia di staging o a un vecchio progetto | La riga più recente, del giorno sbagliato |
| Non si carica affatto | Un dump di Postgres 17 ricaricato in Postgres 15, o righe di proprietario che il nuovo progetto rifiuta | Il ripristino si ferma con un errore |
Il secondo e il terzo sono l'argomento di perché il tuo dump di Supabase non ha utenti, ed entrambi nascono da un comando di dump lanciato con meno opzioni di quelle che servivano. Il primo ci ha sorpreso, quindi ha una sezione tutta sua.
Un file di backup troncato fallisce al ripristino?
Non sempre. Ne abbiamo troncato uno a metà di una tabella, l'abbiamo ricaricato
con le opzioni che usa la guida stessa di Supabase, e psql ha finito senza
alcun errore.
Il test era piccolo e facile da ripetere. Il 27 settembre 2026 abbiamo fatto il
dump di un database con due tabelle, una da 5.000 righe e una da 300, troncato
il file in tre punti diversi e ricaricato ogni versione con psql di Postgres
17.11. Ogni caricamento ha usato --single-transaction e
--variable ON_ERROR_STOP=1, le due opzioni che servono a fermare un
ripristino al primo problema e annullare tutto.
- Troncato a metà di un valore,
psqlsi è fermato con un errore e non ha scritto niente. È il risultato che ti augureresti. - Troncato dentro l'ultima colonna di una riga, è finito con codice di uscita 0, che è il modo in cui un programma dice di aver avuto successo. La prima tabella è tornata con 2.596 delle sue 5.000 righe, all'ultima mancava metà del testo, e la seconda tabella è tornata vuota.
- Troncato esattamente tra le due tabelle, è finito anche lui con 0. La prima tabella era completa e la seconda vuota.
Il motivo sta nel modo in cui un dump conserva le righe. Le righe di ogni
tabella stanno in un blocco che finisce con una riga che contiene solo \., e
quando il file finisce prima di quella riga, psql prende la fine del file per
la fine del blocco. L'unico segno che doveva esserci dell'altro è una riga che
sarebbe dovuta stare proprio alla fine.
Quella riga è la firma di pg_dump. Un dump completo contiene le parole
PostgreSQL database dump complete verso la fine, e uno troncato no. Dei tre
file che scrive la CLI di Supabase, la riga sopravvive solo in data.sql,
perché la CLI toglie tutti i commenti dal file dello schema (verificato con la
versione 2.111 della CLI). Quindi data.sql è il file in cui cercare, e quella
ricerca è il secondo passo della prova.
Dove dovrei ripristinarlo?
In un progetto Supabase che non conta: un progetto di prova nel tuo account, o un Supabase che gira sul tuo computer. Mai nel progetto che usa la tua app.
Un progetto di prova su Supabase è la cosa più simile al tuo progetto reale, ed è la destinazione per cui è scritta la guida di Supabase a backup e ripristino: il suo primo passo è creare un nuovo progetto. Con il piano gratuito hai diritto a due progetti gratuiti attivi, e quelli in pausa non contano, quindi un progetto di prova di solito non costa niente finché il tuo database sta nel piano gratuito. In un'organizzazione a pagamento, il calcolo di un nuovo progetto viene addebitato a ore, quindi eliminalo quando la prova è finita.
Supabase sul tuo computer non costa niente e non richiede un account. La
CLI di Supabase fa girare tutto lo stack in locale con Docker:
supabase init, poi supabase start,
e mostra un indirizzo del database sulla porta 54322 e una publishable key per
il progetto locale. Prima di avviarlo, apri supabase/config.toml e imposta
major_version sulla versione principale di Postgres del tuo progetto. Il
commento sopra quell'impostazione dice che devono coincidere, e la versione
del tuo progetto è in Project Settings, poi General.
Su Postgres 15 c'è un tranello. A meno che il job di backup non abbia fissato
una versione, la CLI ha fatto la copia con pg_dump 17, e il file dei dati
contiene allora, vicino all'inizio, SET transaction_timeout = 0,
un'impostazione che Postgres 15 non riconosce, quindi il caricamento si ferma su
quella riga. Per la prova, imposta major_version su 17. Poi applica al job di
backup la correzione di una riga descritta
nell'articolo sulla GitHub Action, perché
il progetto in cui ripristineresti davvero è ancora su 15.
Un Postgres nudo in Docker, senza niente di Supabase dentro, non basta. Un dump
di Supabase fa riferimento a cose che crea solo Supabase, come lo schema auth
in cui vivono i tuoi utenti e il ruolo authenticated nominato dalle tue
regole di sicurezza, e il ripristino si ferma alla prima riga che ne menziona
una.
Una cautela, perché il progetto di prova ora contiene una copia reale. Ci sono dentro gli indirizzi email dei tuoi utenti, quindi non collegarci né la tua app né i suoi webhook, ed eliminalo quando hai finito.
I job pianificati sono la parte che non arriva. Se il tuo progetto li esegue con
l'estensione pg_cron, i tre file della CLI riportano l'estensione e nessuno
dei suoi job, perché i job sono righe di cron.job e il dump dei dati lascia
fuori quelle righe. L'abbiamo verificato il 4 ottobre 2026 con la versione 2.119
della CLI, ripristinando un database che aveva un job pianificato. Il progetto
di prova resta quindi tranquillo, e anche un ripristino vero da questi file
parte senza alcun job pianificato, quindi tieni le tue chiamate a
cron.schedule in un posto da cui puoi rieseguirle.
Come testare un backup di Supabase, passo per passo
Sei passi, e i primi tre avvengono prima di ripristinare qualsiasi cosa.
- Trova la copia più recente e leggi la sua data. Se è più vecchia dell'ultima esecuzione programmata, il job si è fermato, ed è la tua prima scoperta.
- Cerca
dump completeindata.sql. Un risultato significa che il file è arrivato alla fine. Nessuno significa che è stato troncato, qualunque sia la sua dimensione. La ricerca di un editor di testo funziona quanto un terminale:grep -c 'dump complete' data.sql - Cercaci dentro i tuoi utenti. Una riga che inizia con
COPY "auth"."users"con delle righe sotto significa che i tuoi account sono nel file:grep -n 'COPY .*auth.*users' data.sql - Ricaricalo nel progetto di prova con il comando della guida di
Supabase, puntato sulla connection string del progetto di prova. Su un
Supabase locale quella stringa è
postgresql://postgres:postgres@127.0.0.1:54322/postgres.psql \ --single-transaction \ --variable ON_ERROR_STOP=1 \ --file roles.sql \ --file schema.sql \ --command 'SET session_replication_role = replica' \ --file data.sql \ --dbname "postgresql://…the spare's connection string…" - Conta le righe e leggi la più recente, in entrambi i database. La query è nella prossima sezione.
- Accedi al progetto di prova come te stesso. Il comando è nella sezione successiva.
Se il passo 4 si ferma con un errore, la prova ha già fatto il suo lavoro. Le note di risoluzione dei problemi in fondo alla guida di Supabase coprono i due errori più comuni, entrambi sui ruoli, e come ripristinare un backup di Supabase spiega da cosa ti protegge ogni opzione di quel comando.
Mancano in quelle note altri due arresti in roles.sql. Li abbiamo incontrati
entrambi il 4 ottobre 2026, ricaricando i file di due database Postgres 17, uno
dei quali un progetto Supabase, in una copia locale nuova di Supabase:
"supabase_admin" is a reserved role, only superusers can modify it, su una
riga che inizia con ALTER ROLE "supabase_admin", e
permission denied for parameter log_min_messages, su una riga che inizia con
GRANT SET ON PARAMETER. Entrambe le righe configurano ruoli che Supabase crea
da sé in ogni progetto, quindi metti -- all'inizio di ciascuna per
trasformarla in un commento e riesegui il comando.
La nostra Action di backup
le commenta già quando fa la copia.
Cosa contare, e rispetto a cosa
Conta ogni tabella nel progetto di prova e nel tuo progetto in produzione con la stessa query, e metti le due liste una accanto all'altra. La copia dovrebbe essere una notte indietro rispetto al database in produzione: un po' più bassa su una tabella che cresce, e mai a zero su una tabella che aveva righe.
È l'appello sulla lista di chi era dentro. Incolla la query nell'editor SQL di
ogni progetto e premi Run. Conta le righe di ogni tabella del tuo schema e di
auth:
select table_schema, table_name,
(xpath('/row/n/text()',
query_to_xml(format('select count(*) as n from %I.%I', table_schema, table_name),
false, true, '')))[1]::text::bigint as row_count
from information_schema.tables
where table_schema in ('public', 'auth')
and table_type = 'BASE TABLE'
order by table_schema, table_name;
Legge ogni riga di ogni tabella, quindi su un database grande lanciala fuori dalle tue ore più affollate.
Poi leggi la riga più recente di una tabella che conosci, solo nel progetto di
prova. Va bene qualsiasi tabella con una colonna created_at; metti il suo
nome al posto di orders:
select max(created_at) from public.orders;
La risposta dovrebbe essere vicina all'ora in cui è girato il backup. Una data più vecchia di settimane, o righe che non riconosci, significano che il file viene da un altro progetto.
| Controllo | Dove | Cosa mostra una copia buona |
|---|---|---|
| Le righe di ogni tabella | Entrambi | Le stesse tabelle, ognuna un po' indietro rispetto alla produzione, nessuna vuota che avesse righe |
| La riga più recente | Progetto di prova | Un'ora della notte in cui è stata fatta la copia |
| Il tuo account | Progetto di prova | La tua email in auth.users |
| Un accesso | Progetto di prova | Torna un token |
Perché l'accesso è il test che dimostra i tuoi account
Un conteggio di auth.users dimostra che le righe sono arrivate. Un accesso
dimostra che funzionano: che la password salvata, il servizio di accesso del
progetto di prova e il tuo indirizzo email vanno ancora d'accordo.
Usa il tuo account, con una password che conosci. L'indirizzo del progetto e
la publishable key del progetto di prova sono nel suo pannello Connect, o
nell'output di supabase start su un Supabase locale:
curl -X POST 'https://…the spare's project ref….supabase.co/auth/v1/token?grant_type=password' \
-H "apikey: sb_publishable_…" \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "…"}'
È la chiamata di accesso della
documentazione di Supabase stessa,
diretta al progetto di prova. Una risposta che contiene access_token
significa che il tuo account è arrivato con una password che funziona.
Invalid login credentials, per un account che accede senza problemi alla tua
app in produzione, significa che non è arrivato, e
perché un dump arriva senza gli account è
l'articolo per quel risultato.
Se tutti accedono alla tua app con Google, questa chiamata non ha niente da
testare, perché nel progetto di prova non c'è un accesso con Google
configurato. Cerca invece la tua email in auth.users dopo il ripristino.
Questo mostra che la riga dell'account è arrivata, anche se non che la sua
password funziona.
I file: la metà che un ripristino del database non può testare
La copia del database contiene una riga per ogni file caricato e nessuno dei file. Se copi i tuoi bucket di Storage con un job a parte, che è l'unico modo in cui vengono copiati, fai fare la prova anche a quella copia.
Prendi le tre righe più recenti dal database ripristinato:
select bucket_id, name from storage.objects order by created_at desc limit 3;
Trova quei tre percorsi nella tua copia dei file e aprili uno per uno. Un percorso senza un file dietro è un'immagine che i tuoi utenti vedrebbero rotta dopo un vero ripristino.
Posso testare i backup che Supabase fa per me?
Con un piano a pagamento sì, con Restore to a New Project. È l'unico modo per aprire una delle copie giornaliere di Supabase, perché sui progetti attuali non puoi scaricarle.
Supabase descrive la funzione come un modo per
fare test in sicurezza.
Scegli una copia nella scheda Restore to a New Project della pagina Backups, e
Supabase ne costruisce un nuovo progetto con i tuoi utenti e le loro password
hashate, pronto per gli stessi conteggi e lo stesso accesso. Due cose da sapere
prima di premere. Il nuovo progetto viene fatturato come un progetto a sé, e
Supabase ti mostra il costo prima di partire. E copia tutto, job pianificati
compresi: Supabase dice che i job di pg_cron, pg_net e dei wrapper partono
appena il ripristino è completato, senza modo di metterli in pausa prima. Se un
job della tua app manda email o addebita una carta, lo farà anche il progetto di
test.
Se tieni anche un file fuori dall'account, quel file ha bisogno di una prova tutta sua.
Ogni quanto dovrei testare un ripristino?
Una volta adesso, poi ogni tre mesi, e di nuovo ogni volta che cambia qualcosa nel modo in cui viene fatto il backup.
I cambiamenti che contano sono quelli che rompono un backup in silenzio: un workflow nuovo o modificato, una password del database reimpostata, il passaggio a un nuovo piano o a una nuova versione di Postgres, una nuova tabella in cui la tua app ha cominciato a scrivere. Dopo ognuno di questi, la prova del trimestre scorso non descrive più il file di questo trimestre.
Poi annotalo: è il foglio vicino alla porta. Una riga per prova, in un posto che raggiungi senza ciò che si è rotto: la data, quale file, i conteggi che contavano, se l'accesso ha funzionato e quanto è durata tutta la prova. Basta un file di testo nel repository del backup, e va bene anche un evento ricorrente nel calendario con i risultati incollati dentro. La data risponde a «quando l'abbiamo dimostrato l'ultima volta» nell'ora in cui qualcuno ha bisogno di saperlo, e la durata è la tua prima stima di quanto un vero ripristino terrebbe ferma la tua app.
Dove si inserisce Reeve Care
Care conserva copie del tuo database Supabase fuori dal tuo account Supabase, secondo l'orario del tuo piano, controlla ogni copia mentre viene fatta e la rimette al suo posto con un pulsante.
- Le copie seguono l'orario del tuo piano, da una volta al giorno fino a ogni sei ore.
- Una copia troncata viene scoperta mentre viene fatta. La riga finale di
pg_dumpdeve essere nel file, altrimenti la copia non supera il controllo e non diventa mai la data nella tua dashboard. - Ogni tabella viene contata mentre la copia viene scritta. Quando una tabella che aveva righe nella copia precedente non ne ha nessuna in questa, una persona di Reeve lo viene a sapere.
- I tuoi account ci sono, e anche i tuoi file caricati arrivano non appena colleghi una credenziale di Storage.
- Ripristinare è un pulsante, e prima di sostituire qualsiasi cosa viene fatta una copia dello stato attuale.
- Ogni copia si scarica come zip con
schema.sql,data.sql,roles.sqle un manifest con il numero di righe di ogni tabella, che è la metà «rispetto a cosa» di questo articolo, già scritta.
Una prova trimestrale dimostra la copia che hai scelto quel giorno, e il controllo gira su ogni copia mentre viene fatta. La copia, il controllo e il ripristino sono disegnati passo per passo nella pagina sui backup di Supabase, e cosa include ogni piano, orario compreso, è nella pagina dei prezzi.
Cosa fare questa settimana
Cosa fare
- Trova il tuo backup più recente e leggi la sua data. Se è più vecchio dell'ultima esecuzione programmata, sistema il job prima di tutto.
- Cerca
dump completeeCOPY "auth"."users"indata.sql. Due ricerche ti dicono se il file arriva alla fine e se i tuoi account ci sono. - Crea un progetto di prova, o avvia Supabase sul tuo computer, e ricarica il file con il comando
psqldella guida di Supabase. - Lancia la query di conteggio su entrambi i database e metti le due liste una accanto all'altra. Leggi la riga più recente di una tabella che conosci.
- Accedi al progetto di prova come te stesso.
- Annota la data, i conteggi e quanto è durata, poi elimina il progetto di prova.
Prima di chiudere questa scheda, cerca dump complete nel tuo data.sql più
recente. È una sola ricerca, e ti dice se il file che chiami backup arriva alla
sua ultima riga. Se non hai ancora un file in cui cercare,
una GitHub Action gratuita è il modo più
rapido per cominciare a produrne.
FAQ
Come faccio a sapere se il mio backup di Supabase funziona davvero?
Ripristinalo in un progetto che non conta e guarda cosa torna. Confronta il numero di righe di ogni tabella con il database in produzione, controlla che la riga più recente sia della notte in cui è stata fatta la copia e accedi come te stesso. Niente nel file in sé distingue un dump buono da uno rotto: nome, dimensione e la spunta verde accanto al job sono uguali in entrambi i casi.
Ogni quanto dovrei testare un ripristino?
Una volta adesso, poi ogni tre mesi, e di nuovo ogni volta che cambia il modo in cui viene fatto il backup: un workflow nuovo o modificato, una password del database reimpostata, un nuovo piano o una nuova versione di Postgres, o una nuova tabella in cui scrive la tua app. Annota la data ogni volta, con i conteggi e quanto è durata, così la domanda su quando è stato dimostrato l'ultima volta ha una risposta.
Posso testare un ripristino senza toccare il database in produzione?
Sì, ed è sempre così che dovresti farlo. Ripristina in un progetto di prova su Supabase, cosa che il piano gratuito consente, o in un Supabase che gira sul tuo computer con la CLI e Docker. L'unica cosa che la prova fa al database in produzione è leggerlo una volta per contarne le righe. Elimina il progetto di prova alla fine, perché contiene una copia reale dei tuoi utenti.
Cosa dovrei controllare dopo aver ripristinato un backup?
Quattro cose. Il numero di righe di ogni tabella accanto a quello in produzione, dove la copia dovrebbe essere un po' indietro e mai a zero per una tabella che aveva righe. La riga più recente di una tabella che conosci, che dovrebbe essere della notte della copia. La tua email in auth.users. E un accesso come te stesso, l'unico controllo che dimostra che gli account funzionano e non solo che sono arrivati.
Il ripristino ha funzionato, ma nessuno riesce ad accedere. Perché?
Quasi sempre perché il file non ha mai contenuto i tuoi account. Supabase li tiene in uno schema chiamato auth, e un dump che ha nominato solo il tuo schema, o un supabase db dump senza opzioni, li lascia fuori mentre ogni tua tabella si ripristina senza problemi. Cerca prima COPY "auth"."users" nel file. Se manca, fai un dump dei dati con --data-only, che attraversa lo schema auth e porta con sé i tuoi utenti.
Un file di backup troncato fallisce al ripristino?
Non sempre. Abbiamo troncato un file di pg_dump in tre punti e ricaricato ogni versione con --single-transaction e ON_ERROR_STOP, le opzioni della guida al ripristino di Supabase. Un taglio a metà di un valore si è fermato con un errore. Un taglio dentro l'ultima colonna di una riga e un taglio tra due tabelle sono finiti entrambi senza errori, con le tabelle incomplete. Un dump completo contiene la riga PostgreSQL database dump complete verso la fine, quindi cercala prima di fidarti di un file.