[{"data":1,"prerenderedAt":1148},["ShallowReactive",2],{"blog-de-database-error-deleting-user":3,"blog-index-de":622},{"id":4,"title":5,"body":6,"category":580,"cover":581,"coverAlt":582,"description":583,"draft":584,"extension":585,"faq":586,"image":601,"keywords":602,"meta":610,"navigation":611,"ogTitle":612,"path":613,"published":614,"seo":615,"stem":616,"tldr":617,"updated":614,"__hash__":621},"blog_de\u002Fblog\u002Fdatabase-error-deleting-user.md","\"Database error deleting user\" in Supabase und was mitgelöscht wird",{"type":7,"value":8,"toc":566},"minimark",[9,13,24,27,34,39,42,59,65,69,72,75,98,101,122,126,133,136,142,157,168,183,186,194,208,212,215,221,224,227,233,236,240,243,307,323,326,332,335,349,354,358,367,381,395,401,405,408,436,447,454,458,461,477,480,488,492,498,506,528,532,558],[10,11,12],"p",{},"Du öffnest Authentication → Users in deinem Supabase-Dashboard und löschst ein\nKonto. Vielleicht hat die Person darum gebeten, vielleicht ist es ein Testkonto\naus der letzten Woche. Das Dashboard antwortet:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Failed to delete user: Database error deleting user\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Das Konto steht weiter in der Liste. Die App, die du mit Lovable, Bolt, v0,\nCursor, Claude Code oder Replit gebaut hast, läuft die ganze Zeit, und der Satz\nnennt weder eine Tabelle noch einen Grund.",[10,28,29,30,33],{},"Die erste Antwort, die du findest, ist eine Zeile SQL: Häng ",[21,31,32],{},"on delete cascade","\nan das, was im Weg steht. Das funktioniert. Es legt aber auch fest, welche\nanderen Zeilen bei jedem künftig gelöschten Konto mitgelöscht werden, und danach\nfragt dich niemand mehr. Lies also zuerst den echten Fehler und triff diese\nEntscheidung dann Tabelle für Tabelle.",[35,36,38],"h2",{"id":37},"was-bedeutet-database-error-deleting-user-in-supabase","Was bedeutet \"Database error deleting user\" in Supabase?",[10,40,41],{},"Deine Datenbank hat das Löschen abgelehnt, und Supabase hat alles rückgängig\ngemacht, das Konto ist also genau so wie vorher.",[10,43,44,45,48,49,52,53,58],{},"Einen Nutzer zu löschen ist eine Aufgabe für Supabase Auth, den Dienst hinter dem\nLogin deiner App. Im Quellcode von Auth läuft das Löschen in einer einzigen\nTransaktion, einer Gruppe von Änderungen, die entweder alle passieren oder gar\nkeine, und ihr zentraler Schritt entfernt die Zeile der Person aus ",[21,46,47],{},"auth.users",".\nWenn irgendetwas in deiner Datenbank dagegen Einspruch erhebt, wird die\nTransaktion zurückgerollt, und Auth antwortet mit diesem einen Satz. Supabase\nführt ihn als HTTP 500 mit dem Code ",[21,50,51],{},"unexpected_failure",", neben seinem Zwilling\nbei der Registrierung,\n",[54,55,57],"a",{"href":56},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\"",".",[10,60,61,62,64],{},"Stell dir deine Datenbank als Verein vor. ",[21,63,47],{}," ist die Mitgliederliste,\nund jedes Mitglied hat eine Nummer: seine User-ID. Deine anderen Bücher schreiben\ndiese Nummer auf ihre Zeilen, ob Profil, Bestellung, Beitrag oder Kommentar.\nJemanden von der Liste zu streichen ist eine Zeile Arbeit. Nur trägt jedes andere\nBuch die Nummer weiter, und solange niemand aufgeschrieben hat, was mit diesen\nZeilen geschehen soll, weigert sich der Schriftführer des Vereins.",[35,66,68],{"id":67},"wo-steht-der-echte-fehler","Wo steht der echte Fehler?",[10,70,71],{},"In den Postgres-Logs deines Projekts, zu dem Zeitpunkt, an dem das Löschen\nfehlschlug.",[10,73,74],{},"Supabases Troubleshooting-Notiz zu den Fehlern bei der Nutzerverwaltung gibt den\nWeg vor. Versuch das Löschen einmal und notier dir die Uhrzeit. Dann im\nDashboard:",[76,77,78,91],"ol",{},[79,80,81,82,86,87,90],"li",{},"Öffne ",[83,84,85],"strong",{},"Logs"," und lies die ",[83,88,89],{},"Auth","-Logs zu dieser Zeit. Der Eintrag ist\nAuths eigenes Protokoll des fehlgeschlagenen Löschens.",[79,92,93,94,97],{},"Öffne die ",[83,95,96],{},"Postgres","-Logs zur selben Zeit. Diese Zeile ist der echte Fehler,\nund sie nennt eine Tabelle, eine Regel oder eine Berechtigung.",[10,99,100],{},"Dieselbe Notiz nennt drei Ursachen, und die Logzeile sagt dir, welche du hast:",[102,103,104,110,116],"ul",{},[79,105,106,107,109],{},"ein Trigger auf der Tabelle ",[21,108,47],{},", der fehlschlägt",[79,111,112,113,115],{},"eine Constraint, die nicht erfüllt ist, was beim Löschen einen Foreign Key in\neiner anderen Tabelle bedeutet, der auf ",[21,114,47],{}," zeigt",[79,117,118,119,121],{},"Prisma, das laut der Notiz die Berechtigungen auf ",[21,120,47],{}," kaputtmachen\nkann",[35,123,125],{"id":124},"eine-tabelle-die-noch-auf-den-nutzer-zeigt","Eine Tabelle, die noch auf den Nutzer zeigt",[10,127,128,129,132],{},"Steht in der Postgres-Zeile ",[21,130,131],{},"violates foreign key constraint",", dann hält eine\nZeile in einer deiner Tabellen noch die ID dieses Nutzers, und Postgres entfernt\nniemanden, auf den noch etwas zeigt.",[10,134,135],{},"Supabases Notiz druckt die Form ab, die das annimmt:",[14,137,140],{"className":138,"code":139,"language":19},[17],"ERROR:  23503: update or delete on table \"users\" violates foreign key constraint \"profiles_id_fkey\" on table \"profiles\"\nDETAIL:  Key (id)=(7428a53c-75b7-4531-9ae9-1567d9c4ac0a) is still referenced from table \"profiles\".\n",[21,141,139],{"__ignoreMap":23},[10,143,144,145,148,149,152,153,156],{},"Ein Foreign Key ist eine Regel auf einer Spalte, die besagt, dass jeder Wert darin\nin einer anderen Tabelle existieren muss. Hier heißt die Regel\n",[21,146,147],{},"profiles_id_fkey",", sie sitzt auf deiner Tabelle ",[21,150,151],{},"profiles",", und die Zeile ",[21,154,155],{},"Key","\nist die ID des Nutzers, den du löschen wolltest. Im Verein ist das eine Zeile im\nProfilbuch mit der Nummer des Mitglieds, und der Schriftführer streicht es nicht,\nsolange sie dort steht.",[10,158,159,160,163,164,58],{},"Dieselbe Regel lehnt auch von der anderen Seite ab. Eine neue Zeile, die einen\nNutzer nennt, den es nicht gibt, kommt als\n",[21,161,162],{},"insert or update on table … violates foreign key constraint"," zurück, und\n",[54,165,167],{"href":166},"\u002Fblog\u002Fviolates-foreign-key-constraint","diese Meldung hat einen eigenen Beitrag",[10,169,170,171,174,175,178,179,182],{},"Die Weigerung ist der Standard. Ein Foreign Key, der ohne Zusatz nach\n",[21,172,173],{},"references auth.users"," angelegt wurde, bekommt das Verhalten, das Postgres\n",[21,176,177],{},"no action"," nennt, und Supabases Anleitung zu Cascade Deletes sagt ausdrücklich,\ndass ",[21,180,181],{},"NO ACTION"," der Standard ist, wenn du nichts angibst. Eine Tabelle, die dein\nBuilder so angelegt hat, funktioniert tadellos bis zu dem Tag, an dem zum ersten\nMal jemand gelöscht wird.",[10,184,185],{},"Um jede Tabelle zu sehen, die auf deine Nutzer zeigt, und was jede beim Löschen\ntut, führ das im SQL Editor aus:",[14,187,192],{"className":188,"code":190,"language":191,"meta":23},[189],"language-sql","select conrelid::regclass as table_name,\n       conname as rule,\n       case confdeltype\n         when 'c' then 'cascade'\n         when 'n' then 'set null'\n         when 'd' then 'set default'\n         when 'r' then 'restrict'\n         else 'no action'\n       end as on_delete\nfrom pg_constraint\nwhere contype = 'f'\n  and confrelid = 'auth.users'::regclass\n  and connamespace \u003C> 'auth'::regnamespace;\n","sql",[21,193,190],{"__ignoreMap":23},[10,195,196,197,200,201,203,204,207],{},"Die Abfrage liest nur den eigenen Katalog von Postgres und ändert nichts. Die\nletzte Zeile lässt Supabases eigene Tabellen im Schema ",[21,198,199],{},"auth"," weg. Jede Zeile mit\n",[21,202,177],{}," oder ",[21,205,206],{},"restrict"," ist eine Tabelle, die das Löschen ablehnt, sobald sie\neine Zeile für diesen Nutzer enthält.",[35,209,211],{"id":210},"was-löscht-on-delete-cascade","Was löscht on delete cascade?",[10,213,214],{},"Jede Zeile, die auf den Nutzer zeigt, dann jede Zeile, die auf diese zeigt, bei\njedem Löschen ab diesem Moment.",[10,216,217,218,220],{},"Es ist die Lösung, die man dir zuerst gibt, und Supabases Anleitung zur\nNutzerverwaltung verwendet sie für eine Profiltabelle: Dort heißt es, man solle\nin der Referenz ",[21,219,32],{}," angeben. Für ein Profil stimmt das. Ein\nProfil beschreibt die Person und sonst nichts, also soll es gehen, wenn sie\ngeht.",[10,222,223],{},"Schwierig wird es, wenn dieselben Worte auf jeder Tabelle landen. Supabases\nCascade-Anleitung beschreibt das Verhalten schlicht: Wird eine Zeile aus der\nElterntabelle gelöscht, werden alle zugehörigen Zeilen in den Kindtabellen\nebenfalls gelöscht. Und es geht weiter nach unten. Im eigenen Beispiel der\nAnleitung leert ein einziges Löschen in der obersten Tabelle die beiden Tabellen\ndarunter.",[10,225,226],{},"Im Verein sagt eine Kaskade dem Schriftführer, jede Zeile mit der Nummer des\nMitglieds herauszureißen und danach jede Zeile in jedem anderen Buch, die auf\neine herausgerissene Zeile zeigte. Stell dir einen Nutzer vor, der Beiträge\ngeschrieben hat, auf die Kommentare anderer Leute zeigen. Mit Kaskade auf beiden\nentfernt das Löschen dieses einen Nutzers seine Beiträge und die Kommentare\naller anderen darunter.",[228,229],"diagram",{"alt":230,"caption":231,"src":232},"Drei Bücher nebeneinander, durch Pfeile verbunden. Aus der Mitgliederliste links ist eine Zeile gestrichen. Im mittleren Buch sind die zwei Zeilen mit der Marke dieses Mitglieds herausgerissen. Im rechten Buch sind auch die Zeilen herausgerissen, die auf diese zwei zeigten, und die meisten tragen Marken anderer Mitglieder in anderen Farben.","Eine Kaskade folgt jeder Regel, die auf die gelöschte Zeile zeigt, dann jeder Regel, die auf diese zeigt. Das letzte Buch verliert Zeilen, die anderen Leuten gehörten.","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fthe-chain-1600x700.png",[10,234,235],{},"Nichts sagt dir, was mitgegangen ist. Auth beantwortet ein erfolgreiches Löschen\nmit einer leeren Antwort, das Dashboard zeigt ein Konto weniger, und die Zeilen,\ndie im selben Moment gegangen sind, fehlen, wenn das nächste Mal jemand nach\nihnen sucht.",[35,237,239],{"id":238},"was-jede-tabelle-behält","Was jede Tabelle behält",[10,241,242],{},"Entscheide pro Tabelle, denn jede hält etwas anderes über die Person fest, die\ngegangen ist.",[244,245,246,264],"table",{},[247,248,249],"thead",{},[250,251,252,256,261],"tr",{},[253,254,255],"th",{},"Was die Tabelle enthält",[253,257,258],{},[21,259,260],{},"on delete",[253,262,263],{},"Wenn der Nutzer gelöscht wird",[265,266,267,281,294],"tbody",{},[250,268,269,273,278],{},[270,271,272],"td",{},"Nur die Person: ein Profil, ihre Einstellungen",[270,274,275],{},[21,276,277],{},"cascade",[270,279,280],{},"Die Zeilen gehen mit",[250,282,283,286,291],{},[270,284,285],{},"Was andere noch brauchen: ein Kommentar im Thread eines anderen, ein Zahlungsbeleg",[270,287,288],{},[21,289,290],{},"set null",[270,292,293],{},"Die Zeilen bleiben, die Besitzerspalte ist leer",[250,295,296,299,304],{},[270,297,298],{},"Alles, worum du dich zuerst selbst kümmern willst",[270,300,301,303],{},[21,302,177],{}," (der Standard)",[270,305,306],{},"Das Löschen wird abgelehnt, solange diese Zeilen da sind",[10,308,309,311,312,318,319,322],{},[21,310,290],{}," kommt mit zwei Bedingungen. Die Spalte muss leere Werte erlauben,\nsonst schlägt das Löschen erneut fehl, mit einer eigenen Meldung,\n",[54,313,315],{"href":314},"\u002Fblog\u002Fnull-value-violates-not-null-constraint",[21,316,317],{},"null value in column … violates not-null constraint",". Und eine Policy der Form\n",[21,320,321],{},"user_id = auth.uid()"," zeigt diese Zeile nie wieder irgendwem, weil in SQL nichts\ngleich einem leeren Wert ist. Die Zeile bleibt erhalten, und deine App zeigt sie\nniemandem mehr.",[10,324,325],{},"Eine Regel zu ändern heißt, sie zu löschen und mit dem neuen Verhalten wieder\nanzulegen, so wie es Supabases Notiz empfiehlt:",[14,327,330],{"className":328,"code":329,"language":191,"meta":23},[189],"alter table public.profiles\n  drop constraint profiles_id_fkey,\n  add constraint profiles_id_fkey\n    foreign key (id) references auth.users (id) on delete cascade;\n",[21,331,329],{"__ignoreMap":23},[10,333,334],{},"Nimm den Regelnamen, den die Abfrage oben ausgegeben hat, mit deiner eigenen\nTabelle und Spalte.",[10,336,337,338,341,342,345,346,348],{},"Es gibt noch einen Weg, und der behält jede Zeile. Supabase Auth kann ein Konto\nweich löschen: ",[21,339,340],{},"auth.admin.deleteUser()"," nimmt die Option ",[21,343,344],{},"shouldSoftDelete",",\nund damit behält Auth die Zeile in ",[21,347,47],{},", markiert sie als gelöscht,\nverwürfelt E-Mail und Telefonnummer, leert Passwort und Metadaten und beendet\ndie Sessions. Entfernt wurde nichts, also greift kein Foreign Key. Das läuft auf\neinem Server mit deinem Secret Key, nie im Browser.",[228,350],{"alt":351,"caption":352,"src":353},"Dasselbe gelöschte Mitglied dreimal gezeichnet, je eine Bahn für no action, cascade und set null. In der ersten hält eine Schranke das Löschen auf, und die Zeile des Mitglieds und die Zeile, die auf sie zeigt, bleiben beide. In der zweiten wird die zeigende Zeile mit herausgerissen. In der dritten bleibt sie, mit einem leeren gestrichelten Platz, wo die Marke des Mitglieds war.","Dasselbe Löschen unter drei Regeln. Die erste lehnt ab und ändert nichts, die zweite nimmt die zeigende Zeile mit, und die dritte behält sie mit einem leeren Platz.","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fthree-outcomes-1600x760.png",[35,355,357],{"id":356},"ein-trigger-der-deine-tabelle-nicht-erreicht","Ein Trigger, der deine Tabelle nicht erreicht",[10,359,128,360,363,364,366],{},[21,361,362],{},"permission denied for table",", dann ist beim Löschen\nein Trigger auf ",[21,365,47],{}," gelaufen und wollte eine Tabelle anfassen, in die er\nnicht darf.",[10,368,369,370,373,374,376,377,380],{},"Die Rolle, als die Supabase Auth arbeitet, ",[21,371,372],{},"supabase_auth_admin",", hat nur die\nBerechtigungen, die ihre eigene Aufgabe braucht. Supabases Notiz sagt es so:\nWenn ein Trigger, den ",[21,375,372],{}," ausführt, außerhalb des Schemas auth\narbeitet, entsteht ein Berechtigungsfehler. Ein Trigger, der nach einem\ngelöschten Konto aufräumt, etwa indem er in eine eigene Log-Tabelle schreibt,\nscheitert genau so, außer seine Funktion wurde mit ",[21,378,379],{},"security definer"," angelegt.",[10,382,383,384,386,387,390,391,394],{},"Die Reparatur ist dieselbe wie bei der Registrierung: eine Funktion mit\n",[21,385,379],{},", angelegt von der Rolle ",[21,388,389],{},"postgres",", die eine eng begrenzte\nSache tut.\n",[54,392,393],{"href":56},"Die Registrierungs-Variante dieses Fehlers","\ngeht sie Zeile für Zeile durch, samt dem leeren Suchpfad, der sie sicher hält.",[10,396,397,398,400],{},"Wenn deine App Prisma benutzt, lies zuerst die dritte Ursache in Supabases\nNotiz, denn sie nennt Prisma als einen Weg, auf dem die Berechtigungen auf\n",[21,399,47],{}," kaputtgehen.",[35,402,404],{"id":403},"was-passiert-mit-den-dateien-die-die-person-hochgeladen-hat","Was passiert mit den Dateien, die die Person hochgeladen hat?",[10,406,407],{},"In einem aktuellen Projekt geht das Löschen durch, und die Dateien bleiben, wo\nsie sind.",[10,409,410,411,414,415,418,419,421,422,425,426,429,430,432,433,435],{},"Supabases Anleitung zur Nutzerverwaltung warnt weiterhin, dass du keinen Nutzer\nlöschen kannst, dem Objekte in Supabase Storage gehören. Das stimmte, solange\n",[21,412,413],{},"storage.objects",", die Tabelle, in der Storage für jede Datei eine Zeile führt,\neinen Foreign Key namens ",[21,416,417],{},"objects_owner_fkey"," auf ",[21,420,47],{}," hatte. Storage hat\ndiesen Key inzwischen in seinen eigenen Schema-Migrationen entfernt\n(",[21,423,424],{},"0017-drop-owner-foreign-key.sql","), und seine Anleitung zum Besitz von Dateien\nsagt jetzt, dass der Besitz in einer Spalte ",[21,427,428],{},"owner_id"," steht. Listet die Abfrage\nweiter oben ",[21,431,413],{}," mit ",[21,434,417],{},", hat dein Projekt noch die\nalte Regel, und die Warnung der Anleitung gilt für dich.",[10,437,438,439,442,443,58],{},"Sonst bleibt jede Datei, die die Person hochgeladen hat, nach ihrem Weggang in\nihrem Bucket. Im Verein hängen die Mäntel weiter an ihren Haken, mit einer\nNummernmarke, die niemand mehr hat. Eine Policy der Form\n",[21,440,441],{},"owner_id = auth.uid()::text"," passt nie wieder auf sie, und eine Datei in einem\nöffentlichen Bucket wird weiter jedem ausgeliefert, der ihren Link hat. Ob ein\nFremder die Dateien in einem deiner Buckets auflisten kann, ist einer der Checks\nim ",[54,444,446],{"href":445},"\u002Fsecurity-scanner","kostenlosen Scan von Reeve",[10,448,449,450,58],{},"Um sie zu entfernen, geh über Storage selbst, über die Storage-Seite im\nDashboard oder die Storage-API. Ein einfaches SQL-Delete auf seinen Tabellen\nwird abgelehnt, und Storage sagt, warum: \"Direct deletion from storage tables is\nnot allowed. Use the Storage API instead.\" Was eine Datenbankkopie von diesen\nDateien enthält und was nicht, steht in\n",[54,451,453],{"href":452},"\u002Fblog\u002Fsupabase-storage-backup","Supabase Storage sichern",[35,455,457],{"id":456},"mach-eine-kopie-bevor-du-einen-foreign-key-änderst","Mach eine Kopie, bevor du einen Foreign Key änderst",[10,459,460],{},"Postgres hat keinen Papierkorb, und eine Kaskade entfernt Zeilen aus Tabellen,\nauf die du gar nicht geschaut hast.",[10,462,463,464,466,467,471,472,476],{},"Was eine Kaskade oder ein ",[21,465,290],{}," ändert, ist endgültig, sobald das Löschen\ngelingt, und der einzige Weg zurück ist eine Kopie von vorher. Supabases\nFree-Plan behält gar keine Backups. Pro behält 7 Tage tägliche Kopien, Team 14\nund Enterprise bis zu 30, und jede davon liegt im selben Supabase-Projekt.\n",[54,468,470],{"href":469},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Deine Datenbank selbst zu kopieren","\nbraucht ein paar Befehle, und\n",[54,473,475],{"href":474},"\u002Fblog\u002Fsupabase-backup-auth-users","eine Kopie mit deinen Nutzern"," braucht den\ndritten der drei Befehle, die Supabase veröffentlicht.",[10,478,479],{},"Probier die neuen Regeln dann an einem Testkonto aus, bevor ein echtes dran ist.\nLeg ein Konto an, gib ihm eine Zeile in jeder Tabelle, die die Abfrage gelistet\nhat, lösch es und schau nach, was in jeder Tabelle übrig ist.",[10,481,482,483,487],{},"Wenn dir lieber wäre, dass diese Kopie schon existiert, bevor jemand auf Löschen\ndrückt, dafür gibt es ",[54,484,486],{"href":485},"\u002Fsupabase-backups","Supabase-Backups"," von Reeve.",[35,489,491],{"id":490},"ein-weg-zurück-wenn-ein-löschen-mehr-mitnimmt-als-gedacht","Ein Weg zurück, wenn ein Löschen mehr mitnimmt als gedacht",[10,493,494,497],{},[83,495,496],{},"Eine Kaskade meldet nichts darüber, was sie entfernt hat."," Du merkst es, wenn\njemand fragt, wo seine Kommentare geblieben sind.",[10,499,500],{},[83,501,502,505],{},[54,503,504],{"href":485},"Reeve Care"," hält eine Kopie deiner Supabase-Datenbank von\nvor dem Löschen:",[102,507,508,511,514,517,520],{},[79,509,510],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[79,512,513],{},"jede Kopie wird geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[79,515,516],{},"eine Wiederherstellung per Klick, die sichert, was jetzt da ist, bevor sie es ersetzt",[79,518,519],{},"deine hochgeladenen Dateien ebenfalls, sobald du eine Storage-Zugangsberechtigung verbindest",[79,521,522,523,527],{},"alles, was ",[54,524,526],{"href":525},"\u002Fwebsite-monitoring","Reeve Monitor"," tut: alle neun Checks deiner Live-App jede Stunde und eine Erreichbarkeitsprüfung alle 60 Sekunden",[35,529,531],{"id":530},"was-heute-zu-tun-ist","Was heute zu tun ist",[533,534,535],"key-takeaways",{},[102,536,537,540,543,552,555],{},[79,538,539],{},"Versuch das Löschen einmal, notier die Uhrzeit und lies die Postgres-Logzeile von diesem Moment, bevor du irgendetwas änderst.",[79,541,542],{},"Nennt sie einen Foreign Key, führ die Abfrage oben aus, um jede Tabelle aufzulisten, die auf deine Nutzer zeigt, und was jede beim Löschen tut.",[79,544,545,546,548,549,551],{},"Entscheide pro Tabelle: ",[21,547,277],{}," für Zeilen, die nur die Person beschreiben, ",[21,550,290],{}," für Zeilen, die andere noch brauchen, den Standard für alles, was du selbst wegräumen willst.",[79,553,554],{},"Mach eine Kopie der Datenbank, bevor du eine dieser Regeln änderst, und probier die neuen Regeln zuerst an einem Testkonto aus.",[79,556,557],{},"Entferne auch die Dateien der Person über Storage. In einem aktuellen Projekt geht das Konto, und die Dateien bleiben.",[10,559,560,561,565],{},"Wenn schon mehr Zeilen weg sind als gedacht, geht\n",[54,562,564],{"href":563},"\u002Fblog\u002Fai-agent-deleted-my-database","was du nach einem Löschen zurückbekommst","\ndurch, wo du in welcher Reihenfolge nachsiehst.",{"title":23,"searchDepth":567,"depth":567,"links":568},3,[569,571,572,573,574,575,576,577,578,579],{"id":37,"depth":570,"text":38},2,{"id":67,"depth":570,"text":68},{"id":124,"depth":570,"text":125},{"id":210,"depth":570,"text":211},{"id":238,"depth":570,"text":239},{"id":356,"depth":570,"text":357},{"id":403,"depth":570,"text":404},{"id":456,"depth":570,"text":457},{"id":490,"depth":570,"text":491},{"id":530,"depth":570,"text":531},"Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcover-1200x630.png","Eine Mitgliederliste mit einer durchgestrichenen Zeile, dahinter zwei Bücher, aus denen die Zeilen mit derselben Marke gerissen sind.","\"Database error deleting user\" in Supabase heißt: Deine Datenbank hat das Löschen abgelehnt. Der Grund steht im Log, die Lösung entscheidet, was mitgeht.",false,"md",[587,589,592,595,598],{"q":38,"a":588},"Supabase Auth wollte die Zeile der Person aus auth.users entfernen, etwas in deiner Datenbank hat das abgelehnt, und das ganze Löschen wurde rückgängig gemacht. Das Konto ist genau so wie vorher. Die Meldung nennt keine Tabelle, die Zeile, die eine nennt, steht im selben Moment in den Postgres-Logs deines Projekts.",{"q":590,"a":591},"Soll ich on delete cascade hinzufügen, um den Fehler zu beheben?","Auf einer Tabelle, die nur die Person beschreibt, etwa einer Profiltabelle, ja, und Supabases eigene Anleitung macht genau das. Auf einer Tabelle mit Dingen, die andere noch brauchen, etwa Kommentaren oder Bestellungen, entscheide vorher. Cascade löscht jede Zeile, die auf den Nutzer zeigt, und jede, die auf diese zeigt, bei jedem Löschen ab dann, und nichts meldet, was es entfernt hat.",{"q":593,"a":594},"Kann ich einen Nutzer löschen und seine Zeilen behalten?","Ja, auf zwei Wegen. Stell den Foreign Key auf on delete set null, dann bleiben die Zeilen mit leerer Besitzerspalte, wofür diese Spalte leere Werte erlauben muss. Oder ruf auth.admin.deleteUser() auf einem Server mit der Option shouldSoftDelete auf: Supabase Auth behält die Zeile, markiert sie als gelöscht, verwürfelt E-Mail und Telefonnummer und leert das Passwort, also wird nichts angefasst, was auf sie zeigt.",{"q":596,"a":597},"Warum sagt Supabase, dass ich einen Nutzer mit hochgeladenen Dateien nicht löschen kann?","Die Anleitung zur Nutzerverwaltung sagt das noch, und es stimmte, solange storage.objects einen Foreign Key namens objects_owner_fkey auf auth.users hatte. Supabase Storage hat diesen Key inzwischen in seinen eigenen Schema-Migrationen entfernt. In einem aktuellen Projekt geht das Löschen durch, und die Dateien bleiben in ihrem Bucket, unter einer owner_id, die kein Nutzer mehr hat.",{"q":599,"a":600},"Meldet das Löschen eines Nutzers ihn ab?","Nicht sofort. Laut Supabases Anleitung bleibt ein bereits ausgestellter Access Token gültig, bis er abläuft, auch nachdem das Konto gelöscht ist. Das Löschen entfernt die Sessions des Nutzers, die App bekommt also keinen neuen Token, aber der vorhandene funktioniert bis zu seiner Ablaufzeit.","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",[603,604,605,606,607,608,609],"database error deleting user supabase","database error deleting user","failed to delete user database error deleting user","supabase nutzer löschen foreign key","supabase on delete cascade auth users","supabase nutzer löschen storage","update or delete on table users violates foreign key constraint",{},true,"\"Database error deleting user\" in Supabase","\u002Fblog\u002Fdatabase-error-deleting-user","2026-10-30",{"title":5,"description":583},"blog\u002Fdatabase-error-deleting-user",[618,619,620],"\"Database error deleting user\" in Supabase heißt, dass das Löschen deine Datenbank erreicht hat und abgelehnt wurde, also wurde nichts entfernt. Die Zeile mit dem Grund steht in deinen Postgres-Logs, und genau dorthin schickt dich Supabases eigene Troubleshooting-Notiz.","Steht in dieser Zeile, dass ein Foreign Key verletzt wird, dann hält eine Zeile in einer deiner Tabellen noch die ID des Nutzers. Postgres entfernt niemanden, auf den noch etwas zeigt, außer du hast festgelegt, was mit diesen Zeilen passieren soll.","Die erste Antwort, die du findest, ist on delete cascade. Sie löscht jede Zeile, die auf den Nutzer zeigt, und jede Zeile, die auf diese zeigt, bei jedem Löschen ab diesem Moment. Entscheide pro Tabelle und mach eine Kopie, bevor du eine Regel änderst.","eaId4DbVu6me2yhTW_Dfi6iyCFEveGZpe-z_2YsgQFk",[623,630,636,641,646,652,658,664,670,676,682,683,689,695,701,707,713,719,725,731,737,743,749,755,761,767,773,778,784,790,796,802,808,814,820,826,832,838,844,850,856,862,868,874,880,886,891,897,903,908,914,920,926,932,938,944,950,956,961,967,973,979,985,991,997,1003,1009,1015,1021,1027,1033,1039,1045,1051,1057,1063,1069,1075,1081,1087,1093,1099,1104,1110,1115,1121,1127,1133,1138,1143],{"path":624,"title":625,"description":626,"published":627,"category":628,"image":629,"draft":584},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\" erklärt","Supabase \"max client connections reached\": Der Pooler hat keinen Platz für noch einen Client. Der Port in deinem Connection String setzt das Limit.","2026-11-09","Sicherheitsgrundlagen","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":631,"title":632,"description":633,"published":634,"category":628,"image":635,"draft":584},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Supabase-Fehler: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\" heißt: Google-Login ist in deinem Supabase-Projekt aus. Die Lösung, und was bei redirect_uri_mismatch hilft.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":166,"title":637,"description":638,"published":639,"category":628,"image":640,"draft":584},"Supabase-Fehler \"violates foreign key constraint\" beim Einfügen","Supabase \"insert or update on table violates foreign key constraint\": Deine Zeile zeigt auf eine, die es nicht gibt. Welche, warum, und die Lösung.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":314,"title":642,"description":643,"published":644,"category":628,"image":645,"draft":584},"Supabase-Fehler \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": Eine Pflichtspalte kam leer an. Woher die Null kommt, und die Lösung.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":647,"title":648,"description":649,"published":650,"category":628,"image":651,"draft":584},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": wo die Sitzung geblieben ist","\"Auth session missing!\" heißt: supabase-js fand keine angemeldete Sitzung und fragte Supabase gar nicht erst. Wo die Sitzung blieb, und die Lösung je Fall.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":653,"title":654,"description":655,"published":656,"category":628,"image":657,"draft":584},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": niemand ist angemeldet","\"invalid claim: missing sub claim\" heißt: Supabase Auth bekam ein echtes Token ohne Nutzer darin, deinen Projektschlüssel statt einer Sitzung.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":659,"title":660,"description":661,"published":662,"category":628,"image":663,"draft":584},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": der echte Grund","\"Failed to send a request to the Edge Function\" heißt: Der Browser hat keine lesbare Antwort bekommen. Seine Konsole sagt, warum, und ob deine Funktion lief.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":665,"title":666,"description":667,"published":668,"category":628,"image":669,"draft":584},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Warum Supabase-E-Mail-Links auf localhost:3000 weiterleiten","Leitet Supabase auf localhost:3000 um, ist die Site URL unverändert, oder deine Adresse fehlt in Redirect URLs. Die Lösung und der Platzhalter, den du meidest.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":671,"title":672,"description":673,"published":674,"category":628,"image":675,"draft":584},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" bei einem neuen Link","Bei einem Link von vor einer Minute heißt Supabases \"Email link is invalid or has expired\" meist: Ein Mailfilter hat ihn zuerst benutzt. Prüfen und beheben.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":677,"title":678,"description":679,"published":680,"category":628,"image":681,"draft":584},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\" erklärt","Supabase \"canceling statement due to statement timeout\": Eine Abfrage lief länger als ihre Rolle darf, 3 Sekunden für Besucher. Prüf zuerst die RLS-Regel.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":613,"title":5,"description":583,"published":614,"category":580,"image":601,"draft":584},{"path":684,"title":685,"description":686,"published":687,"category":628,"image":688,"draft":584},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" bei Supabase","Ein Stripe-Webhook in einer Supabase Edge Function meldet \"No signatures found matching the expected signature\"? Zwei Ursachen. Prüfe weiter.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":690,"title":691,"description":692,"published":693,"category":628,"image":694,"draft":584},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" in Supabase: die drei Ursachen","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":696,"title":697,"description":698,"published":699,"category":628,"image":700,"draft":584},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": der echte Fehler","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":702,"title":703,"description":704,"published":705,"category":628,"image":706,"draft":584},"\u002Fblog\u002Fcertificate-not-trusted","Zertifikat nicht vertrauenswürdig: drei Ursachen außer Ablauf","Zertifikat nicht vertrauenswürdig, obwohl das Datum stimmt? Es nennt eine andere Adresse, hat sich selbst signiert oder seiner Kette fehlt ein Glied.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":708,"title":709,"description":710,"published":711,"category":628,"image":712,"draft":584},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": was im Zitat steht","Supabase \"invalid input syntax for type uuid\" heißt: Deine App hat etwas geschickt, das keine ID ist. Zitat lesen, Abfrage zurückhalten, Spalte behalten.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":714,"title":715,"description":716,"published":717,"category":628,"image":718,"draft":584},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\" erklärt","Supabase \"duplicate key value violates unique constraint\" heißt: Der Wert ist schon vergeben. Spalte finden, Lösung wählen, Wert vom Bildschirm fernhalten.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":720,"title":721,"description":722,"published":723,"category":628,"image":724,"draft":584},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", obwohl die Tabelle da ist","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":726,"title":727,"description":728,"published":729,"category":628,"image":730,"draft":584},"\u002Fblog\u002Fsupabase-function-not-found","Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":732,"title":733,"description":734,"published":735,"category":628,"image":736,"draft":584},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" heißt meist: Der Name passt nicht. Vier Prüfungen und der Einzeiler zum Neuladen.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":738,"title":739,"description":740,"published":741,"category":628,"image":742,"draft":584},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": zwei Limits, ein Fehlercode","Supabase \"Email Rate Limit Exceeded\" begrenzt jede E-Mail deines Projekts: 2 pro Stunde beim eingebauten Absender. Was zählt und wie du es anhebst.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":744,"title":745,"description":746,"published":747,"category":628,"image":748,"draft":584},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 Ursachen","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" meldet deine Nutzer ab. Drei Ursachen, und wie das Auth-Log sie trennt.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":750,"title":751,"description":752,"published":753,"category":628,"image":754,"draft":584},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": drei Ursachen","Supabase \"permission denied for schema public\" heißt: Ein Grant auf das Schema fehlt. Was ihn entfernt hat und welche Zeile ihn zurückbringt.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":756,"title":757,"description":758,"published":759,"category":628,"image":760,"draft":584},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": die drei Dinge, die es bedeutet","Supabase \"Bucket not found\" ist eins von drei Dingen: ein öffentlicher Link zu einem privaten Bucket, ein ungenauer Name oder das falsche Projekt.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":762,"title":763,"description":764,"published":765,"category":628,"image":766,"draft":584},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: Welcher Schlüssel streikt hier?","Ein Supabase invalid JWT ist PGRST301: ein signiertes Token hat die Prüfung nicht bestanden. In neueren Projekten ist das die Sitzung, nicht der API-Schlüssel.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":768,"title":769,"description":770,"published":771,"category":628,"image":772,"draft":584},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" heißt meist: keine Zeilen","Supabase gibt PGRST116 zurück, \"JSON object requested, multiple (or no) rows returned\", wenn die Abfrage nichts fand. Versteckte Zeilen wirken fehlend.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":56,"title":774,"description":775,"published":776,"category":628,"image":777,"draft":584},"\"Database error saving new user\" in Supabase: wo du nachsiehst","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":782,"category":628,"image":783,"draft":584},"\u002Fblog\u002Fwhat-is-supabase","Was ist Supabase? Die Datenbank, die dein Builder ausgesucht hat","Was ist Supabase: die Datenbank, der Login und der Dateispeicher hinter deiner App. Supabase betreibt die Server, die Regeln zu deinen Zeilen gehören dir.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":785,"title":786,"description":787,"published":788,"category":628,"image":789,"draft":584},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Ein offengelegter AWS-Schlüssel im Frontend ist kein OpenAI-Key","Ein im Frontend offengelegter AWS-Zugriffsschlüssel liest und schreibt deinen Speicher. Die Lösung ist meist eine presigned URL, kein neuer Schlüssel.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":791,"title":792,"description":793,"published":794,"category":628,"image":795,"draft":584},"\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","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":797,"title":798,"description":799,"published":800,"category":628,"image":801,"draft":584},"\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":803,"title":804,"description":805,"published":806,"category":628,"image":807,"draft":584},"\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":809,"title":810,"description":811,"published":812,"category":628,"image":813,"draft":584},"\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":815,"title":816,"description":817,"published":818,"category":628,"image":819,"draft":584},"\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":821,"title":822,"description":823,"published":824,"category":628,"image":825,"draft":584},"\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":827,"title":828,"description":829,"published":830,"category":628,"image":831,"draft":584},"\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.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":833,"title":834,"description":835,"published":836,"category":628,"image":837,"draft":584},"\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":839,"title":840,"description":841,"published":842,"category":628,"image":843,"draft":584},"\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":845,"title":846,"description":847,"published":848,"category":628,"image":849,"draft":584},"\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":851,"title":852,"description":853,"published":854,"category":628,"image":855,"draft":584},"\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":857,"title":858,"description":859,"published":860,"category":628,"image":861,"draft":584},"\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":863,"title":864,"description":865,"published":866,"category":628,"image":867,"draft":584},"\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":869,"title":870,"description":871,"published":872,"category":580,"image":873,"draft":584},"\u002Fblog\u002Ftest-your-supabase-backup","Teste dein Supabase-Backup, bevor du es brauchst","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":875,"title":876,"description":877,"published":878,"category":580,"image":879,"draft":584},"\u002Fblog\u002Fsupabase-backup-github-action","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":881,"title":882,"description":883,"published":884,"category":580,"image":885,"draft":584},"\u002Fblog\u002Fdownload-your-supabase-backup","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":887,"title":888,"description":889,"published":884,"category":628,"image":890,"draft":584},"\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":892,"title":893,"description":894,"published":895,"category":628,"image":896,"draft":584},"\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":898,"title":899,"description":900,"published":901,"category":628,"image":902,"draft":584},"\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":474,"title":904,"description":905,"published":906,"category":580,"image":907,"draft":584},"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":909,"title":910,"description":911,"published":912,"category":628,"image":913,"draft":584},"\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":915,"title":916,"description":917,"published":918,"category":628,"image":919,"draft":584},"\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":921,"title":922,"description":923,"published":924,"category":628,"image":925,"draft":584},"\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":927,"title":928,"description":929,"published":930,"category":628,"image":931,"draft":584},"\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":933,"title":934,"description":935,"published":936,"category":628,"image":937,"draft":584},"\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":939,"title":940,"description":941,"published":942,"category":628,"image":943,"draft":584},"\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":945,"title":946,"description":947,"published":948,"category":628,"image":949,"draft":584},"\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":951,"title":952,"description":953,"published":954,"category":628,"image":955,"draft":584},"\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":452,"title":957,"description":958,"published":959,"category":580,"image":960,"draft":584},"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":962,"title":963,"description":964,"published":965,"category":580,"image":966,"draft":584},"\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":968,"title":969,"description":970,"published":971,"category":580,"image":972,"draft":584},"\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":974,"title":975,"description":976,"published":977,"category":628,"image":978,"draft":584},"\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":980,"title":981,"description":982,"published":983,"category":628,"image":984,"draft":584},"\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":986,"title":987,"description":988,"published":989,"category":628,"image":990,"draft":584},"\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":992,"title":993,"description":994,"published":995,"category":628,"image":996,"draft":584},"\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":998,"title":999,"description":1000,"published":1001,"category":628,"image":1002,"draft":584},"\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. Acht Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1004,"title":1005,"description":1006,"published":1007,"category":628,"image":1008,"draft":584},"\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":1010,"title":1011,"description":1012,"published":1013,"category":628,"image":1014,"draft":584},"\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":1016,"title":1017,"description":1018,"published":1019,"category":628,"image":1020,"draft":584},"\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":1022,"title":1023,"description":1024,"published":1025,"category":628,"image":1026,"draft":584},"\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":1028,"title":1029,"description":1030,"published":1031,"category":628,"image":1032,"draft":584},"\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":1034,"title":1035,"description":1036,"published":1037,"category":580,"image":1038,"draft":584},"\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":1040,"title":1041,"description":1042,"published":1043,"category":628,"image":1044,"draft":584},"\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":1046,"title":1047,"description":1048,"published":1049,"category":580,"image":1050,"draft":584},"\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":1052,"title":1053,"description":1054,"published":1055,"category":628,"image":1056,"draft":584},"\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":1058,"title":1059,"description":1060,"published":1061,"category":628,"image":1062,"draft":584},"\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":1064,"title":1065,"description":1066,"published":1067,"category":628,"image":1068,"draft":584},"\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":1070,"title":1071,"description":1072,"published":1073,"category":628,"image":1074,"draft":584},"\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":1076,"title":1077,"description":1078,"published":1079,"category":580,"image":1080,"draft":584},"\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":1082,"title":1083,"description":1084,"published":1085,"category":580,"image":1086,"draft":584},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","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":1088,"title":1089,"description":1090,"published":1091,"category":628,"image":1092,"draft":584},"\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":1094,"title":1095,"description":1096,"published":1097,"category":628,"image":1098,"draft":584},"\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":563,"title":1100,"description":1101,"published":1102,"category":580,"image":1103,"draft":584},"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":1105,"title":1106,"description":1107,"published":1108,"category":628,"image":1109,"draft":584},"\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":1111,"title":1112,"description":1113,"published":1108,"category":628,"image":1114,"draft":584},"\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":1116,"title":1117,"description":1118,"published":1119,"category":628,"image":1120,"draft":584},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: ist er derselbe wie der anon key?","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":1122,"title":1123,"description":1124,"published":1125,"category":580,"image":1126,"draft":584},"\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":1128,"title":1129,"description":1130,"published":1131,"category":628,"image":1132,"draft":584},"\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":1134,"title":1135,"description":1136,"published":1131,"category":580,"image":1137,"draft":584},"\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":469,"title":1139,"description":1140,"published":1141,"category":580,"image":1142,"draft":584},"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":1144,"title":1145,"description":1146,"published":1141,"category":628,"image":1147,"draft":584},"\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",1794213638695]