[{"data":1,"prerenderedAt":1367},["ShallowReactive",2],{"blog-de-canceling-statement-due-to-statement-timeout":3,"blog-index-de":838},{"id":4,"title":5,"body":6,"category":796,"cover":797,"coverAlt":798,"description":799,"draft":800,"extension":801,"faq":802,"image":817,"keywords":818,"meta":826,"navigation":827,"ogTitle":828,"path":829,"published":830,"seo":831,"stem":832,"tldr":833,"updated":830,"__hash__":837},"blog_de\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout.md","Supabase \"canceling statement due to statement timeout\" erklärt",{"type":7,"value":8,"toc":782},"minimark",[9,13,24,27,30,35,38,57,60,64,67,70,148,158,161,167,171,178,194,202,223,226,235,239,246,261,267,278,285,288,292,295,298,404,407,414,424,428,431,439,445,465,470,476,494,511,525,531,537,540,546,557,562,566,569,575,582,588,599,603,606,634,656,664,668,674,683,703,712,729,733,775],[10,11,12],"p",{},"Die Seite in deiner App lädt ihre Liste, der Spinner dreht sich ein paar\nSekunden, und dann kommt nichts. In der Browser-Konsole, oder in einer roten\nMeldung, die dein Builder eingebaut hat, steht eine Zeile:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","canceling statement due to statement timeout\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Du öffnest dieselbe Tabelle in Supabase, und jede Zeile ist da. Du fragst den\nBuilder, mit dem du die App gebaut hast (Lovable, Bolt, v0, Cursor, Claude Code\noder Replit), welche Abfrage diese Seite schickt, fügst sie in den SQL Editor\nein, und sie ist im Nu zurück.",[10,28,29],{},"Der erste Rat, den du zu \"canceling statement due to statement timeout\" in\nSupabase findest, lautet: das Limit erhöhen. Dieses Limit tut seine Arbeit, und\njeder Besucher deiner App teilt es. Bevor du irgendetwas erhöhst, sieh dir die\nRow-Level-Security-Regel auf dieser Tabelle an, also die Regel, die Postgres\nprüft, bevor es eine Zeile herausgibt. In Supabases eigenen Messungen ist das\ndie Stelle, an der eine Abfrage, die 7 Millisekunden dauern sollte, 11 Sekunden\nverbringt.",[31,32,34],"h2",{"id":33},"was-bedeutet-canceling-statement-due-to-statement-timeout-in-supabase","Was bedeutet \"canceling statement due to statement timeout\" in Supabase?",[10,36,37],{},"Postgres, die Datenbank in deinem Supabase-Projekt, hat die Abfrage gestoppt,\nweil sie länger lief, als die Rolle darf, die sie geschickt hat, und hat\nrückgängig gemacht, was die Abfrage bis dahin getan hatte.",[10,39,40,41,44,45,48,49,52,53,56],{},"Der Satz kommt von Postgres selbst, mit dem Fehlercode ",[21,42,43],{},"57014",", den Postgres\n",[21,46,47],{},"query_canceled"," nennt. Supabase reicht ihn unverändert an deine App weiter,\nalso trägt der Fehler, den dein Code bekommt, ",[21,50,51],{},"code: '57014'"," und diesen Satz\nals Nachricht. Postgres verwendet denselben Code für ",[21,54,55],{},"canceling statement due to user request",", einen Abbruch, um den jemand gebeten hat, deshalb sagt dir der\nSatz mehr als die Zahl.",[10,58,59],{},"Stell dir deine Datenbank als Bibliothek vor, mit einer Ausleihtheke und einem\nKüchenwecker. Jedes Mal, wenn jemand nach Büchern fragt, stellt die\nBibliothekarin den Wecker, bevor sie zu den Regalen geht, und wie lange er\nläuft, hängt davon ab, wer fragt. Wenn er klingelt, kommt jedes Buch zurück ins\nRegal, und der Besucher bekommt einen Zettel mit diesem Satz darauf. Sollte die\nAnfrage etwas ändern, wird auch die Änderung zurückgestellt.",[31,61,63],{"id":62},"warum-läuft-die-abfrage-im-sql-editor-und-scheitert-in-meiner-app","Warum läuft die Abfrage im SQL Editor und scheitert in meiner App?",[10,65,66],{},"Weil der SQL Editor als ein anderer Besucher fragt, einer ohne eigenen Wecker\nund ohne Regeln, die geprüft werden müssen.",[10,68,69],{},"Jede Anfrage erreicht Postgres unter einer Rolle, einem Namen, der festlegt,\nwas die Anfrage darf. Supabases Anleitung zu Timeouts nennt das Limit, mit dem\njede Rolle startet:",[71,72,73,89],"table",{},[74,75,76],"thead",{},[77,78,79,83,86],"tr",{},[80,81,82],"th",{},"Wer fragt",[80,84,85],{},"Rolle",[80,87,88],{},"Erlaubte Zeit",[90,91,92,106,119,135],"tbody",{},[77,93,94,98,103],{},[95,96,97],"td",{},"Ein Besucher deiner App ohne Anmeldung",[95,99,100],{},[21,101,102],{},"anon",[95,104,105],{},"3 Sekunden",[77,107,108,111,116],{},[95,109,110],{},"Ein angemeldeter Nutzer deiner App",[95,112,113],{},[21,114,115],{},"authenticated",[95,117,118],{},"8 Sekunden",[77,120,121,124,129],{},[95,122,123],{},"Dein Server, mit dem Secret Key",[95,125,126],{},[21,127,128],{},"service_role",[95,130,131,132],{},"kein eigenes Limit, also gelten die 8 Sekunden der Rolle ",[21,133,134],{},"authenticator",[77,136,137,140,145],{},[95,138,139],{},"Du, im Dashboard und im SQL Editor",[95,141,142],{},[21,143,144],{},"postgres",[95,146,147],{},"kein eigenes Limit, begrenzt durch einen Standard von 2 Minuten",[10,149,150,151,153,154,157],{},"Die Rolle des Editors hat noch einen zweiten Vorteil. Supabases Anleitung zu\nRow Level Security sagt, dass ",[21,152,144],{}," auf Supabase ",[21,155,156],{},"bypassrls"," hat, das\nPostgres-Attribut, das jede Regel überspringt. Der Editor antwortet also, ohne\neine einzige Regel zu lesen. Die Anfrage deiner App liest jede Regel auf der\nTabelle an jeder Zeile, die sie ansieht, mit einem Wecker, der für einen\nBesucher ohne Anmeldung nach drei Sekunden klingelt. Der Editor hat eine andere\nAbfrage gemessen als die, die deine App schickt.",[10,159,160],{},"In der Bibliothek gehörst du zum Personal. Du gehst ohne Wecker ins Magazin,\nund niemand will deinen Ausweis sehen. Der Besucher hat drei Sekunden, und die\nBibliothekarin prüft die Regeln an jedem Buch auf dem Weg.",[162,163],"diagram",{"alt":164,"caption":165,"src":166},"Dieselbe Abfrage als drei Balken auf einer Zeitachse. Bei postgres läuft der Balken ohne Häkchen bis zum Ende und endet mit einem Haken. Bei authenticated und anon trägt der Balken an jedem Schritt ein Häkchen; der authenticated-Balken endet mit einem Haken vor seiner Linie bei 8 Sekunden, der anon-Balken wird an seiner Linie bei 3 Sekunden rot abgeschnitten.","Eine Abfrage, drei Rollen. Die Rolle des Editors überspringt die Regel und hat keine Linie, die sie überschreiten kann; ein Besucher ohne Anmeldung durchläuft jede Prüfung und wird bei drei Sekunden gestoppt.","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fthree-clocks-1600x720.png",[31,168,170],{"id":169},"finde-die-abgebrochene-abfrage","Finde die abgebrochene Abfrage",[10,172,173,174,177],{},"Durchsuche die Postgres-Logs deines Projekts nach den Wörtern ",[21,175,176],{},"statement timeout"," und notier dir, welche Rolle die Abfrage geschickt hat.",[10,179,180,181,185,186,189,190,193],{},"Supabases Anleitung zu Timeouts hat dafür eine Abfrage. Öffne im Dashboard\n",[182,183,184],"strong",{},"Explorer",", wähl ",[182,187,188],{},"Run SQL",", setz die Quelle auf ",[182,191,192],{},"Logs",", wähl einen\nZeitraum, der den Fehler abdeckt, und führ diese gekürzte Fassung aus:",[14,195,200],{"className":196,"code":198,"language":199,"meta":23},[197],"language-sql","select timestamp,\n       log_attributes['parsed.user_name'] as user_name,\n       log_attributes['parsed.query'] as query\nfrom logs\nwhere source = 'postgres_logs'\n  and match(event_message, 'statement timeout')\norder by timestamp desc\nlimit 100;\n","sql",[21,201,198],{"__ignoreMap":23},[10,203,204,205,208,209,211,212,215,216,218,219,222],{},"Ein ",[21,206,207],{},"user_name"," von ",[21,210,134],{}," heißt, dass die Anfrage über die Data API\nkam, den Server, über den jeder ",[21,213,214],{},"supabase.from(…)","-Aufruf deiner App läuft. Die\nRollentabelle der Anleitung führt ",[21,217,134],{}," als PostgREST, und das ist\ndieser Server. Die Spalte ",[21,220,221],{},"query"," ist das SQL, zu dem die Anfrage deiner App\nwurde, und der Tabellenname darin ist die Tabelle, die du dir ansehen musst.",[10,224,225],{},"Die Seite Query Performance im Dashboard ist der andere Ort, an dem man\nnachsieht, und die Anleitung warnt, dass sie nur langsame Abfragen zeigt, die\nfertig wurden. Eine abgebrochene Abfrage steht in den Logs.",[10,227,228,229,234],{},"Zeigen die Logs Abbrüche auf allen Tabellen gleichzeitig, liegt der langsame\nTeil nicht an einer einzelnen Regel, und\n",[230,231,233],"a",{"href":232},"\u002Fblog\u002Fis-supabase-down-or-your-app","einen Supabase-Ausfall von einem Problem in deiner App unterscheiden","\nist der Ort, an dem du anfängst.",[31,236,238],{"id":237},"miss-sie-so-wie-deine-app-sie-ausführt","Miss sie so, wie deine App sie ausführt",[10,240,241,242,245],{},"Führ die Abfrage als Rolle deiner App aus, mit ",[21,243,244],{},"explain analyze"," davor, und\nPostgres gibt aus, wie lange sie gebraucht hat und wie viele Zeilen die Regel\nabgewiesen hat.",[10,247,248,249,252,253,256,257,260],{},"Das ist die Methode aus Supabases Anleitung zur Leistung von Row Level\nSecurity, eingepackt in ",[21,250,251],{},"begin"," und ",[21,254,255],{},"rollback",", damit der Rollenwechsel mit dem\nBlock endet. Kopier eine echte Nutzer-ID aus ",[182,258,259],{},"Authentication → Users"," an die\nStelle der Nullen:",[14,262,265],{"className":263,"code":264,"language":199,"meta":23},[197],"begin;\nset local role authenticated;\nset local request.jwt.claims to '{\"role\":\"authenticated\", \"sub\":\"00000000-0000-0000-0000-000000000000\"}';\nexplain analyze select * from public.orders;\nrollback;\n",[21,266,264],{"__ignoreMap":23},[10,268,269,270,273,274,277],{},"Zwei Zeilen der Ausgabe zählen. ",[21,271,272],{},"Execution Time"," ist die Zahl, die du gegen 3\nund 8 Sekunden hältst. ",[21,275,276],{},"Rows Removed by Filter"," zählt die Zeilen, die Postgres\ngelesen und die Regel abgewiesen hat, und Supabases Anleitung nennt sie das\nSignal, auf das man achten soll: Eine Regel, die bei jedem Lesen den größten\nTeil der Tabelle aussortiert, ist eine Regel, deren Filterspalte einen Index\nbraucht.",[10,279,280,281,284],{},"Um zu messen, was ein Besucher ohne Anmeldung bekommt, schreib ",[21,282,283],{},"set local role anon;"," und lass die Zeile mit den Claims weg.",[10,286,287],{},"Dieselbe Anleitung schlägt vor, die Abfrage einmal mit eingeschalteter und\neinmal mit ausgeschalteter Row Level Security laufen zu lassen, um zu sehen, ob\ndie Regel die Kosten verursacht. Sie sagt auch, das nur außerhalb der\nProduktion zu tun, weil das Ausschalten jede Zeile offenlegt. In einer Live-App\nmiss stattdessen die Regel gegen ihre umgeschriebene Fassung.",[31,289,291],{"id":290},"wie-kann-eine-regel-sekunden-kosten","Wie kann eine Regel Sekunden kosten?",[10,293,294],{},"Postgres prüft die Regel an jeder Zeile, die die Abfrage liest, und ein\nFunktionsaufruf in der Regel läuft für jede dieser Zeilen erneut.",[10,296,297],{},"Supabase hat dazu Messungen veröffentlicht, an einer Tabelle mit 100.000\nZeilen. Vier davon, der langsame und der schnelle Weg:",[71,299,300,318],{},[74,301,302],{},[77,303,304,307,310,313,316],{},[80,305,306],{},"Was die Regel prüft",[80,308,309],{},"Geschrieben als",[80,311,312],{},"Dauer",[80,314,315],{},"Umgeschrieben als",[80,317,312],{},[90,319,320,341,362,383],{},[77,321,322,325,330,333,338],{},[95,323,324],{},"Zeilen, die dem angemeldeten Nutzer gehören",[95,326,327],{},[21,328,329],{},"auth.uid() = user_id",[95,331,332],{},"179 ms",[95,334,335],{},[21,336,337],{},"(select auth.uid()) = user_id",[95,339,340],{},"9 ms",[77,342,343,346,350,353,359],{},[95,344,345],{},"Dieselbe Regel, ohne Index auf der Spalte",[95,347,348],{},[21,349,329],{},[95,351,352],{},"171 ms",[95,354,355,356],{},"dieselbe, mit einem Index auf ",[21,357,358],{},"user_id",[95,360,361],{},"unter 0,1 ms",[77,363,364,367,372,375,380],{},[95,365,366],{},"Eine Admin-Prüfung, die eine andere Tabelle liest",[95,368,369],{},[21,370,371],{},"is_admin()",[95,373,374],{},"11.000 ms",[95,376,377],{},[21,378,379],{},"(select is_admin())",[95,381,382],{},"7 ms",[77,384,385,388,393,396,401],{},[95,386,387],{},"Eine Rolle, nachgeschlagen in einer anderen Tabelle",[95,389,390],{},[21,391,392],{},"has_role() = role",[95,394,395],{},"178.000 ms",[95,397,398],{},[21,399,400],{},"(select has_role()) = role",[95,402,403],{},"12 ms",[10,405,406],{},"Die ersten beiden sind langsam und auf dieser Tabelle trotzdem unter drei\nSekunden. Die letzten beiden liegen jenseits jedes Limits, das eine Anfrage\neiner App hat. Eine Hilfsfunktion, die eine zweite Tabelle liest, die Art, die\nman schreibt, um zu prüfen, ob jemand Admin ist, wird für jede Zeile der ersten\neinmal aufgerufen, also hat sie auf dieser Tabelle die zweite 100.000 Mal\ngelesen.",[10,408,409,410,413],{},"In der Bibliothek ist dieser Helfer die Bibliothekarin, die für jedes Buch im\nRegal zum Büro vorne läuft, um zu fragen, ob du zum Personal gehörst. Ihn in\n",[21,411,412],{},"(select …)"," zu packen heißt, einmal zu fragen und die Antwort auf den Zettel zu\nschreiben.",[10,415,416,417],{},"Supabases Performance Advisor fängt einen Teil davon ab. Seine Regel namens\nAuth RLS Initialization Plan meldet eine Regel, die \"re-evaluates\ncurrent_setting() or auth.",[418,419,420,421,423],"function",{},"() for each row\". Ein Helfer von dir, etwa\n",[21,422,371],{},", fällt nicht unter diese Beschreibung, also hat eine leere\nAdvisor-Seite deine Helfer nicht geprüft. Lies die Regeln auf der Tabelle selbst\nnach Funktionsaufrufen durch, die nicht eingepackt sind.",[31,425,427],{"id":426},"reparier-es-in-dieser-reihenfolge","Reparier es in dieser Reihenfolge",[10,429,430],{},"Funktionsaufrufe einpacken, die verglichene Spalte indexieren, dann die Rolle\nnennen. Jeder Schritt ist ein kurzes Stück SQL, das du im Editor ausführen oder\ndeinem Builder geben kannst.",[10,432,433],{},[182,434,435,436,438],{},"1. Pack jeden Funktionsaufruf in ",[21,437,412],{},".",[14,440,443],{"className":441,"code":442,"language":199,"meta":23},[197],"alter policy \"read own orders\" on public.orders\n  using ( (select auth.uid()) = user_id );\n",[21,444,442],{"__ignoreMap":23},[10,446,447,450,451,454,455,459,460,464],{},[21,448,449],{},"alter policy"," behält den Namen und die Rolle der Regel und ersetzt die\nBedingung. Nimm den Namen deiner Regel und die Spalte deiner Tabelle, und mach\ndasselbe mit einem Helfer: ",[21,452,453],{},"(select private.is_admin())",". Supabase nennt eine\nBedingung: Das funktioniert nur für einen Wert, der von Zeile zu Zeile gleich\nbleibt. Warum die Klammern den Unterschied machen, steht in\n",[230,456,458],{"href":457},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","der Anleitung zum Einschalten von Row Level Security",",\nund ein Helfer, der geschrieben wurde, um\n",[230,461,463],{"href":462},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","einen Fehler wegen unendlicher Rekursion zu beheben",",\nist genau die Art, die sie braucht.",[10,466,467],{},[182,468,469],{},"2. Indexier die Spalte, die die Regel vergleicht.",[14,471,474],{"className":472,"code":473,"language":199,"meta":23},[197],"create index orders_user_id_idx on public.orders (user_id);\n",[21,475,473],{"__ignoreMap":23},[10,477,478,479,482,483,485,486,489,490,493],{},"Supabases Anleitung nennt einen Haken. Eine Spalte gilt nur dann als\nindexiert, wenn sie im Index an erster Stelle steht, also hat eine Tabelle mit\ndem Primärschlüssel ",[21,480,481],{},"(team_id, user_id)"," keinen Index auf ",[21,484,358],{},". Auf einer\ngroßen Tabelle, in die geschrieben wird, während du arbeitest, sagt die\nPostgres-Dokumentation, dass ein normales ",[21,487,488],{},"create index"," die Tabelle für\nSchreibzugriffe sperrt, bis der Index fertig ist. ",[21,491,492],{},"create index concurrently","\nbaut ihn ohne diese Sperre, und es muss als eigene Anweisung laufen, außerhalb\neiner Transaktion.",[10,495,496,499,500,503,504,507,508,510],{},[182,497,498],{},"3. Nenn die Rolle, für die die Regel gilt."," Eine Regel mit ",[21,501,502],{},"to authenticated"," läuft für einen Besucher ohne Anmeldung nie. In Supabases\nMessungen brauchte eine Anfrage ohne Anmeldung gegen eine Regel ohne ",[21,505,506],{},"to"," 170\nms und mit ",[21,509,502],{}," unter 0,1 ms.",[10,512,513,516,517,520,521,524],{},[182,514,515],{},"4. Filtere auch in der Anfrage."," Eine Regel wirkt wie ein unsichtbares\n",[21,518,519],{},"where"," an jeder Abfrage, und Supabases Anleitung empfiehlt, es in der Anfrage\ndeiner App zu wiederholen, ",[21,522,523],{},".eq('user_id', userId)",", weil Postgres damit eine\nschnellere Abfrage planen kann. In ihren Messungen brachte das eine Abfrage von\n171 ms auf 9.",[10,526,527,530],{},[182,528,529],{},"5. Nimm den Join aus einer Team-Regel."," Eine Regel, die jede Zeile gegen\neine Mitgliedertabelle abgleicht, macht diese Suche pro Zeile:",[14,532,535],{"className":533,"code":534,"language":199,"meta":23},[197],"using ( (select auth.uid()) in (\n  select user_id from team_user where team_user.team_id = projects.team_id\n) )\n",[21,536,534],{"__ignoreMap":23},[10,538,539],{},"Supabases Anleitung schreibt sie so um, dass sie die Teams einmal liest und\ngegen diese Liste vergleicht:",[14,541,544],{"className":542,"code":543,"language":199,"meta":23},[197],"using ( team_id in (\n  select team_id from team_user where user_id = (select auth.uid())\n) )\n",[21,545,543],{"__ignoreMap":23},[10,547,548,549,551,552,252,554,556],{},"Dann führ das ",[21,550,244],{}," von oben noch einmal aus und vergleich\n",[21,553,272],{},[21,555,276],{}," mit dem, was du vorher hattest.",[162,558],{"alt":559,"caption":560,"src":561},"Zwei Regale mit denselben zwölf Zeilen. Links läuft eine Suchlinie an jeder Zeile vorbei, neben jeder steht ein Häkchen, und drei davon leuchten. Rechts zeigt eine Indexkarte mit drei Reitern direkt auf dieselben drei leuchtenden Zeilen, und die übrigen tragen keine Markierung.","Ohne Index liest die Regel jede Zeile, um die wenigen zu finden, die dir gehören. Mit Index geht Postgres direkt zu ihnen.","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fevery-row-or-the-few-1600x700.png",[31,563,565],{"id":564},"soll-ich-den-statement-timeout-erhöhen","Soll ich den Statement Timeout erhöhen?",[10,567,568],{},"Nur für eine Abfrage, die du gemessen, umgeschrieben und immer noch gebraucht\nhast, und dann für diese eine Funktion statt für eine ganze Rolle.",[10,570,571,572,574],{},"Die Limits sind Absicht. Supabases Anleitung zum Datenimport sagt, die Limits\nsollen die Ressourcen fair verteilen und verhindern, dass lange laufende\nAbfragen das ganze System beeinträchtigen. Das ",[21,573,102],{},"-Limit teilen sich alle\nBesucher ohne Anmeldung, und jeder kann diese Anfrage mit dem Publishable Key\nschicken, der in deiner App mitkommt. Es von drei auf dreißig Sekunden zu\nerhöhen, gibt jeder dieser Anfragen dreißig Sekunden deiner Datenbank.",[10,576,577,578,581],{},"Wenn ein Job wirklich länger braucht, gib das Limit der Funktion, die ihn\nausführt. Supabases Anleitung beschreibt das für wiederkehrende Funktionen, die\neine Ausnahme bei der Laufzeit brauchen, und es funktioniert für eine Funktion,\ndie deine App mit ",[21,579,580],{},"supabase.rpc(…)"," aufruft:",[14,583,586],{"className":584,"code":585,"language":199,"meta":23},[197],"alter function public.monthly_totals() set statement_timeout to '20s';\n",[21,587,585],{"__ignoreMap":23},[10,589,590,591,594,595,598],{},"Wenn du doch eine Rolle änderst, lauten die Befehle der Anleitung\n",[21,592,593],{},"alter role authenticated set statement_timeout = '15s';"," und danach\n",[21,596,597],{},"notify pgrst, 'reload config';",", damit die Data API den neuen Wert übernimmt.\nSupabase begrenzt Abfragen aus seinen Client-Bibliotheken auf 60 Sekunden, egal\nwas du einstellst.",[31,600,602],{"id":601},"zwei-lösungen-die-die-meldung-stoppen-und-die-tabelle-öffnen","Zwei Lösungen, die die Meldung stoppen und die Tabelle öffnen",[10,604,605],{},"Row Level Security auf der Tabelle ausschalten, und die Anfrage mit dem Secret\nKey schicken. Beide machen die Abfrage schnell, weil beide die Regel\nüberspringen, und beide geben die Zeilen an Leute, die sie nie haben sollten.",[10,607,608,611,612,615,616,619,620,623,624,252,627,630,631,633],{},[182,609,610],{},"Ausschalten."," Ohne Regel wird pro Zeile nichts geprüft, und der Timeout\nverschwindet. Supabase druckt seine eigene Warnung direkt neben den Test, der\ndas vorschlägt: Wer Row Level Security ausschaltet, legt jede Zeile der Tabelle\nfür jede Rolle mit passender Berechtigung offen. Seine Anleitung sagt auch, dass\nbei bestehenden Projekten eine neue Tabelle in ",[21,613,614],{},"public"," mit ",[21,617,618],{},"select",", ",[21,621,622],{},"insert",",\n",[21,625,626],{},"update",[21,628,629],{},"delete"," für ",[21,632,102],{}," startet, die Rolle eines Besuchers ohne\nAnmeldung. Ist die Regel weg, stehen nur noch diese Berechtigungen zwischen\ndiesem Besucher und der Tabelle.",[10,635,636,639,640,642,643,645,646,650,651,653,654,438],{},[182,637,638],{},"Der Secret Key."," Supabases Anleitung sagt, dass auch die Rolle\n",[21,641,128],{}," dahinter ",[21,644,156],{}," hat, also läuft keine Regel. Dieser\nSchlüssel gehört auf einen Server, und einer, der aus dem Browser geschickt\nwird, ist ein Schlüssel, den jeder aus deiner Seite auslesen kann;\n",[230,647,649],{"href":648},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","welche Schlüssel im Frontend sicher sind","\ngeht das Paar durch. Viel Zeit bringt er auch nicht, denn die Anleitung gibt\n",[21,652,128],{}," dieselben 8 Sekunden wie ",[21,655,134],{},[10,657,658,659,663],{},"Ob eine deiner Tabellen auf eine Anfrage ganz ohne Anmeldung antwortet, ist\neiner der neun Checks in ",[230,660,662],{"href":661},"\u002Fsecurity-scanner","Reeves kostenlosem Scan",". Er liest\ndeine Live-Seite so, wie ein Besucher sie sieht, dauert etwa 20 Sekunden und\nbraucht kein Konto.",[31,665,667],{"id":666},"damit-die-regel-schnell-und-die-tabelle-zu-bleibt","Damit die Regel schnell und die Tabelle zu bleibt",[10,669,670,673],{},[182,671,672],{},"Eine Regel, die du heute repariert hast, bekommt eine nächste Fassung."," Dein\nBuilder schreibt Regeln, wann immer ein Feature eine braucht, also kann die\nnächste wieder pro Zeile eine Funktion aufrufen oder die Tabelle öffnen, damit\nein Bildschirm lädt.",[10,675,676],{},[182,677,678,682],{},[230,679,681],{"href":680},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft deine App von außen, jede Stunde:",[684,685,686,690,693,700],"ul",{},[687,688,689],"li",{},"alle neun Checks stündlich, auch ob irgendeine Tabelle auf eine Anfrage ohne Anmeldung antwortet",[687,691,692],{},"ob die App läuft, alle 60 Sekunden",[687,694,695,696,699],{},"eine Nachricht, wenn sich ein Ergebnis ",[182,697,698],{},"ändert",", damit eine Tabelle, die plötzlich Fremden antwortet, nicht wartet, bis du nachsiehst",[687,701,702],{},"ein Monatsbericht über das, was er gesehen hat",[10,704,705],{},[182,706,707,711],{},[230,708,710],{"href":709},"\u002Fsupabase-backups","Reeve Care"," hält eine Kopie deiner Supabase-Datenbank von\nvor deiner Änderung:",[684,713,714,717,720,723,726],{},[687,715,716],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[687,718,719],{},"jede Kopie wird geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[687,721,722],{},"eine Wiederherstellung per Klick, die sichert, was jetzt da ist, bevor sie es ersetzt",[687,724,725],{},"deine hochgeladenen Dateien ebenfalls, sobald du eine Storage-Zugangsberechtigung verbindest",[687,727,728],{},"alles, was Monitor tut",[31,730,732],{"id":731},"was-heute-zu-tun-ist","Was heute zu tun ist",[734,735,736],"key-takeaways",{},[684,737,738,744,760,766,772],{},[687,739,740,741,743],{},"Durchsuch die Postgres-Logs nach ",[21,742,176],{}," und notier dir die Abfrage und die Rolle, die sie geschickt hat.",[687,745,746,747,749,750,752,753,755,756,252,758,438],{},"Miss diese Abfrage mit ",[21,748,244],{}," als ",[21,751,102],{}," oder ",[21,754,115],{},", den Rollen, die deine App benutzt, und lies ",[21,757,272],{},[21,759,276],{},[687,761,762,763,765],{},"Pack jeden Funktionsaufruf in den Regeln dieser Tabelle in ",[21,764,412],{},", auch eigene Helfer, die der Performance Advisor nicht meldet.",[687,767,768,769,771],{},"Indexier die Spalte, die jede Regel vergleicht, und schreib ",[21,770,502],{}," an jede Regel, die nur für angemeldete Nutzer gedacht ist.",[687,773,774],{},"Erhöh ein Limit zuletzt, an der einen Funktion, die es braucht, und lass Row Level Security an.",[10,776,777,778,781],{},"Fang mit der Tabelle hinter der Seite an, die gescheitert ist. Hat sie noch\nkeine eigenen Regeln,\n",[230,779,780],{"href":457},"Row Level Security auf jeder Tabelle einschalten","\nhat die drei Formen, die die meisten Tabellen brauchen.",{"title":23,"searchDepth":783,"depth":783,"links":784},3,[785,787,788,789,790,791,792,793,794,795],{"id":33,"depth":786,"text":34},2,{"id":62,"depth":786,"text":63},{"id":169,"depth":786,"text":170},{"id":237,"depth":786,"text":238},{"id":290,"depth":786,"text":291},{"id":426,"depth":786,"text":427},{"id":564,"depth":786,"text":565},{"id":601,"depth":786,"text":602},{"id":666,"depth":786,"text":667},{"id":731,"depth":786,"text":732},"Sicherheitsgrundlagen","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcover-1200x630.png","Eine Stoppuhr, deren Zeiger über die Markierung hinaus ist, vor einem langen Regal aus Zeilen, von denen nur die ersten abgehakt sind.","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.",false,"md",[803,805,808,811,814],{"q":34,"a":804},"Postgres hat deine Abfrage gestoppt, weil sie länger lief, als die Rolle darf, die sie geschickt hat, und hat rückgängig gemacht, was sie bis dahin getan hatte. Supabase gibt Besuchern ohne Anmeldung 3 Sekunden und angemeldeten Nutzern 8. Der Fehler trägt den Code 57014, den Postgres auch für eine auf Wunsch abgebrochene Abfrage verwendet, also lies den Satz und nicht nur die Zahl.",{"q":806,"a":807},"Warum läuft meine Abfrage im SQL Editor, aber in meiner App gibt es einen Timeout?","Weil der SQL Editor als Rolle postgres arbeitet und deine App nicht. Supabase gibt postgres kein eigenes Limit, und die Rolle hat bypassrls, also führt der Editor deine Row-Level-Security-Regeln nie aus. Deine App läuft als anon oder authenticated, mit 3 oder 8 Sekunden Limit, und jede Regel wird an jeder Zeile geprüft, die die Abfrage liest.",{"q":809,"a":810},"Kann Row Level Security einen Statement Timeout auslösen?","Ja. Postgres prüft die Regel an jeder Zeile, die die Abfrage liest, und ein Funktionsaufruf in der Regel läuft für jede davon erneut. In Messungen, die Supabase für eine Tabelle mit 100.000 Zeilen veröffentlicht hat, brauchte eine Regel mit einem Helfer is_admin() 11.000 Millisekunden und dieselbe Regel mit dem Aufruf als (select is_admin()) 7.",{"q":812,"a":813},"Wie erhöhe ich den Statement Timeout in Supabase?","Für einen einzelnen langsamen Job setzt du ihn an der Funktion, die ihn ausführt, mit alter function … set statement_timeout. Für eine ganze Rolle führst du alter role mit dem neuen statement_timeout aus und danach notify pgrst, 'reload config', damit die Data API den Wert übernimmt. Supabase begrenzt Abfragen aus seinen Client-Bibliotheken auf 60 Sekunden. Reparier zuerst die Regel, denn das anon-Limit teilen sich alle Besucher ohne Anmeldung.",{"q":815,"a":816},"Soll ich RLS ausschalten, damit die Abfrage schneller wird?","Nein. Die Abfrage wird schneller, weil keine Regel mehr läuft, und die Tabelle steht dann jeder Rolle offen, die eine Berechtigung darauf hat. Laut Supabases Anleitung startet eine neue Tabelle in public bei bestehenden Projekten mit select, insert, update und delete für anon, die Rolle eines Besuchers ohne Anmeldung. Pack stattdessen die Funktionsaufrufe ein und leg einen Index an.","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",[819,820,821,822,823,824,825],"canceling statement due to statement timeout supabase","canceling statement due to statement timeout","supabase statement timeout","57014 supabase","supabase abfrage timeout anon","supabase rls langsam","supabase statement timeout erhöhen",{},true,"Supabase \"canceling statement due to statement timeout\"","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","2026-10-31",{"title":5,"description":799},"blog\u002Fcanceling-statement-due-to-statement-timeout",[834,835,836],"\"canceling statement due to statement timeout\" in Supabase heißt, Postgres hat eine Abfrage gestoppt, weil sie länger lief, als die Rolle darf, die sie geschickt hat: 3 Sekunden für Besucher ohne Anmeldung, 8 für angemeldete. Von dem, was die Abfrage tat, bleibt nichts.","Im SQL Editor läuft dieselbe Abfrage durch, weil der Editor als Rolle postgres arbeitet. Die hat kein eigenes Limit und überspringt deine Row-Level-Security-Regeln ganz. Deine App prüft jede Regel an jeder Zeile, die sie liest.","Reparier die Regel, bevor du das Limit anfasst: Funktionsaufrufe in (select …) packen, die verglichene Spalte indexieren, die Rolle nennen. Ein höheres Limit für Besucher gibt jedem Fremden mehr Zeit mit deiner Datenbank.","do8gaij9vGChGl4YRA3xdQux6ThVS9HLrvIn4T0A0qw",[839,845,851,857,863,869,875,881,887,893,894,901,907,913,919,925,931,937,943,949,955,961,967,973,979,985,991,997,1003,1009,1015,1021,1027,1032,1038,1044,1050,1056,1062,1068,1073,1079,1085,1091,1097,1103,1108,1114,1120,1126,1132,1138,1144,1150,1156,1162,1168,1174,1180,1186,1192,1198,1203,1209,1215,1221,1227,1233,1239,1245,1251,1257,1263,1269,1275,1281,1287,1293,1299,1305,1311,1317,1323,1329,1334,1340,1346,1352,1357,1363],{"path":840,"title":841,"description":842,"published":843,"category":796,"image":844,"draft":800},"\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","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":846,"title":847,"description":848,"published":849,"category":796,"image":850,"draft":800},"\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":852,"title":853,"description":854,"published":855,"category":796,"image":856,"draft":800},"\u002Fblog\u002Fviolates-foreign-key-constraint","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":858,"title":859,"description":860,"published":861,"category":796,"image":862,"draft":800},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","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":864,"title":865,"description":866,"published":867,"category":796,"image":868,"draft":800},"\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":870,"title":871,"description":872,"published":873,"category":796,"image":874,"draft":800},"\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":876,"title":877,"description":878,"published":879,"category":796,"image":880,"draft":800},"\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":882,"title":883,"description":884,"published":885,"category":796,"image":886,"draft":800},"\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":888,"title":889,"description":890,"published":891,"category":796,"image":892,"draft":800},"\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":829,"title":5,"description":799,"published":830,"category":796,"image":817,"draft":800},{"path":895,"title":896,"description":897,"published":898,"category":899,"image":900,"draft":800},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" in Supabase und was mitgelöscht wird","\"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.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":902,"title":903,"description":904,"published":905,"category":796,"image":906,"draft":800},"\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":908,"title":909,"description":910,"published":911,"category":796,"image":912,"draft":800},"\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":914,"title":915,"description":916,"published":917,"category":796,"image":918,"draft":800},"\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":920,"title":921,"description":922,"published":923,"category":796,"image":924,"draft":800},"\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":926,"title":927,"description":928,"published":929,"category":796,"image":930,"draft":800},"\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":932,"title":933,"description":934,"published":935,"category":796,"image":936,"draft":800},"\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":938,"title":939,"description":940,"published":941,"category":796,"image":942,"draft":800},"\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":944,"title":945,"description":946,"published":947,"category":796,"image":948,"draft":800},"\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":950,"title":951,"description":952,"published":953,"category":796,"image":954,"draft":800},"\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":956,"title":957,"description":958,"published":959,"category":796,"image":960,"draft":800},"\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":962,"title":963,"description":964,"published":965,"category":796,"image":966,"draft":800},"\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":968,"title":969,"description":970,"published":971,"category":796,"image":972,"draft":800},"\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":974,"title":975,"description":976,"published":977,"category":796,"image":978,"draft":800},"\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":980,"title":981,"description":982,"published":983,"category":796,"image":984,"draft":800},"\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":986,"title":987,"description":988,"published":989,"category":796,"image":990,"draft":800},"\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":992,"title":993,"description":994,"published":995,"category":796,"image":996,"draft":800},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"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":998,"title":999,"description":1000,"published":1001,"category":796,"image":1002,"draft":800},"\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":1004,"title":1005,"description":1006,"published":1007,"category":796,"image":1008,"draft":800},"\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":1010,"title":1011,"description":1012,"published":1013,"category":796,"image":1014,"draft":800},"\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":1016,"title":1017,"description":1018,"published":1019,"category":796,"image":1020,"draft":800},"\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":1022,"title":1023,"description":1024,"published":1025,"category":796,"image":1026,"draft":800},"\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":462,"title":1028,"description":1029,"published":1030,"category":796,"image":1031,"draft":800},"\"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":1033,"title":1034,"description":1035,"published":1036,"category":796,"image":1037,"draft":800},"\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":1039,"title":1040,"description":1041,"published":1042,"category":796,"image":1043,"draft":800},"\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":1045,"title":1046,"description":1047,"published":1048,"category":796,"image":1049,"draft":800},"\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":1051,"title":1052,"description":1053,"published":1054,"category":796,"image":1055,"draft":800},"\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":1057,"title":1058,"description":1059,"published":1060,"category":796,"image":1061,"draft":800},"\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":1063,"title":1064,"description":1065,"published":1066,"category":796,"image":1067,"draft":800},"\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":232,"title":1069,"description":1070,"published":1071,"category":796,"image":1072,"draft":800},"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":1074,"title":1075,"description":1076,"published":1077,"category":796,"image":1078,"draft":800},"\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":1080,"title":1081,"description":1082,"published":1083,"category":796,"image":1084,"draft":800},"\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":1086,"title":1087,"description":1088,"published":1089,"category":899,"image":1090,"draft":800},"\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":1092,"title":1093,"description":1094,"published":1095,"category":899,"image":1096,"draft":800},"\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":1098,"title":1099,"description":1100,"published":1101,"category":899,"image":1102,"draft":800},"\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":1104,"title":1105,"description":1106,"published":1101,"category":796,"image":1107,"draft":800},"\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":1109,"title":1110,"description":1111,"published":1112,"category":796,"image":1113,"draft":800},"\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":1115,"title":1116,"description":1117,"published":1118,"category":796,"image":1119,"draft":800},"\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":1121,"title":1122,"description":1123,"published":1124,"category":899,"image":1125,"draft":800},"\u002Fblog\u002Fsupabase-backup-auth-users","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":1127,"title":1128,"description":1129,"published":1130,"category":796,"image":1131,"draft":800},"\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":1133,"title":1134,"description":1135,"published":1136,"category":796,"image":1137,"draft":800},"\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":1139,"title":1140,"description":1141,"published":1142,"category":796,"image":1143,"draft":800},"\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":1145,"title":1146,"description":1147,"published":1148,"category":796,"image":1149,"draft":800},"\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":1151,"title":1152,"description":1153,"published":1154,"category":796,"image":1155,"draft":800},"\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":1157,"title":1158,"description":1159,"published":1160,"category":796,"image":1161,"draft":800},"\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":1163,"title":1164,"description":1165,"published":1166,"category":796,"image":1167,"draft":800},"\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":1169,"title":1170,"description":1171,"published":1172,"category":796,"image":1173,"draft":800},"\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":1175,"title":1176,"description":1177,"published":1178,"category":899,"image":1179,"draft":800},"\u002Fblog\u002Fsupabase-storage-backup","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":1181,"title":1182,"description":1183,"published":1184,"category":899,"image":1185,"draft":800},"\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":1187,"title":1188,"description":1189,"published":1190,"category":899,"image":1191,"draft":800},"\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":1193,"title":1194,"description":1195,"published":1196,"category":796,"image":1197,"draft":800},"\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":457,"title":1199,"description":1200,"published":1201,"category":796,"image":1202,"draft":800},"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":1204,"title":1205,"description":1206,"published":1207,"category":796,"image":1208,"draft":800},"\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":1210,"title":1211,"description":1212,"published":1213,"category":796,"image":1214,"draft":800},"\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":1216,"title":1217,"description":1218,"published":1219,"category":796,"image":1220,"draft":800},"\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":1222,"title":1223,"description":1224,"published":1225,"category":796,"image":1226,"draft":800},"\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":1228,"title":1229,"description":1230,"published":1231,"category":796,"image":1232,"draft":800},"\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":1234,"title":1235,"description":1236,"published":1237,"category":796,"image":1238,"draft":800},"\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":1240,"title":1241,"description":1242,"published":1243,"category":796,"image":1244,"draft":800},"\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":1246,"title":1247,"description":1248,"published":1249,"category":796,"image":1250,"draft":800},"\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":1252,"title":1253,"description":1254,"published":1255,"category":899,"image":1256,"draft":800},"\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":1258,"title":1259,"description":1260,"published":1261,"category":796,"image":1262,"draft":800},"\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":1264,"title":1265,"description":1266,"published":1267,"category":899,"image":1268,"draft":800},"\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":1270,"title":1271,"description":1272,"published":1273,"category":796,"image":1274,"draft":800},"\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":1276,"title":1277,"description":1278,"published":1279,"category":796,"image":1280,"draft":800},"\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":1282,"title":1283,"description":1284,"published":1285,"category":796,"image":1286,"draft":800},"\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":1288,"title":1289,"description":1290,"published":1291,"category":796,"image":1292,"draft":800},"\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":1294,"title":1295,"description":1296,"published":1297,"category":899,"image":1298,"draft":800},"\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":1300,"title":1301,"description":1302,"published":1303,"category":899,"image":1304,"draft":800},"\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":1306,"title":1307,"description":1308,"published":1309,"category":796,"image":1310,"draft":800},"\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":1312,"title":1313,"description":1314,"published":1315,"category":796,"image":1316,"draft":800},"\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":1318,"title":1319,"description":1320,"published":1321,"category":899,"image":1322,"draft":800},"\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":1324,"title":1325,"description":1326,"published":1327,"category":796,"image":1328,"draft":800},"\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":1330,"title":1331,"description":1332,"published":1327,"category":796,"image":1333,"draft":800},"\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":1335,"title":1336,"description":1337,"published":1338,"category":796,"image":1339,"draft":800},"\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":1341,"title":1342,"description":1343,"published":1344,"category":899,"image":1345,"draft":800},"\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":1347,"title":1348,"description":1349,"published":1350,"category":796,"image":1351,"draft":800},"\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":1353,"title":1354,"description":1355,"published":1350,"category":899,"image":1356,"draft":800},"\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":1358,"title":1359,"description":1360,"published":1361,"category":899,"image":1362,"draft":800},"\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":648,"title":1364,"description":1365,"published":1361,"category":796,"image":1366,"draft":800},"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",1794213638689]