[{"data":1,"prerenderedAt":1224},["ShallowReactive",2],{"blog-de-test-your-supabase-backup":3,"blog-index-de":871},{"id":4,"title":5,"body":6,"category":827,"cover":828,"coverAlt":829,"description":830,"draft":831,"extension":832,"faq":833,"image":849,"keywords":850,"meta":859,"navigation":860,"ogTitle":5,"path":861,"published":862,"seo":863,"stem":864,"tldr":865,"updated":869,"__hash__":870},"blog_de\u002Fblog\u002Ftest-your-supabase-backup.md","Teste dein Supabase-Backup, bevor du es brauchst",{"type":7,"value":8,"toc":811},"minimark",[9,13,21,24,29,32,35,39,42,146,155,161,165,172,186,211,221,238,243,247,250,275,301,319,329,332,347,351,354,429,437,470,474,477,483,491,494,505,511,514,575,579,585,590,596,617,623,627,635,638,644,647,651,658,674,677,681,684,687,690,694,699,749,762,766,798],[10,11,12],"p",{},"Irgendwo liegt eine Datei mit deiner Datenbank darin. Eine GitHub Action\nschreibt jede Nacht eine, oder du hast Supabases drei Backup-Befehle einmal\nausgeführt, oder dein Tarif zieht tägliche Kopien. Sie hat den richtigen Namen\nund ungefähr die Größe, die du erwarten würdest. Geöffnet hat sie noch nie\njemand.",[10,14,15,16,20],{},"Hier ist der Teil, den die Einrichtungsanleitungen auf später verschieben:\n",[17,18,19],"strong",{},"ein Backup, das nie wiederhergestellt wurde, ist eine Behauptung, keine\nKopie."," Die einzige Art, ein Supabase-Backup zu testen, ist, es absichtlich\nirgendwo einzuspielen, wo nichts davon abhängt, und nachzusehen, was\nzurückkommt. Ein Dump, der mittendrin abbricht, ein Dump ohne eine einzige\nZeile und ein Dump des falschen Projekts liegen alle im Speicher und sehen\ngenau aus wie ein guter.",[10,22,23],{},"Denk an einen Probealarm. Ein Gebäude macht ihn an einem gewöhnlichen Vormittag,\nwenn nichts brennt, weil niemand die Treppe zum ersten Mal an dem Tag\nhinuntergehen sollte, an dem sie voller Rauch ist. Draußen zählt jemand die\nLeute anhand der Liste, wer drin war, und jemand schreibt das Datum auf das\nBlatt an der Tür. Eine Wiederherstellungsübung ist dasselbe: den Weg gehen,\nzählen, aufschreiben.",[25,26,28],"h2",{"id":27},"woher-weiß-ich-ob-mein-supabase-backup-wirklich-funktioniert","Woher weiß ich, ob mein Supabase-Backup wirklich funktioniert?",[10,30,31],{},"Spiel es ein und sieh nach. Das ist der einzige Test, den es gibt, denn an der\nDatei selbst lässt sich ein gutes Backup nicht von einem kaputten\nunterscheiden.",[10,33,34],{},"Die Übung nimmt deine neueste Kopie, spielt sie in ein Projekt ein, an dem\nnichts hängt, und stellt dem Ergebnis drei Fragen. Ist jede Tabelle da, mit\nungefähr so vielen Zeilen wie die Live-Tabelle? Stammt die neueste Zeile aus\nder Nacht, in der die Kopie gezogen wurde? Kannst du dich als du selbst\nanmelden? Eine gute Datei beantwortet alle drei mit Ja, und jede Art, wie ein\nBackup schiefgeht, scheitert an mindestens einer davon.",[25,36,38],{"id":37},"fünf-arten-wie-ein-backup-falsch-ist-und-trotzdem-richtig-aussieht","Fünf Arten, wie ein Backup falsch ist und trotzdem richtig aussieht",[10,40,41],{},"Alle fünf laufen in der Nacht ohne Fehler durch, und alle fünf hinterlassen\neine Datei mit dem üblichen Namen am üblichen Ort. Auseinander gehen sie erst,\nwenn die Datei eingespielt wird.",[43,44,45,61],"table",{},[46,47,48],"thead",{},[49,50,51,55,58],"tr",{},[52,53,54],"th",{},"Was mit der Datei nicht stimmt",[52,56,57],{},"Wie es meistens dazu kommt",[52,59,60],{},"Der Schritt der Übung, der es findet",[62,63,64,88,106,124,135],"tbody",{},[49,65,66,70,85],{},[67,68,69],"td",{},"Sie hört mittendrin auf",[67,71,72,73,77,78,81,82,84],{},"Ein Skript, das ",[74,75,76],"code",{},"pg_dump"," an ",[74,79,80],{},"gzip"," weiterreicht, meldet das Ergebnis von ",[74,83,80],{},". Ein Dump, der auf halbem Weg starb, wird gespeichert, und der Job meldet Erfolg. Eine volle Platte oder ein abgebrochener Upload tun dasselbe",[67,86,87],{},"Die Schlusszeile, dann die Zählungen",[49,89,90,93,103],{},[67,91,92],{},"Sie hat deine Tabellen und keine Zeilen",[67,94,95,98,99,102],{},[74,96,97],{},"supabase db dump"," lief ohne ",[74,100,101],{},"--data-only"," und schreibt dann nur die Struktur",[67,104,105],{},"Die Zählungen: jede Tabelle bei null",[49,107,108,111,117],{},[67,109,110],{},"Sie hat die Zeilen und keine Konten",[67,112,113,114],{},"Der Dump hat nur dein eigenes Schema genannt, und deine Nutzer leben in einem namens ",[74,115,116],{},"auth",[67,118,119,120,123],{},"Die Suche nach ",[74,121,122],{},"auth.users",", dann die Anmeldung",[49,125,126,129,132],{},[67,127,128],{},"Es sind die Daten eines anderen Projekts",[67,130,131],{},"Der Connection String zeigt auf eine Staging-Kopie oder ein altes Projekt",[67,133,134],{},"Die neueste Zeile, vom falschen Tag",[49,136,137,140,143],{},[67,138,139],{},"Sie lässt sich gar nicht einspielen",[67,141,142],{},"Ein Dump aus Postgres 17, eingespielt in Postgres 15, oder Owner-Zeilen, die das neue Projekt ablehnt",[67,144,145],{},"Die Wiederherstellung bricht mit einem Fehler ab",[10,147,148,149,154],{},"Um die zweite und dritte geht es in\n",[150,151,153],"a",{"href":152},"\u002Fblog\u002Fsupabase-backup-auth-users","warum dein Supabase-Dump keine Nutzer enthält",",\nund beide entstehen durch einen Dump-Befehl mit weniger Flags, als er gebraucht\nhätte. Die erste hat uns überrascht, deshalb bekommt sie einen eigenen\nAbschnitt.",[156,157],"diagram",{"alt":158,"caption":159,"src":160},"Sechs gleiche versiegelte Dateien in einer Reihe, jede fällt in eine wiederhergestellte Datenbank. Die erste hat volle Tabellen und ein Register mit Personen, abgehakt. Fünf sind durchgestrichen: eine gekürzte Tabelle neben einer leeren, alle Tabellen leer, ein leeres Register, graue Zeilen mit Ungleich-Zeichen und ein an einem Balken gestoppter Import.","Im Speicher sehen alle sechs Dateien gleich aus. Eingespielt gibt dir nur die erste die Datenbank zurück, die du hattest.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fsix-files-one-good-copy-1600x760.png",[25,162,164],{"id":163},"schlägt-die-wiederherstellung-einer-abgeschnittenen-backup-datei-fehl","Schlägt die Wiederherstellung einer abgeschnittenen Backup-Datei fehl?",[10,166,167,168,171],{},"Nicht immer. Wir haben eine mitten in einer Tabelle abgeschnitten, mit den\nFlags eingespielt, die Supabases eigene Anleitung verwendet, und ",[74,169,170],{},"psql"," lief\nohne Fehler durch.",[10,173,174,175,177,178,181,182,185],{},"Der Test war klein und leicht nachzumachen. Am 27. September 2026 haben wir\neine Datenbank mit zwei Tabellen gedumpt, eine mit 5.000 Zeilen und eine mit\n300, die Datei an drei verschiedenen Stellen abgeschnitten und jede Version mit\n",[74,176,170],{}," aus Postgres 17.11 eingespielt. Jeder Lauf nutzte\n",[74,179,180],{},"--single-transaction"," und ",[74,183,184],{},"--variable ON_ERROR_STOP=1",", die beiden Flags, die\neine Wiederherstellung beim ersten Problem anhalten und alles rückgängig machen\nsollen.",[187,188,189,199,205],"ul",{},[190,191,192,195,196,198],"li",{},[17,193,194],{},"Schnitt mitten in einem Wert:"," ",[74,197,170],{}," brach mit einem Fehler ab und\nschrieb nichts. Das ist das Ergebnis, auf das du hoffen würdest.",[190,200,201,204],{},[17,202,203],{},"Schnitt in der letzten Spalte einer Zeile:"," Der Lauf endete mit Exit-Code\n0, so meldet ein Programm Erfolg. Die erste Tabelle kam mit 2.596 ihrer 5.000\nZeilen zurück, der letzten davon fehlte die Hälfte ihres Texts, und die\nzweite Tabelle kam leer zurück.",[190,206,207,210],{},[17,208,209],{},"Schnitt genau zwischen den beiden Tabellen:"," Auch hier Exit-Code 0. Die\nerste Tabelle war vollständig, die zweite leer.",[10,212,213,214,217,218,220],{},"Der Grund liegt darin, wie ein Dump Zeilen speichert. Die Zeilen jeder Tabelle\nstehen in einem Block, der mit einer Zeile endet, in der nur ",[74,215,216],{},"\\."," steht. Endet\ndie Datei vor dieser Zeile, nimmt ",[74,219,170],{}," das Dateiende als Ende des Blocks. Das\neinzige Zeichen, dass noch mehr kommen sollte, ist eine Zeile, die ganz am Ende\nhätte stehen müssen.",[10,222,223,224,226,227,230,231,234,235,237],{},"Diese Zeile ist die Abschlussformel von ",[74,225,76],{},". Ein vollständiger Dump\nenthält kurz vor dem Ende die Worte ",[74,228,229],{},"PostgreSQL database dump complete",", und\nein abgeschnittener nicht. Von den drei Dateien, die die Supabase CLI schreibt,\nüberlebt die Zeile nur in ",[74,232,233],{},"data.sql",", weil die CLI jeden Kommentar aus der\nSchema-Datei entfernt (geprüft mit Version 2.111 der CLI). Damit ist ",[74,236,233],{},"\ndie Datei, in der du suchst, und die Suche ist der zweite Schritt der Übung.",[156,239],{"alt":240,"caption":241,"src":242},"Eine Datei mit abgerissenem unteren Rand führt in einen Wiederherstellungsschritt mit ON_ERROR_STOP=1 und grünem Haken. Dahinter zwei Tabellen: die erste etwa zur Hälfte gefüllt, 2596 von 5000, mit abgerissener letzter Zeile; die zweite leer, 0 von 300.","Der Import meldete Erfolg. Die erste Tabelle kam halb voll zurück, die zweite leer.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fa-short-file-restores-clean-1600x680.png",[25,244,246],{"id":245},"wo-soll-ich-es-einspielen","Wo soll ich es einspielen?",[10,248,249],{},"In ein Supabase-Projekt, an dem nichts hängt: ein Übungsprojekt in deinem\nKonto oder ein Supabase, das auf deinem eigenen Rechner läuft. Nie in das\nProjekt, das deine App benutzt.",[10,251,252,255,256,262,263,268,269,274],{},[17,253,254],{},"Ein Übungsprojekt bei Supabase"," kommt deinem echten Projekt am nächsten, und\ngenau dafür ist\n",[150,257,261],{"href":258,"rel":259},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fmigrating-within-supabase\u002Fbackup-restore",[260],"nofollow","Supabases Anleitung zu Backup und Wiederherstellung","\ngeschrieben: Ihr erster Schritt ist, ein neues Projekt anzulegen. Im\nFree-Tarif stehen dir\n",[150,264,267],{"href":265,"rel":266},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fbilling-faq",[260],"zwei aktive kostenlose Projekte zu",",\npausierte zählen nicht mit, also kostet ein Übungsprojekt meistens nichts,\nsolange deine Datenbank in den Free-Tarif passt. In einer bezahlten\nOrganisation wird die Rechenleistung eines neuen Projekts\n",[150,270,273],{"href":271,"rel":272},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fmanage-your-usage\u002Fcompute",[260],"stundenweise berechnet",",\nalso lösch es, wenn die Übung vorbei ist.",[10,276,277,280,281,292,293,296,297,300],{},[17,278,279],{},"Supabase auf deinem eigenen Rechner"," kostet nichts und braucht kein Konto.\nDie Supabase CLI startet den ganzen Stack lokal in Docker:\n",[150,282,285,288,289],{"href":283,"rel":284},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Flocal-development\u002Fcli\u002Fgetting-started",[260],[74,286,287],{},"supabase init",", dann ",[74,290,291],{},"supabase start",",\nund sie gibt eine Datenbankadresse auf Port 54322 und einen Publishable Key für\ndas lokale Projekt aus. Bevor du es startest, öffne ",[74,294,295],{},"supabase\u002Fconfig.toml"," und\nsetz ",[74,298,299],{},"major_version"," auf die Postgres-Hauptversion deines Projekts. Der\nKommentar über dieser Einstellung sagt, dass sie übereinstimmen muss, und die\nVersion deines Projekts findest du unter Project Settings, dann General.",[10,302,303,304,306,307,310,311,313,314,318],{},"Bei Postgres 15 gibt es einen Haken. Hat der Backup-Job keine Version\nfestgelegt, hat die CLI die Kopie mit ",[74,305,76],{}," 17 erstellt, und die Datendatei\nenthält dann weit oben ",[74,308,309],{},"SET transaction_timeout = 0",", eine Einstellung, die\nPostgres 15 nicht kennt, also bricht das Einspielen an dieser Zeile ab. Setz für\ndie Übung ",[74,312,299],{}," auf 17. Gib dem Backup-Job danach die einzeilige\nKorrektur aus\n",[150,315,317],{"href":316},"\u002Fblog\u002Fsupabase-backup-github-action","dem Artikel zur GitHub Action",", denn das\nProjekt, in das du im Ernstfall wiederherstellen würdest, läuft weiter auf 15.",[10,320,321,322,324,325,328],{},"Ein nacktes Postgres in Docker, ohne etwas von Supabase darin, reicht nicht.\nEin Supabase-Dump verweist auf Dinge, die nur Supabase anlegt, etwa das\n",[74,323,116],{},"-Schema, in dem deine Nutzer leben, und die Rolle ",[74,326,327],{},"authenticated",", die\ndeine Sicherheitsregeln nennen, und die Wiederherstellung bricht an der ersten\nZeile ab, die eins davon erwähnt.",[10,330,331],{},"Eine Warnung, weil das Übungsprojekt jetzt eine echte Kopie enthält. Darin\nstehen die E-Mail-Adressen deiner Nutzer, also richte weder deine App noch ihre\nWebhooks darauf, und lösch es, wenn du fertig bist.",[10,333,334,335,338,339,342,343,346],{},"Geplante Jobs sind der Teil, der nicht mitkommt. Führt dein Projekt sie über die\nErweiterung ",[74,336,337],{},"pg_cron"," aus, bringen die drei Dateien der CLI die Erweiterung\nzurück und keinen ihrer Jobs, denn die Jobs sind Zeilen in ",[74,340,341],{},"cron.job",", und der\nDaten-Dump lässt diese Zeilen weg. Wir haben das am 4. Oktober 2026 mit Version\n2.119 der CLI geprüft, indem wir eine Datenbank mit einem geplanten Job\nwiederhergestellt haben. Das Übungsprojekt bleibt dadurch ruhig, und eine echte\nWiederherstellung aus diesen Dateien startet ebenfalls ohne einen einzigen\ngeplanten Job, also bewahr deine ",[74,344,345],{},"cron.schedule","-Aufrufe irgendwo auf, wo du sie\nerneut ausführen kannst.",[25,348,350],{"id":349},"wie-du-ein-supabase-backup-testest-schritt-für-schritt","Wie du ein Supabase-Backup testest, Schritt für Schritt",[10,352,353],{},"Sechs Schritte, und die ersten drei passieren, bevor du irgendetwas einspielst.",[355,356,357,363,386,402,417,423],"ol",{},[190,358,359,362],{},[17,360,361],{},"Such die neueste Kopie und lies ihr Datum."," Ist sie älter als der letzte\ngeplante Lauf, ist der Job stehen geblieben, und das ist dein erster Befund.",[190,364,365,375,376],{},[17,366,367,368,370,371,374],{},"Such in ",[74,369,233],{}," nach ",[74,372,373],{},"dump complete","."," Ein Treffer heißt, die Datei\nhat ihr Ende erreicht. Keiner heißt, sie wurde abgeschnitten, egal wie groß\nsie ist. Die Suche in einem Texteditor funktioniert genauso gut wie ein\nTerminal:",[377,378,383],"pre",{"className":379,"code":381,"language":382},[380],"language-text","grep -c 'dump complete' data.sql\n","text",[74,384,381],{"__ignoreMap":385},"",[190,387,388,391,392,395,396],{},[17,389,390],{},"Such darin nach deinen Nutzern."," Eine Zeile, die mit\n",[74,393,394],{},"COPY \"auth\".\"users\""," beginnt und unter der Zeilen stehen, heißt, deine\nKonten sind in der Datei:",[377,397,400],{"className":398,"code":399,"language":382},[380],"grep -n 'COPY .*auth.*users' data.sql\n",[74,401,399],{"__ignoreMap":385},[190,403,404,407,408,374,411],{},[17,405,406],{},"Spiel sie in das Übungsprojekt ein",", mit dem Befehl aus Supabases\nAnleitung und dem Connection String des Übungsprojekts. Bei einem lokalen\nSupabase lautet er\n",[74,409,410],{},"postgresql:\u002F\u002Fpostgres:postgres@127.0.0.1:54322\u002Fpostgres",[377,412,415],{"className":413,"code":414,"language":382},[380],"psql \\\n  --single-transaction \\\n  --variable ON_ERROR_STOP=1 \\\n  --file roles.sql \\\n  --file schema.sql \\\n  --command 'SET session_replication_role = replica' \\\n  --file data.sql \\\n  --dbname \"postgresql:\u002F\u002F…the spare's connection string…\"\n",[74,416,414],{"__ignoreMap":385},[190,418,419,422],{},[17,420,421],{},"Zähl die Zeilen und lies die neueste",", in beiden Datenbanken. Die Abfrage\nsteht im nächsten Abschnitt.",[190,424,425,428],{},[17,426,427],{},"Melde dich im Übungsprojekt als du selbst an."," Der Befehl steht im\nAbschnitt danach.",[10,430,431,432,436],{},"Bricht Schritt 4 mit einem Fehler ab, hat die Übung ihre Arbeit früh erledigt.\nDie Troubleshooting-Hinweise am Ende von Supabases Anleitung behandeln die\nbeiden Fehler, auf die Leute am häufigsten stoßen, beide zu Rollen, und\n",[150,433,435],{"href":434},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","wie du ein Supabase-Backup wiederherstellst","\nerklärt, wovor dich jedes Flag in diesem Befehl schützt.",[10,438,439,440,443,444,447,448,451,452,455,456,459,460,463,464,469],{},"Zwei weitere Abbrüche in ",[74,441,442],{},"roles.sql"," fehlen in diesen Hinweisen. Wir sind am 4.\nOktober 2026 auf beide gestoßen, als wir die Dateien von zwei\nPostgres-17-Datenbanken, eine davon ein Supabase-Projekt, in eine frische lokale\nKopie von Supabase eingespielt haben:\n",[74,445,446],{},"\"supabase_admin\" is a reserved role, only superusers can modify it"," auf einer\nZeile, die mit ",[74,449,450],{},"ALTER ROLE \"supabase_admin\""," beginnt, und\n",[74,453,454],{},"permission denied for parameter log_min_messages"," auf einer Zeile, die mit\n",[74,457,458],{},"GRANT SET ON PARAMETER"," beginnt. Beide Zeilen richten Rollen ein, die Supabase\nin jedem Projekt selbst anlegt, also setz ",[74,461,462],{},"--"," an den Anfang jeder dieser\nZeilen, damit sie zu Kommentaren werden, und führ den Befehl erneut aus.\n",[150,465,468],{"href":466,"rel":467},"https:\u002F\u002Fgithub.com\u002FReeve-page\u002Fsupabase-backup-action",[260],"Unsere Backup-Action","\nkommentiert sie schon beim Erstellen der Kopie aus.",[25,471,473],{"id":472},"was-du-zählst-und-womit-du-es-vergleichst","Was du zählst, und womit du es vergleichst",[10,475,476],{},"Zähl jede Tabelle im Übungsprojekt und in deinem Live-Projekt mit derselben\nAbfrage und leg die beiden Listen nebeneinander. Die Kopie sollte der\nLive-Datenbank eine Nacht hinterherhinken: bei einer wachsenden Tabelle etwas\nniedriger, und bei einer Tabelle, die Zeilen hatte, nie null.",[10,478,479,480,482],{},"Das ist das Durchzählen anhand der Liste, wer drin war. Füg die Abfrage in den\nSQL-Editor jedes Projekts ein und drück Run. Sie zählt die Zeilen jeder Tabelle\nin deinem eigenen Schema und in ",[74,481,116],{},":",[377,484,489],{"className":485,"code":487,"language":488,"meta":385},[486],"language-sql","select table_schema, table_name,\n       (xpath('\u002Frow\u002Fn\u002Ftext()',\n         query_to_xml(format('select count(*) as n from %I.%I', table_schema, table_name),\n                      false, true, '')))[1]::text::bigint as row_count\n  from information_schema.tables\n where table_schema in ('public', 'auth')\n   and table_type = 'BASE TABLE'\n order by table_schema, table_name;\n","sql",[74,490,487],{"__ignoreMap":385},[10,492,493],{},"Sie liest jede Zeile jeder Tabelle, also lass sie bei einer großen Datenbank\naußerhalb deiner geschäftigsten Stunden laufen.",[10,495,496,497,500,501,504],{},"Dann lies die neueste Zeile einer Tabelle, die du kennst, nur im\nÜbungsprojekt. Jede Tabelle mit einer Spalte ",[74,498,499],{},"created_at"," geht; setz ihren\nNamen anstelle von ",[74,502,503],{},"orders"," ein:",[377,506,509],{"className":507,"code":508,"language":488,"meta":385},[486],"select max(created_at) from public.orders;\n",[74,510,508],{"__ignoreMap":385},[10,512,513],{},"Die Antwort sollte nah an dem Zeitpunkt liegen, an dem das Backup lief. Ein\nDatum, das Wochen älter ist, oder Zeilen, die du nicht wiedererkennst, heißen,\ndass die Datei aus einem anderen Projekt stammt.",[43,515,516,529],{},[46,517,518],{},[49,519,520,523,526],{},[52,521,522],{},"Prüfung",[52,524,525],{},"Wo",[52,527,528],{},"Was eine gute Kopie zeigt",[62,530,531,542,553,565],{},[49,532,533,536,539],{},[67,534,535],{},"Zeilen in jeder Tabelle",[67,537,538],{},"Beide",[67,540,541],{},"Dieselben Tabellen, jede etwas hinter der Live-Zahl, keine leer, die Zeilen hatte",[49,543,544,547,550],{},[67,545,546],{},"Die neueste Zeile",[67,548,549],{},"Übungsprojekt",[67,551,552],{},"Ein Zeitpunkt aus der Nacht, in der die Kopie gezogen wurde",[49,554,555,558,560],{},[67,556,557],{},"Dein eigenes Konto",[67,559,549],{},[67,561,562,563],{},"Deine E-Mail-Adresse in ",[74,564,122],{},[49,566,567,570,572],{},[67,568,569],{},"Eine Anmeldung",[67,571,549],{},[67,573,574],{},"Ein Token kommt zurück",[25,576,578],{"id":577},"warum-die-anmeldung-der-test-ist-der-deine-konten-beweist","Warum die Anmeldung der Test ist, der deine Konten beweist",[10,580,581,582,584],{},"Eine Zählung von ",[74,583,122],{}," beweist, dass die Zeilen angekommen sind. Eine\nAnmeldung beweist, dass sie funktionieren: dass das gespeicherte Passwort, der\nAnmeldedienst des Übungsprojekts und deine E-Mail-Adresse noch\nzusammenpassen.",[10,586,587,588,482],{},"Nimm dein eigenes Konto, mit einem Passwort, das du kennst. Die Projektadresse\nund der Publishable Key des Übungsprojekts stehen in dessen Connect-Panel, bei\neinem lokalen Supabase in der Ausgabe von ",[74,589,291],{},[377,591,594],{"className":592,"code":593,"language":382},[380],"curl -X POST 'https:\u002F\u002F…the spare's project ref….supabase.co\u002Fauth\u002Fv1\u002Ftoken?grant_type=password' \\\n  -H \"apikey: sb_publishable_…\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\": \"you@example.com\", \"password\": \"…\"}'\n",[74,595,593],{"__ignoreMap":385},[10,597,598,599,604,605,608,609,612,613,616],{},"Das ist der Anmeldeaufruf aus\n",[150,600,603],{"href":601,"rel":602},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fpasswords",[260],"Supabases eigener Dokumentation",",\nauf das Übungsprojekt gerichtet. Eine Antwort mit ",[74,606,607],{},"access_token"," heißt, dein\nKonto ist mit einem funktionierenden Passwort angekommen.\n",[74,610,611],{},"Invalid login credentials",", bei einem Konto, das sich in deiner Live-App ohne\nProbleme anmeldet, heißt, es ist nicht angekommen, und\n",[150,614,615],{"href":152},"warum ein Dump ohne die Konten ankommt"," ist\nder Artikel für dieses Ergebnis.",[10,618,619,620,622],{},"Melden sich alle in deiner App mit Google an, hat dieser Aufruf nichts zu\ntesten, weil im Übungsprojekt keine Google-Anmeldung eingerichtet ist. Such\nstattdessen in der wiederhergestellten ",[74,621,122],{}," nach deiner eigenen\nE-Mail-Adresse. Das zeigt, dass die Kontozeile angekommen ist, aber nicht, dass\nihr Passwort funktioniert.",[25,624,626],{"id":625},"dateien-die-hälfte-die-eine-datenbank-wiederherstellung-nicht-testen-kann","Dateien: die Hälfte, die eine Datenbank-Wiederherstellung nicht testen kann",[10,628,629,630,634],{},"Die Datenbankkopie enthält eine Zeile für jede hochgeladene Datei und keine\neinzige Datei. Kopierst du deine Storage-Buckets in einem eigenen Job, und\n",[150,631,633],{"href":632},"\u002Fblog\u002Fsupabase-storage-backup","nur so werden sie überhaupt kopiert",", dann gib\ndieser Kopie auch eine Übung.",[10,636,637],{},"Nimm die drei neuesten Zeilen aus der wiederhergestellten Datenbank:",[377,639,642],{"className":640,"code":641,"language":488,"meta":385},[486],"select bucket_id, name from storage.objects order by created_at desc limit 3;\n",[74,643,641],{"__ignoreMap":385},[10,645,646],{},"Such diese drei Pfade in deiner Kopie der Dateien und öffne jede einzelne. Ein\nPfad ohne Datei dahinter ist ein Bild, das deine Nutzer nach einer echten\nWiederherstellung kaputt sehen würden.",[25,648,650],{"id":649},"kann-ich-die-backups-testen-die-supabase-für-mich-macht","Kann ich die Backups testen, die Supabase für mich macht?",[10,652,653,654,374],{},"Im bezahlten Tarif ja, mit Restore to a New Project. Nur so lässt sich eine\nvon Supabases eigenen Tageskopien öffnen, denn bei aktuellen Projekten\n",[150,655,657],{"href":656},"\u002Fblog\u002Fdownload-your-supabase-backup","kannst du sie nicht herunterladen",[10,659,660,661,666,667,669,670,673],{},"Supabase beschreibt die Funktion als Weg,\n",[150,662,665],{"href":663,"rel":664},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fclone-project",[260],"gefahrlos zu testen",".\nWähl im Tab Restore to a New Project auf der Backups-Seite eine Kopie, und\nSupabase baut daraus ein neues Projekt mit deinen Nutzern und ihren gehashten\nPasswörtern, bereit für dieselben Zählungen und dieselbe Anmeldung. Zwei Dinge\nsolltest du wissen, bevor du klickst. Das neue Projekt wird als eigenes\nProjekt abgerechnet, und Supabase zeigt dir die Kosten, bevor es losgeht. Und\nes kopiert alles, auch geplante Jobs: Supabase schreibt, dass Jobs von\n",[74,668,337],{},", ",[74,671,672],{},"pg_net"," und Wrappers loslaufen, sobald die Wiederherstellung fertig\nist, ohne Möglichkeit, sie vorher anzuhalten. Verschickt ein Job in deiner App\nE-Mails oder belastet eine Karte, tut das Testprojekt das auch.",[10,675,676],{},"Bewahrst du zusätzlich eine Datei außerhalb des Kontos auf, braucht diese Datei\neine eigene Übung.",[25,678,680],{"id":679},"wie-oft-sollte-ich-eine-wiederherstellung-testen","Wie oft sollte ich eine Wiederherstellung testen?",[10,682,683],{},"Einmal jetzt, dann alle drei Monate und wieder, sobald sich irgendetwas daran\nändert, wie das Backup entsteht.",[10,685,686],{},"Es zählen die Änderungen, die ein Backup still kaputt machen: ein neuer oder\nein geänderter Workflow, ein zurückgesetztes Datenbank-Passwort, ein Wechsel\nauf einen neuen Tarif oder eine neue Postgres-Version, eine neue Tabelle, in\ndie deine App jetzt schreibt. Nach jeder davon beschreibt die Übung vom letzten\nQuartal die Datei von diesem Quartal nicht mehr.",[10,688,689],{},"Dann schreib es auf, das ist das Blatt an der Tür. Eine Zeile pro Übung, an\neinem Ort, den du ohne das erreichst, was kaputtgegangen ist: das Datum, welche\nDatei, die Zählungen, auf die es ankam, ob die Anmeldung geklappt hat und wie\nlange die ganze Übung gedauert hat. Eine Textdatei im Backup-Repository reicht,\ngenauso ein wiederkehrender Kalendereintrag mit den eingefügten Ergebnissen.\nDas Datum beantwortet „wann haben wir das zuletzt bewiesen“ in der Stunde, in\nder es jemand wissen muss, und die Dauer ist deine erste Schätzung, wie lange\neine echte Wiederherstellung deine App lahmlegen würde.",[25,691,693],{"id":692},"wo-reeve-care-passt","Wo Reeve Care passt",[10,695,696],{},[17,697,698],{},"Care bewahrt Kopien deiner Supabase-Datenbank außerhalb deines\nSupabase-Kontos auf, nach dem Zeitplan deines Tarifs, prüft jede Kopie beim\nErstellen und spielt sie per Klick zurück.",[187,700,701,707,716,722,728,734],{},[190,702,703,706],{},[17,704,705],{},"Die Kopien laufen nach dem Zeitplan deines Tarifs",", von einmal täglich bis\nalle sechs Stunden.",[190,708,709,712,713,715],{},[17,710,711],{},"Eine abgeschnittene Kopie fällt schon beim Erstellen auf."," Die\nSchlusszeile von ",[74,714,76],{}," muss in der Datei stehen, sonst fällt die Kopie\ndurch die Prüfung und wird nie zum Datum in deinem Dashboard.",[190,717,718,721],{},[17,719,720],{},"Jede Tabelle wird gezählt, während die Kopie geschrieben wird."," Hat eine\nTabelle, die in der vorigen Kopie Zeilen hatte, in dieser keine mehr, erfährt\nein Mensch bei Reeve davon.",[190,723,724,727],{},[17,725,726],{},"Deine Konten sind in der Kopie",", und deine hochgeladenen Dateien kommen\nmit, sobald du einen Storage-Zugang verbindest.",[190,729,730,733],{},[17,731,732],{},"Wiederherstellen ist ein Klick",", und bevor irgendetwas ersetzt wird, wird\neine Kopie des aktuellen Zustands gezogen.",[190,735,736,739,740,743,744,669,746,748],{},[17,737,738],{},"Jede Kopie lässt sich als Zip herunterladen",", mit ",[74,741,742],{},"schema.sql",",\n",[74,745,233],{},[74,747,442],{}," und einem Manifest mit der Zeilenzahl jeder Tabelle.\nDas ist die Hälfte dieses Artikels mit dem „womit vergleichen“, schon\naufgeschrieben.",[10,750,751,752,756,757,761],{},"Eine vierteljährliche Übung beweist die Kopie, die du an dem Tag ausgewählt\nhast, und die Prüfung läuft bei jeder Kopie, während sie entsteht. Kopie,\nPrüfung und Wiederherstellung sind Schritt für Schritt auf der\n",[150,753,755],{"href":754},"\u002Fsupabase-backups","Seite zu Supabase-Backups"," gezeichnet, und\n",[150,758,760],{"href":759},"\u002Fpricing","was jeder Tarif enthält",", samt Zeitplan, steht auf der Preisseite.",[25,763,765],{"id":764},"was-du-diese-woche-tun-solltest","Was du diese Woche tun solltest",[767,768,769],"key-takeaways",{},[187,770,771,774,784,790,793,795],{},[190,772,773],{},"Such dein neuestes Backup und lies sein Datum. Ist es älter als der letzte geplante Lauf, repariere zuerst den Job.",[190,775,367,776,370,778,780,781,783],{},[74,777,233],{},[74,779,373],{}," und nach ",[74,782,394],{},". Zwei Suchen sagen dir, ob die Datei ihr Ende erreicht und ob deine Konten darin sind.",[190,785,786,787,789],{},"Leg ein Übungsprojekt an oder starte Supabase auf deinem eigenen Rechner und spiel die Datei mit dem ",[74,788,170],{},"-Befehl aus Supabases Anleitung ein.",[190,791,792],{},"Lass die Zählabfrage in beiden Datenbanken laufen und leg die beiden Listen nebeneinander. Lies die neueste Zeile einer Tabelle, die du kennst.",[190,794,427],{},[190,796,797],{},"Schreib das Datum, die Zählungen und die Dauer auf und lösch dann das Übungsprojekt.",[10,799,800,801,803,804,806,807,810],{},"Bevor du diesen Tab schließt, such in deiner neuesten ",[74,802,233],{}," nach\n",[74,805,373],{},". Es ist eine einzige Suche, und sie sagt dir, ob die Datei, die\ndu Backup nennst, ihre eigene letzte Zeile erreicht. Hast du noch keine Datei\nzum Durchsuchen, ist\n",[150,808,809],{"href":316},"eine kostenlose GitHub Action"," der\nschnellste Weg, damit anzufangen.",{"title":385,"searchDepth":812,"depth":812,"links":813},3,[814,816,817,818,819,820,821,822,823,824,825,826],{"id":27,"depth":815,"text":28},2,{"id":37,"depth":815,"text":38},{"id":163,"depth":815,"text":164},{"id":245,"depth":815,"text":246},{"id":349,"depth":815,"text":350},{"id":472,"depth":815,"text":473},{"id":577,"depth":815,"text":578},{"id":625,"depth":815,"text":626},{"id":649,"depth":815,"text":650},{"id":679,"depth":815,"text":680},{"id":692,"depth":815,"text":693},{"id":764,"depth":815,"text":765},"Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcover-1200x630.png","Eine Reihe gleicher versiegelter Backup-Dateien, die vorderste hell, neben einer leeren gestrichelten Datenbank, die auf eine davon wartet.","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.",false,"md",[834,836,838,841,844,847],{"q":28,"a":835},"Spiel es in ein Projekt ein, an dem nichts hängt, und sieh dir an, was zurückkommt. Vergleiche die Zeilenzahl jeder Tabelle mit der Live-Datenbank, prüfe, ob die neueste Zeile aus der Nacht stammt, in der die Kopie gezogen wurde, und melde dich als du selbst an. An der Datei selbst erkennst du den Unterschied zwischen einem guten und einem kaputten Dump nicht: Name, Größe und der grüne Haken neben dem Job sehen in beiden Fällen gleich aus.",{"q":680,"a":837},"Einmal jetzt, dann alle drei Monate und immer dann, wenn sich etwas daran ändert, wie das Backup entsteht: ein neuer oder geänderter Workflow, ein zurückgesetztes Datenbank-Passwort, ein neuer Tarif oder eine neue Postgres-Version oder eine neue Tabelle, in die deine App schreibt. Schreib jedes Mal das Datum auf, mit den Zählungen und der Dauer, damit die Frage, wann es zuletzt bewiesen wurde, eine Antwort hat.",{"q":839,"a":840},"Kann ich eine Wiederherstellung testen, ohne meine Live-Datenbank anzufassen?","Ja, und genau so solltest du es immer machen. Spiel die Kopie in ein Übungsprojekt bei Supabase ein, das der Free-Tarif erlaubt, oder in ein Supabase, das über die CLI und Docker auf deinem eigenen Rechner läuft. Die Live-Datenbank wird bei der Übung nur einmal gelesen, um ihre Zeilen zu zählen. Lösch das Übungsprojekt danach, denn es enthält eine echte Kopie deiner Nutzer.",{"q":842,"a":843},"Was sollte ich nach einer Wiederherstellung prüfen?","Vier Dinge. Die Zeilenzahl jeder Tabelle neben der Live-Zahl, wobei die Kopie ein wenig zurückliegen sollte und bei einer Tabelle, die Zeilen hatte, nie bei null. Die neueste Zeile einer Tabelle, die du kennst, die aus der Nacht der Kopie stammen sollte. Deine eigene E-Mail-Adresse in auth.users. Und eine Anmeldung als du selbst, die als einzige Prüfung zeigt, dass die Konten funktionieren und nicht nur angekommen sind.",{"q":845,"a":846},"Die Wiederherstellung hat geklappt, aber niemand kann sich anmelden. Warum?","Meistens, weil die Datei deine Konten nie enthalten hat. Supabase bewahrt sie in einem Schema namens auth auf, und ein Dump, der nur dein eigenes Schema nennt, oder ein nacktes supabase db dump lässt sie weg, während jede deiner Tabellen sauber zurückkommt. Such in der Datei zuerst nach COPY \"auth\".\"users\". Fehlt die Zeile, zieh einen Daten-Dump mit --data-only, der das auth-Schema mitnimmt und deine Nutzer mitbringt.",{"q":164,"a":848},"Nicht immer. Wir haben eine pg_dump-Datei an drei Stellen abgeschnitten und jede Version mit --single-transaction und ON_ERROR_STOP eingespielt, den Flags aus Supabases Wiederherstellungsanleitung. Ein Schnitt mitten in einem Wert brach mit einem Fehler ab. Ein Schnitt in der letzten Spalte einer Zeile und ein Schnitt zwischen zwei Tabellen liefen beide ohne Fehler durch, mit unvollständigen Tabellen. Ein vollständiger Dump trägt kurz vor dem Ende die Zeile PostgreSQL database dump complete, also such danach, bevor du einer Datei vertraust.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",[851,852,853,854,855,856,857,858],"supabase backup testen","supabase backup prüfen","supabase wiederherstellung testen","datenbank backup testen","backup in testdatenbank einspielen","funktioniert mein supabase backup","supabase backup verifizieren","wiederherstellungsübung",{},true,"\u002Fblog\u002Ftest-your-supabase-backup","2026-09-28",{"title":5,"description":830},"blog\u002Ftest-your-supabase-backup",[866,867,868],"Um ein Supabase-Backup zu testen, spielst du es in ein Projekt ein, an dem nichts hängt, vergleichst die Zeilenzahlen mit der Live-Datenbank und meldest dich als du selbst an. Nur eine Wiederherstellung unterscheidet eine gute Datei von einer kaputten.","Wir haben einen Dump mitten in einer Tabelle abgeschnitten und mit den Flags eingespielt, die Supabase empfiehlt. psql lief ohne Fehler durch, und die Tabellen kamen unvollständig zurück.","Mach die Übung einmal jetzt, dann alle drei Monate und nach jeder Änderung daran, wie das Backup entsteht, und schreib jedes Mal das Datum auf.","2026-10-05","QBO4k6D5QtOe_d_mU1FDdOqkDgxWrmmB5mYmEpbdnc0",[872,879,885,891,897,903,909,914,920,926,932,938,944,950,951,956,961,966,972,978,983,989,995,1001,1007,1013,1019,1025,1031,1036,1042,1048,1054,1060,1066,1072,1078,1084,1090,1096,1102,1108,1114,1120,1126,1132,1138,1144,1150,1156,1161,1167,1173,1179,1185,1190,1196,1202,1208,1213,1219],{"path":873,"title":874,"description":875,"published":876,"category":877,"image":878,"draft":831},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" beim Upload","\"New row violates row-level security policy for table objects\" heißt: Deinem Upload fehlt eine insert-Regel. Ein öffentlicher Bucket fügt keine hinzu.","2026-10-11","Sicherheitsgrundlagen","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":880,"title":881,"description":882,"published":883,"category":877,"image":884,"draft":831},"\u002Fblog\u002Fbase44-security-scan","Base44 Security Scan: das, was nur er sehen kann","Der Base44 Security Scan prüft sieben Arten von Problemen von innen. Hier ist die Hälfte, die er liest und sonst niemand, und die Hälfte, die er nie ansieht.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":886,"title":887,"description":888,"published":889,"category":877,"image":890,"draft":831},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Dein API-Key wurde geleakt. Die richtige Reihenfolge","Ein API-Key wurde geleakt und du weißt nicht, was zuerst zu tun ist. Nicht jeder Key im Frontend ist ein Leck, und die Reihenfolge zählt mehr als das Tempo.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":892,"title":893,"description":894,"published":895,"category":877,"image":896,"draft":831},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" ohne RLS abzuschalten","\"Infinite recursion detected in policy for relation\" heißt: Deine Policy hat die Tabelle gefragt, die sie schützt. So brichst du den Kreis.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":898,"title":899,"description":900,"published":901,"category":877,"image":902,"draft":831},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, und die falsche Lösung","\"No API key found in request\" heißt, deine Supabase-Anfrage kam ohne Schlüssel an. Die meisten Antworten zeigen stattdessen auf deine Datenbankregeln.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":904,"title":905,"description":906,"published":907,"category":877,"image":908,"draft":831},"\u002Fblog\u002Fis-base44-safe","Ist Base44 sicher? Was 5.442 echte Base44-Apps zeigten","Ist Base44 sicher? Wir haben 5.442 laufende Base44-Apps mit neun Checks geprüft. Fast alle bekamen ein B, aus Gründen, die der Inhaber nie gewählt hat.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":910,"title":911,"description":912,"published":869,"category":877,"image":913,"draft":831},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","API-Schlüssel verstecken: ab in eine Supabase Edge Function","Einen API-Schlüssel verstecken heißt, ihn aus dem Browser zu nehmen. Eine Supabase Edge Function ist der kleinste Ort dafür, und zwei Schritte zählen mehr.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":915,"title":916,"description":917,"published":918,"category":877,"image":919,"draft":831},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Ist deine .env-Datei öffentlich? Zwölf Pfade zum Prüfen","Ist deine .env-Datei auf deinem eigenen Webserver öffentlich? Zwölf Adressen sagen es dir, und ein Treffer heißt: alles darin ist längst öffentlich.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":921,"title":922,"description":923,"published":924,"category":877,"image":925,"draft":831},"\u002Fblog\u002Fis-v0-safe","v0-Sicherheit: alle 1.790 gescannten v0-Apps bekamen ein A","v0-Sicherheit, gemessen an 1.790 laufenden v0-Apps: Jede bekam ein A. Nur 17 nannten eine Datenbank, und genau das misst das A vor allem.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":927,"title":928,"description":929,"published":930,"category":877,"image":931,"draft":831},"\u002Fblog\u002Fis-bolt-safe","Ist Bolt sicher? Was 1.123 echte Bolt-Apps zeigten","Ist Bolt sicher? Wir haben 1.123 laufende Bolt-Apps mit neun Checks geprüft. Das Hosting war sauber. Die Funde waren Schlüssel und offene Tabellen in den Apps.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":933,"title":934,"description":935,"published":936,"category":877,"image":937,"draft":831},"\u002Fblog\u002Fis-supabase-down-or-your-app","Ist Supabase down oder liegt es an deiner App? So erkennst du es","Ist Supabase down oder liegt es an deiner App? Ein pausiertes Projekt, eine volle Datenbank und ein eigener Fehler sehen gleich aus. Vier Prüfungen helfen.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":939,"title":940,"description":941,"published":942,"category":877,"image":943,"draft":831},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Verschlüsselt Supabase meine Daten? Ja. Wovor das schützt","Verschlüsselt Supabase Daten? Ja: AES-256 im Ruhezustand, TLS bei der Übertragung, SOC 2 und ISO 27001. Was jedes abdeckt und welches Leck keines stoppt.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":945,"title":946,"description":947,"published":948,"category":877,"image":949,"draft":831},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase Gratis-Tarif: die Limits und was an jedem passiert","Die Limits des Supabase-Gratis-Tarifs: 500 MB Datenbank, 5 GB Egress und keine Backups. Was an jeder Grenze passiert und was $25 für Pro ändern.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":861,"title":5,"description":830,"published":862,"category":827,"image":849,"draft":831},{"path":316,"title":952,"description":953,"published":954,"category":827,"image":955,"draft":831},"Kostenloses Supabase-Backup per GitHub Action, mit Haken","Eine Supabase-Backup-GitHub-Action kostet nichts und passt für viele Apps. Der Workflow, der richtige Connection String und das Egress pro Lauf.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":656,"title":957,"description":958,"published":959,"category":827,"image":960,"draft":831},"Warum du dein Supabase-Backup nicht herunterladen kannst","Dein Supabase-Backup kannst du auf aktuellen Projekten nicht herunterladen, weil die Tageskopie physisch ist. Wie du es prüfst und selbst eine Kopie hältst.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":962,"title":963,"description":964,"published":959,"category":877,"image":965,"draft":831},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": der fehlende Grant","Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit \"permission denied for table\", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":967,"title":968,"description":969,"published":970,"category":877,"image":971,"draft":831},"\u002Fblog\u002Fopen-api-endpoint-exposed","Ist ein offener API-Endpunkt ein Sicherheitsproblem? Sieh ins JSON","Dein Scan hat einen offenen API-Endpunkt gemeldet. Ob das zählt, hängt davon ab, was zurückkam, und die meisten hier gehörten der Plattform.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":973,"title":974,"description":975,"published":976,"category":877,"image":977,"draft":831},"\u002Fblog\u002Flovable-security-scan","Lovable Security Scan: das Eine, was er nicht beweist","Lovable Security Scan: was Quick Scan und Deep Scan prüfen, wann welcher läuft, und das Eine, was kein Scan von innen beweisen kann.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":152,"title":979,"description":980,"published":981,"category":827,"image":982,"draft":831},"Warum in deinem Supabase-Dump keine Nutzer stehen","Führe supabase db dump allein aus und du bekommst die Form deiner Datenbank und keine einzige Zeile, und das auth-Schema mit deinen Nutzern fehlt ganz.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":984,"title":985,"description":986,"published":987,"category":877,"image":988,"draft":831},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain abgelaufen, Website offline: was jetzt passiert","Deine Domain ist abgelaufen und deine Website ist offline. Welche Frist jetzt läuft, warum das Zertifikat das kleinere Problem ist, und wie du beides prüfst.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":990,"title":991,"description":992,"published":993,"category":877,"image":994,"draft":831},"\u002Fblog\u002Fis-lovable-safe","Ist Lovable sicher? Was 18.554 echte Lovable-Apps zeigten","Ist Lovable sicher? Wir haben 18.554 laufende Lovable-Apps mit neun Checks geprüft. Die Plattform war die sauberste von fünf. Die Funde saßen in den Apps.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":996,"title":997,"description":998,"published":999,"category":877,"image":1000,"draft":831},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Die Sicherheits-Checkliste für Vibe-Coding, in neun Prüfungen","Eine Sicherheits-Checkliste für Vibe-Coding mit neun Punkten, die jeder von außen an deiner Live-App nachprüfen kann, jeder mit einem Test in einer Zeile.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":1002,"title":1003,"description":1004,"published":1005,"category":877,"image":1006,"draft":831},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Ein geheimer Stripe-Schlüssel im Frontend kann Geld bewegen","Ein geheimer Stripe-Schlüssel im Frontend kann erstatten, abbuchen und jeden Kundendatensatz lesen, den du hast. Dein pk_live_-Schlüssel gehört dorthin.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":1008,"title":1009,"description":1010,"published":1011,"category":877,"image":1012,"draft":831},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":1014,"title":1015,"description":1016,"published":1017,"category":877,"image":1018,"draft":831},"\u002Fblog\u002Fbase44-source-maps","Base44-Sicherheit: was ein Scan meldet und was du ändern kannst","Base44-Sicherheit auf 5.438 gescannten Apps: Drei Befunde auf fast jeder gehören der Plattform, die Source Map ist das Base44-Badge, und deine Liste ist kurz.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":1020,"title":1021,"description":1022,"published":1023,"category":877,"image":1024,"draft":831},"\u002Fblog\u002Fis-cursor-ai-safe","Ist Cursor AI sicher? Editor, Code und die App, die du veröffentlichst","Ist Cursor AI sicher? Drei Fragen in einer Suche: was Cursor behält, was sein Code falsch macht und ob deine veröffentlichte App offen steht.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1026,"title":1027,"description":1028,"published":1029,"category":877,"image":1030,"draft":831},"\u002Fblog\u002Fis-replit-safe","Ist Replit sicher? Was wir in 3.042 Replit-Apps gefunden haben","Ist Replit sicher? Wir haben 3.042 laufende Replit-Apps mit neun externen Checks geprüft. Die Funde saßen in der veröffentlichten App, nicht im Hosting.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":632,"title":1032,"description":1033,"published":1034,"category":827,"image":1035,"draft":831},"Supabase Storage Backup: deine Datenbankkopie hat keine Dateien","Ein Supabase Storage Backup ist eine eigene Aufgabe. Datenbank-Backups enthalten die Liste deiner Dateien und keine davon, also bleibt jeder Upload kaputt.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1037,"title":1038,"description":1039,"published":1040,"category":827,"image":1041,"draft":831},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase Point-in-Time Recovery: Kosten und Grenzen","Supabase Point-in-Time Recovery spult deine Datenbank auf jede Sekunde der letzten Woche zurück. $100 im Monat zusätzlich zu Pro, und nur die Datenbank.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1043,"title":1044,"description":1045,"published":1046,"category":827,"image":1047,"draft":831},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase-Projekt pausiert? Deine Daten sind noch da","Supabase hat dein Projekt nach einer Woche ohne Aktivität pausiert. Gelöscht ist nichts, Wiederherstellen steht neben dem Namen, und du hast ein Jahr.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1049,"title":1050,"description":1051,"published":1052,"category":877,"image":1053,"draft":831},"\u002Fblog\u002Fsafest-ai-app-builder","Welcher KI-App-Builder ist am sichersten? 30.998 Apps im Test","Welcher KI-App-Builder ist am sichersten? Wir haben 30.998 aktive Apps von Lovable, Base44, Replit, v0 und Bolt gescannt. Der Builder entscheidet das nicht.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":1055,"title":1056,"description":1057,"published":1058,"category":877,"image":1059,"draft":831},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security für jede Supabase-Tabelle aktivieren und prüfen","Row Level Security in Supabase ohne Policy sperrt eine Tabelle komplett. Eine Policy ohne den Schalter bringt gar nichts. Hier ist das SQL, und der Test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1061,"title":1062,"description":1063,"published":1064,"category":877,"image":1065,"draft":831},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": was die Warnung übersieht","Supabase meldet \"RLS disabled in public\" als Fehler. Zur Lese-Policy, die deine Tabelle genauso offen lässt, sagt der Advisor gar nichts.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1067,"title":1068,"description":1069,"published":1070,"category":877,"image":1071,"draft":831},"\u002Fblog\u002Frotate-supabase-service-role-key","Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1073,"title":1074,"description":1075,"published":1076,"category":877,"image":1077,"draft":831},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe-Coding-Security-Scanner im Vergleich, unserer eingeschlossen","Der beste Vibe-Coding-Security-Scanner hängt an drei Fragen, die keine Funktionsliste beantwortet. Zehn Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1079,"title":1080,"description":1081,"published":1082,"category":877,"image":1083,"draft":831},"\u002Fblog\u002Fsupabase-security-checker","Supabase Security Checker: die fünf Prüfungen selbst machen","Ein Supabase Security Checker liest deine veröffentlichte App statt deiner Projekteinstellungen. Hier sind die fünf Prüfungen und wie du jede selbst ausführst.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1085,"title":1086,"description":1087,"published":1088,"category":877,"image":1089,"draft":831},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe-Coding-Security-Scanner: was ein URL-Scan übersieht","Ein Vibe-Coding-Security-Scanner liest deine laufende App von außen. Was das abdeckt, die vier Dinge, die er nicht sehen kann, und wie du das Ergebnis liest.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1091,"title":1092,"description":1093,"published":1094,"category":877,"image":1095,"draft":831},"\u002Fblog\u002Fmissing-security-headers","Fehlende Sicherheitsheader: wann sie wirklich zählen","Fehlende Sicherheitsheader ist unser häufigster Befund. Wogegen sie schützen, und wann sie die unwichtigste Zeile in deinem Bericht sind.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1097,"title":1098,"description":1099,"published":1100,"category":877,"image":1101,"draft":831},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.","Ein OpenAI-API-Schlüssel im Frontend lässt sich an keine Domain binden. Tausch ihn heute, leg den Aufruf hinter deinen Server und begrenze das Budget.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1103,"title":1104,"description":1105,"published":1106,"category":877,"image":1107,"draft":831},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","API-Schlüssel im Frontend: was 30.998 Apps wirklich ausliefern","Ein API-Schlüssel im Frontend ist meistens ein Google-Maps-Schlüssel. Wir haben 30.998 aktive Vibe-Coding-Apps gescannt und gezählt, was wirklich austritt.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1109,"title":1110,"description":1111,"published":1112,"category":827,"image":1113,"draft":831},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase-Backup-Tools im Vergleich, unseres eingeschlossen","Vier Arten von Supabase-Backup-Tool, was jedes wirklich kopiert und wann eine kostenlose GitHub Action jeden Anbieter schlägt, uns eingeschlossen.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1115,"title":1116,"description":1117,"published":1118,"category":877,"image":1119,"draft":831},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1121,"title":1122,"description":1123,"published":1124,"category":827,"image":1125,"draft":831},"\u002Fblog\u002Fback-up-supabase-free-tier","Supabase Gratis-Tarif: Backup ohne Terminal selbst machen","Im Supabase Gratis-Tarif gibt es keine Backups, die Kopie musst du selbst machen. Wie das im Dashboard geht und was der CSV-Weg auslässt.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1127,"title":1128,"description":1129,"published":1130,"category":877,"image":1131,"draft":831},"\u002Fblog\u002Fis-supabase-secure","Ist Supabase sicher? Ja. Dein Projekt ist eine eigene Frage","Ist Supabase sicher? Die Plattform ist auditiert, verschlüsselt und pentestet. Supabase schreibt selbst auf, wo das aufhört und deine Einstellungen anfangen.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1133,"title":1134,"description":1135,"published":1136,"category":877,"image":1137,"draft":831},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Wo du deine Supabase API-Keys findest: anon, service_role, URL","Projekt-URL, anon-Schlüssel und service_role-Schlüssel liegen auf einer Seite im Dashboard. Wo sie ist, und welcher der vier Werte in deine App gehört.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1139,"title":1140,"description":1141,"published":1142,"category":877,"image":1143,"draft":831},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy in Supabase: was jetzt?","\"New row violates row-level security policy\" heißt, Supabase hat einen Schreibvorgang abgelehnt. Die schnelle Lösung öffnet die Tabelle wieder für alle.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1145,"title":1146,"description":1147,"published":1148,"category":877,"image":1149,"draft":831},"\u002Fblog\u002Fcors-wildcard-security-risk","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist nicht.","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist ist sie die Voreinstellung deines Builders und gibt nichts preis, was dein Server nicht ohnehin herausgab.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1151,"title":1152,"description":1153,"published":1154,"category":827,"image":1155,"draft":831},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase Branching ist kein Backup. Es geht nur vorwärts.","Warum Supabase Branching kein Backup ist: Ein Branch startet ohne deine Daten, und ein Merge bringt nur das Schema. Wofür es gut ist und was stattdessen hilft.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":434,"title":1157,"description":1158,"published":1159,"category":827,"image":1160,"draft":831},"Supabase-Backup wiederherstellen, und was danach kaputt ist","Wie du ein Supabase-Backup aus dem Dashboard oder aus einer Dump-Datei wiederherstellst, was ersetzt wird und warum die App danach kaputt sein kann.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1162,"title":1163,"description":1164,"published":1165,"category":877,"image":1166,"draft":831},"\u002Fblog\u002Fsupabase-storage-bucket-public","Dein Supabase-Storage-Bucket ist öffentlich. Ist das ein Problem?","Ein öffentlicher Supabase-Storage-Bucket heißt: Wer die URL einer Datei hat, kann sie öffnen. Er heißt nicht, dass jemand den Inhalt auflisten darf.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1168,"title":1169,"description":1170,"published":1171,"category":877,"image":1172,"draft":831},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Ist ein Google-API-Schlüssel im Frontend ein Problem?","Ein Google-API-Schlüssel im Frontend ist der Fund unseres Scanners Nummer eins, und meistens unbedenklich. Eine kostenlose Einstellung entscheidet darüber.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1174,"title":1175,"description":1176,"published":1177,"category":827,"image":1178,"draft":831},"\u002Fblog\u002Fai-agent-deleted-my-database","Ein KI-Agent hat meine Supabase-Daten gelöscht. Was hole ich zurück?","Ein KI-Agent hat Daten aus deiner Datenbank gelöscht. Was du zurückholst, stand schon vorher fest, und die nächsten Minuten entscheiden über den Rest.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1180,"title":1181,"description":1182,"published":1183,"category":877,"image":1184,"draft":831},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Kann jeder deine Supabase-Datenbank lesen? 3.680 Apps im Test","Kann jeder deine Supabase-Datenbank ohne Login lesen? Wir haben 30.998 aktive Apps aus KI-Buildern gescannt und gemessen, wie oft die Antwort ja lautet.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1186,"title":1187,"description":1188,"published":1183,"category":877,"image":1189,"draft":831},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source-Maps öffentlich: deine App veröffentlicht ihren Quellcode","Eine öffentliche Source-Map lässt jeden den Originalcode deiner App lesen, Kommentare inklusive. Der 30-Sekunden-Check, und was wirklich zählt.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1191,"title":1192,"description":1193,"published":1194,"category":877,"image":1195,"draft":831},"\u002Fblog\u002Fsupabase-new-api-keys","Supabases neue API-Schlüssel: welcher gehört in deine App?","Supabase hat anon und service_role durch öffentliche und geheime Schlüssel ersetzt. Welcher gehört in deine App, und welcher nie?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1197,"title":1198,"description":1199,"published":1200,"category":827,"image":1201,"draft":831},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Sichert Supabase meine Datenbank? Das hängt von deinem Tarif ab.","Sichert Supabase deine Datenbank? Auf bezahlten Tarifen täglich, im Gratis-Tarif gar nicht. So findest du heraus, was du hast und was es nicht abdeckt.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1203,"title":1204,"description":1205,"published":1206,"category":877,"image":1207,"draft":831},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security ist an. Die Tabelle ist trotzdem offen.","Supabase Row Level Security anzuschalten schützt keine Tabelle. Erst deine Policies tun das, und die, die deine App repariert hat, lässt oft alle herein.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1209,"title":1210,"description":1211,"published":1206,"category":827,"image":1212,"draft":831},"\u002Fblog\u002Fversion-history-is-not-a-backup","Der Versionsverlauf ist kein Backup. Er holt keine Tabelle zurück.","Lovable und Bolt führen einen Versionsverlauf für deinen Code. Deine Datenbank ist ein eigener Dienst, und ein Rücksprung holt deine Daten nicht zurück.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1214,"title":1215,"description":1216,"published":1217,"category":827,"image":1218,"draft":831},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Drei Wege, eine Supabase-Datenbank zu sichern, und was fehlt","Das Dashboard, pg_dump und ein verwalteter Dienst. Was jeder Weg wirklich sichert, was er stillschweigend auslässt und welcher den Kontoverlust übersteht.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1220,"title":1221,"description":1222,"published":1217,"category":877,"image":1223,"draft":831},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Welche API-Schlüssel im Frontend sicher sind, und welche nicht","Dein Supabase-anon-Schlüssel darf öffentlich sein. Der service_role-Schlüssel nicht. Er ignoriert jede Regel, die du setzt. So erkennst du den Unterschied.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791705957971]