[{"data":1,"prerenderedAt":1111},["ShallowReactive",2],{"blog-pt-supabase-email-rate-limit-exceeded":3,"blog-index-pt":581},{"id":4,"title":5,"body":6,"category":536,"cover":537,"coverAlt":538,"description":539,"draft":540,"extension":541,"faq":542,"image":561,"keywords":562,"meta":570,"navigation":571,"ogTitle":5,"path":572,"published":573,"seo":574,"stem":575,"tldr":576,"updated":573,"__hash__":580},"blog_pt\u002Fblog\u002Fsupabase-email-rate-limit-exceeded.md","Supabase \"Email Rate Limit Exceeded\": dois limites, um só código",{"type":7,"value":8,"toc":523},"minimark",[9,18,28,31,43,48,51,54,73,91,110,116,124,128,131,188,200,207,212,216,219,234,237,241,249,252,258,265,287,291,294,318,321,346,353,357,364,370,373,384,389,393,396,402,412,416,419,429,447,456,476,480,517],[10,11,12,13,17],"p",{},"Você está testando o formulário de cadastro antes de divulgar o app. Você se\ncadastra com seu próprio endereço, depois com ",[14,15,16],"code",{},"voce+2@gmail.com",", e depois mais\numa vez para ver se o email de confirmação está bonito. Uma dessas tentativas\npara nisto:",[19,20,25],"pre",{"className":21,"code":23,"language":24},[22],"language-text","AuthApiError: email rate limit exceeded\n","text",[14,26,23],{"__ignoreMap":27},"",[10,29,30],{},"Supabase \"Email Rate Limit Exceeded\" significa que seu projeto gastou a cota de\nemails da hora, então o Supabase Auth, a parte do Supabase que faz o login das\npessoas, se recusou a enviar mais um. No serviço de email com que todo projeto\ncomeça, essa cota é de dois emails por hora para o projeto inteiro.",[10,32,33,34,38,39,42],{},"Esta é a parte fácil de entender ao contrário: ",[35,36,37],"strong",{},"o código de erro cobre dois\nlimites diferentes."," A própria lista de códigos de erro do Auth do Supabase\ndescreve ",[14,40,41],{},"over_email_send_rate_limit"," como \"Too many emails have been sent to this\nemail address.\" Isso vale para um dos dois. O mesmo código também volta quando o\nprojeto inteiro ficou sem cota, seja quem for o destinatário, então tentar outro\nendereço não muda nada. E o conselho de sempre, \"conecte seu próprio SMTP\", é\nmetade da solução, porque o Supabase começa um servidor de email recém-conectado\nem 30 emails por hora.",[44,45,47],"h2",{"id":46},"o-que-significa-email-rate-limit-exceeded-no-supabase","O que significa \"Email rate limit exceeded\" no Supabase?",[10,49,50],{},"Que seu projeto já enviou nesta hora todos os emails que o Supabase Auth\npermite, e o próximo foi recusado.",[10,52,53],{},"Pense na cota como uma folha de selos. O Supabase dá a cada projeto um número\nfixo de selos por hora, e cada email que o Supabase Auth envia gasta um, seja de\nque tipo for e seja para quem for:",[55,56,57,61,64,67,70],"ul",{},[58,59,60],"li",{},"o link de confirmação depois que alguém se cadastra",[58,62,63],{},"um magic link ou um código de uso único para entrar",[58,65,66],{},"uma redefinição de senha",[58,68,69],{},"um convite que você envia pela página Users",[58,71,72],{},"a confirmação quando alguém troca o endereço de email",[10,74,75,76,78,79,82,83,90],{},"Quando a folha acaba, o Supabase Auth responde com HTTP 429, que significa\n\"requisições demais\", o código ",[14,77,41],{}," e a mensagem ",[14,80,81],{},"email rate limit exceeded",". Essas palavras vêm\n",[84,85,89],"a",{"href":86,"rel":87},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Fmail.go",[88],"nofollow","do próprio código do servidor do Supabase Auth",".",[10,92,93,94,97,98,103,104,109],{},"No remetente embutido, o serviço de email com que um projeto novo começa, a folha\ntem ",[35,95,96],{},"dois selos por hora",". É o número da\n",[84,99,102],{"href":100,"rel":101},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Frate-limits",[88],"página de limites do Supabase","\nquando a lemos em 20 de outubro de 2026, e o\n",[84,105,108],{"href":106,"rel":107},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fauth-smtp",[88],"guia de SMTP do Supabase"," diz\nque ele \"can change without notice\". A dois por hora, um cadastro e uma\nredefinição de senha são a cota inteira da hora.",[111,112],"diagram",{"alt":113,"caption":114,"src":115},"Quatro tipos de email, para uma conta nova, um link de login, uma redefinição de senha e um convite, tiram todos da mesma folha, que tem dois selos por hora. Dois envelopes saem selados. Os outros dois ficam parados numa barreira, sem selo.","Cada email que o Supabase Auth envia gasta um selo da mesma folha. No remetente embutido, a folha tem dois por hora.","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fone-sheet-every-email-1600x760.png",[10,117,118,119,123],{},"Se ninguém consegue entrar, ou o app inteiro está em branco, o problema é outro,\ne ",[84,120,122],{"href":121},"\u002Fblog\u002Fis-supabase-down-or-your-app","o Supabase caiu ou é o seu app?"," é por\nonde começar.",[44,125,127],{"id":126},"dois-limites-dividem-um-código-de-erro","Dois limites dividem um código de erro",[10,129,130],{},"A mensagem diz qual limite você atingiu. O código é o mesmo para os dois:",[132,133,134,153],"table",{},[135,136,137],"thead",{},[138,139,140,144,147,150],"tr",{},[141,142,143],"th",{},"A mensagem",[141,145,146],{},"O que limita",[141,148,149],{},"O que conta",[141,151,152],{},"O padrão",[154,155,156,172],"tbody",{},[138,157,158,163,166,169],{},[159,160,161],"td",{},[14,162,81],{},[159,164,165],{},"O projeto inteiro",[159,167,168],{},"Cada email que o Supabase Auth envia, por hora",[159,170,171],{},"2 por hora no remetente embutido, 30 quando você conecta o seu",[138,173,174,179,182,185],{},[159,175,176],{},[14,177,178],{},"For security purposes, you can only request this after N seconds.",[159,180,181],{},"Um endereço",[159,183,184],{},"O mesmo tipo de email, enviado de novo ao mesmo endereço",[159,186,187],{},"Um a cada 60 segundos",[10,189,190,191,193,194,199],{},"Os dois respondem HTTP 429 com ",[14,192,41],{},". A\n",[84,195,198],{"href":196,"rel":197},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fdebugging\u002Ferror-codes",[88],"lista de códigos de erro do Auth","\ndo Supabase pede que você identifique os erros pelo código e \"not string matching\non error messages\". Isso está certo para o código do seu app, e aqui deixa uma\nlacuna: só a mensagem diz qual limite você atingiu. Então leia a mensagem para\nentender o que aconteceu, e deixe o seu app reagir ao código.",[10,201,202,203,206],{},"Se o seu app só diz \"algo deu errado\", a mensagem exata está na resposta à\nrequisição que falhou, na aba Rede das ferramentas de desenvolvedor do seu\nnavegador. Um código ",[14,204,205],{},"over_request_rate_limit"," é um terceiro limite, sobre\nrequisições vindas de um mesmo endereço IP, e a lista do Supabase diz que ele pode\napontar para um bug no seu app que envia requisições demais.",[111,208],{"alt":209,"caption":210,"src":211},"Dois painéis. No da esquerda, a folha de selos do projeto está vazia e três envelopes para três pessoas diferentes estão parados. No da direita, uma pessoa já recebeu um envelope, e um segundo para a mesma pessoa espera ao lado de um relógio marcando 60 segundos. Os dois painéis levam ao mesmo código de erro, over_email_send_rate_limit, com status 429.","Uma folha vazia e uma espera de 60 segundos são recusas diferentes, e o Supabase informa as duas com o mesmo código.","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Ftwo-refusals-one-code-1600x720.png",[44,213,215],{"id":214},"por-que-diz-you-can-only-request-this-after-0-seconds","Por que diz \"you can only request this after 0 seconds\"?",[10,217,218],{},"Porque faltava menos de um segundo de espera. O limite por endereço permite um\nemail de cada tipo para o mesmo endereço a cada 60 segundos: uma confirmação de\ncadastro, uma redefinição de senha, um magic link ou código. Peça de novo antes e\no Supabase Auth calcula quanto falta e coloca isso na mensagem.",[10,220,221,222,229,230,233],{},"Ele conta em segundos inteiros e descarta o resto. A função do servidor do Auth\nque escreve essa mensagem\n(",[84,223,226],{"href":224,"rel":225},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Ferrors.go",[88],[14,227,228],{},"errors.go",")\ndivide o tempo restante por um segundo, então 0,8 segundo aparece como ",[14,231,232],{},"0",". Tente\nde novo um instante depois e passa, desde que o teto por hora do projeto ainda\ntenha um selo.",[10,235,236],{},"Essa espera está fazendo o que deve. É ela que impede um botão de reenviar,\napertado vinte vezes, de mandar vinte emails. Deixe em 60 segundos e deixe o seu\nformulário explicá-la.",[44,238,240],{"id":239},"o-teto-por-hora-e-para-quem-ele-é","O teto por hora, e para quem ele é",[10,242,243,244,248],{},"O remetente embutido serve para experimentar o Supabase, e o Supabase diz isso no\nseu ",[84,245,247],{"href":106,"rel":246},[88],"guia de SMTP",". O guia lista\npara que o serviço é pensado: \"Exploring and getting started with Supabase\nAuth\", \"Setting up and testing email templates with the members of the project's\nteam\" e \"Building toy projects, demos or any non-mission-critical application\".\nEle também vem com \"No SLA guarantee on message delivery or uptime\".",[10,250,251],{},"O mesmo guia tem uma segunda regra, e é ela que decide quem vê cada erro.\nEnquanto você não conecta seu próprio servidor de email, o Supabase Auth \"will\nrefuse to deliver messages to addresses that are not part of the project's\nteam\". Um cliente que se cadastra com o próprio endereço é recusado antes de\nqualquer selo ser contado, com outra mensagem:",[19,253,256],{"className":254,"code":255,"language":24},[22],"Email address \"customer@example.com\" cannot be used as it is not authorized\n",[14,257,255],{"__ignoreMap":27},[10,259,260,261,264],{},"Isso é HTTP 400 com o código ",[14,262,263],{},"email_address_not_authorized",", e no código do\nservidor do Auth essa verificação vem antes dos dois limites. Se o cadastro\nfunciona quando você testa e falha para todo mundo, é por isso.",[10,266,267,268,270,271,274,275,278,279,282,283,286],{},"Então, no remetente embutido, ",[14,269,81],{}," cai principalmente em\nvocê e na sua equipe, testando. Quando o servidor do Auth verifica se um endereço\né da sua equipe, ele ignora tudo o que estiver entre um ",[14,272,273],{},"+"," e o ",[14,276,277],{},"@",". Assim\n",[14,280,281],{},"voce+teste1@gmail.com"," e ",[14,284,285],{},"voce+teste2@gmail.com"," contam os dois como você, e\ncada cadastro de teste gasta um dos mesmos dois selos.",[44,288,290],{"id":289},"como-aumento-o-limite-de-emails-do-supabase","Como aumento o limite de emails do Supabase?",[10,292,293],{},"Conecte seu próprio provedor de email e depois aumente o limite que o Supabase\ncoloca nele. São dois passos separados, e o segundo é o que as pessoas esquecem.",[295,296,297,306,312],"ol",{},[58,298,299,302,303,90],{},[35,300,301],{},"Escolha um serviço de envio e pegue os dados SMTP dele."," O guia do Supabase\ncita Resend, AWS SES, Postmark, Twilio SendGrid, ZeptoMail e Brevo, e diz que\nqualquer serviço que suporte SMTP funciona. Você precisa do host, da porta, de\num usuário e de uma senha, mais um endereço de remetente como\n",[14,304,305],{},"no-reply@seudominio.com.br",[58,307,308,311],{},[35,309,310],{},"Ative o SMTP personalizado"," nas configurações de Authentication do seu\nprojeto e preencha esses dados. A partir daí o Supabase envia para qualquer\nendereço.",[58,313,314,317],{},[35,315,316],{},"Aumente o limite de emails"," na página Rate Limits, também em\nAuthentication. O guia diz que um servidor recém-conectado recebe \"a low\nrate-limit of 30 messages per hour\" para proteger a reputação dele, e que é ali\nque você muda. Coloque o que o seu provedor permite e o que a sua hora mais\nmovimentada precisa.",[10,319,320],{},"Mais três coisas do mesmo guia combinam com essa mudança:",[55,322,323,329,335],{},[58,324,325,328],{},[35,326,327],{},"Configure DKIM, DMARC e SPF"," para o seu domínio de envio, no seu provedor.\nO Supabase diz que isso \"will significantly increase the deliverability of your\nmessages\".",[58,330,331,334],{},[35,332,333],{},"Ative CAPTCHA nos cadastros."," O guia aponta bots que cadastram listas de\nendereços como \"a common source of abuse\", e cada um desses cadastros é um\nemail tirado da sua hora. Ele chama o CAPTCHA de \"the most effective way\" de\nbarrá-los.",[58,336,337,340,341,345],{},[35,338,339],{},"Confira se os seus usuários não estão sendo desconectados."," Segundo o guia,\nsessões curtas forçam \"active users to sign in frequently, increasing the\nnumber of messages\", e se os seus usuários entram por link de email, cada\ndesconexão inesperada custa um selo.\n",[84,342,344],{"href":343},"\u002Fblog\u002Fsupabase-users-logged-out","Por que os usuários do Supabase são desconectados","\nexplica as causas.",[10,347,348,349,90],{},"Para os outros limites que um projeto gratuito encontra, veja\n",[84,350,352],{"href":351},"\u002Fblog\u002Fsupabase-free-plan-limits","o que o plano gratuito do Supabase inclui",[44,354,356],{"id":355},"tratando-o-erro-no-seu-formulário-de-cadastro","Tratando o erro no seu formulário de cadastro",[10,358,359,360,363],{},"Pegue o erro pelo código e diga à pessoa o que fazer, em palavras simples. O\ncliente JavaScript do Supabase coloca o código do servidor no erro que devolve,\ncomo ",[14,361,362],{},"error.code",", então a verificação é uma linha:",[19,365,368],{"className":366,"code":367,"language":24},[22],"const { error } = await supabase.auth.signUp({ email, password })\n\nif (error?.code === 'over_email_send_rate_limit') {\n  \u002F\u002F mostrar: \"Não conseguimos enviar seu email agora. Tente de novo em um minuto.\"\n}\n",[14,369,367],{"__ignoreMap":27},[10,371,372],{},"Peça à sua ferramenta, seja Lovable, Bolt, v0, Cursor, Claude Code ou Replit,\ntrês coisas:",[55,374,375,378,381],{},[58,376,377],{},"a mesma verificação em todo formulário que envia email: cadastro, \"esqueci a\nsenha\", login por link de email e \"reenviar\"",[58,379,380],{},"uma mensagem que peça à pessoa para tentar de novo daqui a pouco, no lugar do\nerro cru ou de um formulário que não faz nada sem avisar",[58,382,383],{},"o botão de reenviar desativado por 60 segundos depois de cada envio, para\nninguém conseguir apertá-lo dentro da espera por endereço",[10,385,386,387,90],{},"Não coloque novas tentativas automáticas. Enquanto a folha estiver vazia, cada\ntentativa é recusada, e as requisições de cadastro também são limitadas por\nendereço IP, a 30 a cada 5 minutos por padrão. Um loop de tentativas pode\ndisparar esse limite também, e ele responde com ",[14,388,205],{},[44,390,392],{"id":391},"o-que-não-mudar-enquanto-os-cadastros-estão-travados","O que não mudar enquanto os cadastros estão travados",[10,394,395],{},"A confirmação por email, e de onde os emails saem. Dois atalhos fazem o erro\nsumir e deixam você numa situação pior.",[10,397,398,401],{},[35,399,400],{},"Deixe a confirmação por email ligada."," Desligar \"Confirm email\" faz os\ncadastros pararem de enviar qualquer coisa, então o erro some. O guia de SMTP do\nSupabase lista \"Do not disable email confirmations under pressure\" entre as suas\ndefesas, porque sem confirmação alguém pode criar uma conta no nome de outra\npessoa.",[10,403,404,407,408,90],{},[35,405,406],{},"Mantenha os emails fora do navegador."," Peça a um assistente para \"só mandar a\nconfirmação com o Resend\" e ele pode colocar a chave de API do provedor no código\nfrontend do seu app, onde qualquer visitante consegue ler e mandar emails em seu\nnome. Envie os emails pelas configurações SMTP do Supabase ou por uma função no\nservidor, nunca com uma chave na página. Se você não tem certeza de que nenhuma\nescapou, nosso scan gratuito lê o código que o seu app no ar envia para cada\nvisitante e aponta as chaves secretas que encontra ali. Leva uns 20 segundos e\nnão pede conta: ",[84,409,411],{"href":410},"\u002Fsecurity-scanner","escaneie seu app",[44,413,415],{"id":414},"de-olho-no-app-enquanto-você-muda-o-envio-de-emails","De olho no app enquanto você muda o envio de emails",[10,417,418],{},"Duas coisas podem dar errado enquanto você refaz o envio de emails: uma chave vai\nparar no código do seu app, e uma mensagem dizendo \"ninguém consegue se\ncadastrar\" manda você atrás de uma queda.",[10,420,421],{},[35,422,423,424,428],{},"O ",[84,425,427],{"href":426},"\u002Fwebsite-monitoring","Reeve Monitor"," continua verificando de fora:",[55,430,431,434,437,444],{},[58,432,433],{},"se o seu app está no ar, verificado a cada minuto, para você saber na hora se uma reclamação sobre o cadastro é uma queda ou algo mais restrito",[58,435,436],{},"a verificação de segurança completa a cada hora, em até três apps, incluindo chaves secretas no código que o seu app envia aos visitantes",[58,438,439,440,443],{},"uma mensagem quando um resultado ",[35,441,442],{},"muda",", para que uma chave que sai num deploy posterior chegue até você sem você precisar ir olhar",[58,445,446],{},"um relatório mensal, em linguagem clara, do que ele viu",[10,448,449],{},[35,450,423,451,455],{},[84,452,454],{"href":453},"\u002Fsupabase-backups","Reeve Care"," guarda uma cópia do seu banco de dados Supabase:",[55,457,458,461,464,467,470,473],{},[58,459,460],{},"uma cópia criptografada num cronograma, no armazenamento próprio da Reeve na UE, fora da sua conta do Supabase",[58,462,463],{},"o schema auth, onde fica cada conta que conseguiu se cadastrar",[58,465,466],{},"cada cópia verificada antes de contar, contando as linhas de cada tabela",[58,468,469],{},"os seus arquivos enviados também, assim que você conecta uma credencial do Storage",[58,471,472],{},"uma restauração com um clique, com uma cópia de segurança do estado atual feita antes",[58,474,475],{},"tudo o que o Monitor faz",[44,477,479],{"id":478},"o-que-fazer-agora","O que fazer agora",[481,482,483],"key-takeaways",{},[55,484,485,495,502,505,508,514],{},[58,486,487,488,490,491,494],{},"Leia a mensagem além do código: ",[14,489,81],{}," é o teto por hora do projeto, e ",[14,492,493],{},"For security purposes…"," é a espera de 60 segundos para um endereço.",[58,496,497,498,501],{},"Se clientes veem ",[14,499,500],{},"Email address … cannot be used as it is not authorized",", seu projeto ainda está no remetente embutido do Supabase, que só escreve para a sua equipe.",[58,503,504],{},"Conecte seu próprio provedor SMTP e depois aumente o limite de emails na página Rate Limits, que começa em 30 por hora.",[58,506,507],{},"Configure DKIM, DMARC e SPF no seu provedor, e ative CAPTCHA nos cadastros.",[58,509,510,511,513],{},"Faça todo formulário que envia email checar ",[14,512,41],{},", mostrar uma mensagem clara e travar o botão de reenviar por 60 segundos.",[58,515,516],{},"Deixe a confirmação por email ligada, e nunca coloque a chave de um provedor de email no seu frontend.",[10,518,519,520,522],{},"Comece pela mensagem na resposta que falhou, porque ela diz qual dos dois limites\nvocê atingiu. Depois, quando os emails já estiverem saindo pelo seu próprio\nprovedor, ",[84,521,411],{"href":410}," para conferir que nenhuma chave\nveio junto.",{"title":27,"searchDepth":524,"depth":524,"links":525},3,[526,528,529,530,531,532,533,534,535],{"id":46,"depth":527,"text":47},2,{"id":126,"depth":527,"text":127},{"id":214,"depth":527,"text":215},{"id":239,"depth":527,"text":240},{"id":289,"depth":527,"text":290},{"id":355,"depth":527,"text":356},{"id":391,"depth":527,"text":392},{"id":414,"depth":527,"text":415},{"id":478,"depth":527,"text":479},"Noções de segurança","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcover-1200x630.png","Uma folha de selos da qual todos os selos já foram arrancados, ao lado de uma pilha de envelopes fechados sem nada no canto.","Supabase \"Email Rate Limit Exceeded\" limita cada email que seu projeto envia: 2 por hora no remetente embutido. O que conta e como aumentar.",false,"md",[543,546,549,552,555,558],{"q":544,"a":545},"O que significa \"email rate limit exceeded\" no Supabase?","Que seu projeto já enviou nesta hora todos os emails que o Supabase Auth permite, então o próximo foi recusado. A conta inclui cada email que o Auth envia, para quem quer que seja: confirmações de cadastro, magic links, redefinições de senha e convites. No remetente embutido são 2 por hora. Com seu próprio provedor SMTP, quem define o número é você.",{"q":547,"a":548},"Por que diz que só posso pedir de novo depois de 0 segundos?","Porque faltava menos de um segundo da espera de 60. O Supabase Auth conta o tempo restante em segundos inteiros e descarta o resto, então o último segundo aparece como 0. Tente de novo um instante depois e o email sai, desde que o teto por hora ainda tenha espaço.",{"q":550,"a":551},"Quantos emails o Supabase pode enviar por mim?","No remetente embutido, 2 por hora para o projeto inteiro, e só para pessoas da sua equipe no Supabase. O Supabase diz que esse número pode mudar sem aviso. Com seu próprio provedor SMTP não há número fixo: o Supabase começa em 30 por hora e você aumenta na página Rate Limits.",{"q":553,"a":554},"Preciso do meu próprio provedor SMTP?","Sim, assim que alguém de fora da sua equipe se cadastrar por email. O remetente embutido recusa endereços que não estão na sua equipe, e o Supabase o descreve como feito para experimentar, testar templates e fazer demos. Resend, AWS SES, Postmark, SendGrid, ZeptoMail e Brevo estão entre os serviços que o Supabase cita como compatíveis.",{"q":556,"a":557},"Como evito que isso quebre meu formulário de cadastro?","Confira o código do erro antes que qualquer coisa chegue à tela. Se for over_email_send_rate_limit, mostre uma mensagem clara pedindo para tentar de novo em um minuto, e mantenha o botão de reenviar desativado por 60 segundos depois de cada envio, para ninguém conseguir apertá-lo dentro da espera.",{"q":559,"a":560},"Por que meus clientes recebem \"Email address not authorized\"?","Porque seu projeto ainda envia pelo remetente embutido do Supabase, que só entrega para membros da sua organização no Supabase. Todos os outros são recusados com o código email_address_not_authorized. Conectar seu próprio provedor SMTP resolve, e é a mesma mudança que tira o teto por hora.","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",[563,564,41,565,566,567,568,569],"email rate limit exceeded supabase","supabase email rate limit exceeded","for security purposes you can only request this after","supabase limite smtp","supabase email de confirmação não chega","supabase magic link não chega","email address not authorized supabase",{},true,"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","2026-10-20",{"title":5,"description":539},"blog\u002Fsupabase-email-rate-limit-exceeded",[577,578,579],"Supabase \"Email Rate Limit Exceeded\" significa que seu projeto já enviou nesta hora todos os emails a que tem direito. No remetente embutido são 2 por hora, e conta cada confirmação de cadastro, cada magic link e cada redefinição de senha.","O mesmo código, over_email_send_rate_limit, também volta como \"For security purposes, you can only request this after N seconds\", uma espera de 60 segundos para um único endereço. Só a mensagem diferencia os dois.","Seu próprio provedor SMTP tira o teto por hora quando você também aumenta o limite na página Rate Limits, que começa em 30 por hora. A espera de 60 segundos continua, e o seu formulário deve explicá-la.","-GHjF8Uv63InSAL5Eo-zViyEDZuLMnRTUIK55Evq7rk",[582,588,594,600,606,612,618,624,630,636,642,649,655,661,667,673,679,685,691,697,703,704,709,715,721,727,733,739,745,751,757,763,769,775,781,787,793,799,805,811,816,822,827,833,839,845,850,856,862,868,874,880,886,892,898,904,910,916,922,928,934,940,946,952,958,964,970,976,982,988,994,1000,1006,1012,1018,1024,1030,1036,1042,1048,1054,1060,1066,1072,1077,1083,1089,1095,1100,1106],{"path":583,"title":584,"description":585,"published":586,"category":536,"image":587,"draft":540},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\", explicado","Supabase \"max client connections reached\": o pooler não tem lugar para mais um cliente. A porta da sua string de conexão define o limite.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":589,"title":590,"description":591,"published":592,"category":536,"image":593,"draft":540},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Erro do Supabase: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\": o Google está desativado no seu projeto Supabase. Como ativar e corrigir o redirect_uri_mismatch.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":595,"title":596,"description":597,"published":598,"category":536,"image":599,"draft":540},"\u002Fblog\u002Fviolates-foreign-key-constraint","Erro do Supabase \"violates foreign key constraint\" ao inserir","Supabase \"insert or update on table violates foreign key constraint\": sua linha aponta para uma linha que não existe. Qual, por quê, e como corrigir.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":601,"title":602,"description":603,"published":604,"category":536,"image":605,"draft":540},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Erro do Supabase \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": uma coluna obrigatória chegou vazia. De onde veio o null, e como corrigir.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":607,"title":608,"description":609,"published":610,"category":536,"image":611,"draft":540},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": para onde foi a sessão","\"Auth session missing!\" é o supabase-js sem achar nenhuma sessão logada e sem chegar a perguntar ao Supabase. Para onde foi a sessão, e a correção.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":613,"title":614,"description":615,"published":616,"category":536,"image":617,"draft":540},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": ninguém está logado","\"invalid claim: missing sub claim\": o Supabase Auth recebeu um token autêntico sem nenhum usuário, a chave do projeto no lugar de uma sessão.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":619,"title":620,"description":621,"published":622,"category":536,"image":623,"draft":540},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": a causa real","\"Failed to send a request to the Edge Function\": o navegador não recebeu uma resposta legível. O console dele diz por quê e se a sua função rodou.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":625,"title":626,"description":627,"published":628,"category":536,"image":629,"draft":540},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Por que o Supabase redireciona links de e-mail para localhost:3000","Se o Supabase redireciona para localhost:3000, a Site URL nunca foi trocada ou o seu endereço falta em Redirect URLs. A solução, e o curinga a evitar.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":631,"title":632,"description":633,"published":634,"category":536,"image":635,"draft":540},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" num link novo","Num link enviado há um minuto, \"Email link is invalid or has expired\" no Supabase costuma significar que um filtro de e-mail o usou antes. Como resolver.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":637,"title":638,"description":639,"published":640,"category":536,"image":641,"draft":540},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\", explicado","Supabase \"canceling statement due to statement timeout\": uma consulta passou do limite do seu papel, 3 segundos para um visitante. Veja antes a política RLS.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":643,"title":644,"description":645,"published":646,"category":647,"image":648,"draft":540},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" no Supabase, e o que vai junto","\"Database error deleting user\" no Supabase: seu banco recusou a exclusão. O motivo está nos seus logs, e a correção decide o que mais é apagado.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":650,"title":651,"description":652,"published":653,"category":536,"image":654,"draft":540},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" no Supabase","O webhook do Stripe numa Edge Function do Supabase diz \"No signatures found matching the expected signature\"? São duas causas. Continue verificando.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":656,"title":657,"description":658,"published":659,"category":536,"image":660,"draft":540},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" no Supabase: as três causas","O Supabase diz \"Invalid login credentials\" para senha errada, e-mail desconhecido e conta Google. Como saber qual é, e por que é vago.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":662,"title":663,"description":664,"published":665,"category":536,"image":666,"draft":540},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": o erro real","\"Edge Function returned a non-2xx status code\" quer dizer que sua função do Supabase respondeu com um erro. Veja onde ler o erro real.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":668,"title":669,"description":670,"published":671,"category":536,"image":672,"draft":540},"\u002Fblog\u002Fcertificate-not-trusted","Certificado não confiável: três causas além do vencimento","Certificado não confiável mesmo com a data certa? Ele cita outro endereço, assinou a si mesmo ou falta um elo na cadeia. Veja como saber qual.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":674,"title":675,"description":676,"published":677,"category":536,"image":678,"draft":540},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": leia as aspas","Supabase \"invalid input syntax for type uuid\": seu app enviou algo que não é um id. Leia as aspas, segure a consulta, mantenha a coluna.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":680,"title":681,"description":682,"published":683,"category":536,"image":684,"draft":540},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\", explicado","Supabase \"duplicate key value violates unique constraint\": o valor já está em uso. Ache a coluna, escolha uma correção e tire o valor da tela.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":686,"title":687,"description":688,"published":689,"category":536,"image":690,"draft":540},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\" e a tabela está lá","Supabase \"relation does not exist\" ou PGRST205: nenhuma tabela tem esse nome nesse schema. Quatro verificações, e o que expor um schema abre.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":692,"title":693,"description":694,"published":695,"category":536,"image":696,"draft":540},"\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\" mostra os nomes de argumentos que seu app enviou. Compare-os com a função.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":698,"title":699,"description":700,"published":701,"category":536,"image":702,"draft":540},"\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\" costuma ser um nome que não bate. Quatro verificações e a linha que recarrega.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":572,"title":5,"description":539,"published":573,"category":536,"image":561,"draft":540},{"path":343,"title":705,"description":706,"published":707,"category":536,"image":708,"draft":540},"Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 causas","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" desconecta seus usuários. Três causas, e como o log do Auth separa cada uma.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":710,"title":711,"description":712,"published":713,"category":536,"image":714,"draft":540},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": três causas","Supabase \"permission denied for schema public\" é um grant que falta no schema. O que o removeu, e a linha que o devolve.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":716,"title":717,"description":718,"published":719,"category":536,"image":720,"draft":540},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": as três coisas que isso significa","Supabase \"Bucket not found\" é uma de três coisas: um link público para um bucket privado, um nome que não bate exatamente ou o projeto errado.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":722,"title":723,"description":724,"published":725,"category":536,"image":726,"draft":540},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: qual chave parou de funcionar?","Um erro Supabase invalid JWT é o PGRST301: um token assinado não passou na verificação. Num projeto novo isso é a sessão, não a chave de API.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":728,"title":729,"description":730,"published":731,"category":536,"image":732,"draft":540},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" quase sempre é nenhuma","O Supabase devolve PGRST116, \"JSON object requested, multiple (or no) rows returned\", quando a consulta não achou nada. Linha escondida parece ausente.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":734,"title":735,"description":736,"published":737,"category":536,"image":738,"draft":540},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" no Supabase: onde olhar","\"Database error saving new user\" quer dizer que algo preso ao seu cadastro no Supabase falhou e tudo foi desfeito. O erro real está nos seus logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":740,"title":741,"description":742,"published":743,"category":536,"image":744,"draft":540},"\u002Fblog\u002Fwhat-is-supabase","O que é Supabase? O banco de dados que seu builder escolheu","O que é Supabase: o banco de dados, o login e o armazenamento de arquivos do seu app. O Supabase cuida dos servidores; as regras das suas linhas são suas.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":746,"title":747,"description":748,"published":749,"category":536,"image":750,"draft":540},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Uma chave AWS exposta no seu frontend não é como uma chave OpenAI","Uma chave de acesso da AWS exposta no seu frontend lê e grava no seu armazenamento. A solução costuma ser uma presigned URL, não uma chave nova.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":752,"title":753,"description":754,"published":755,"category":536,"image":756,"draft":540},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" ao enviar","\"New row violates row-level security policy for table objects\" quer dizer que o seu envio não tem regra insert. Deixar o bucket público não cria nenhuma.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":758,"title":759,"description":760,"published":761,"category":536,"image":762,"draft":540},"\u002Fblog\u002Fbase44-security-scan","Scan de segurança do Base44: o que só ele enxerga","O scan de segurança do Base44 verifica sete tipos de problema por dentro. Esta é a metade que ele lê e mais ninguém, e a metade que ele nunca olha.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":764,"title":765,"description":766,"published":767,"category":536,"image":768,"draft":540},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Sua chave de API vazou. A ordem em que agir","Uma chave de API vazou e você não sabe o que fazer primeiro. Nem toda chave no seu frontend é um vazamento, e a ordem importa mais que a pressa.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":770,"title":771,"description":772,"published":773,"category":536,"image":774,"draft":540},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" sem desligar o RLS","\"Infinite recursion detected in policy for relation\" significa que a sua policy perguntou à tabela que ela protege. Veja como quebrar o círculo.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":776,"title":777,"description":778,"published":779,"category":536,"image":780,"draft":540},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" no Supabase, e a correção errada","\"No API key found in request\" significa que sua requisição chegou ao Supabase sem chave. Quase toda resposta aponta para as regras do seu banco.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":782,"title":783,"description":784,"published":785,"category":536,"image":786,"draft":540},"\u002Fblog\u002Fis-base44-safe","O Base44 é seguro? O que vimos em 5.442 apps Base44","O Base44 é seguro? Rodamos nove verificações em 5.442 apps Base44 no ar. Quase todas tiraram B por motivos que o dono nunca escolheu.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":788,"title":789,"description":790,"published":791,"category":536,"image":792,"draft":540},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Esconder uma chave de API: mova para uma Edge Function do Supabase","Esconder uma chave de API é tirá-la do navegador, e uma Edge Function do Supabase é o menor lugar para guardá-la. Dois passos em volta pesam mais.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":794,"title":795,"description":796,"published":797,"category":536,"image":798,"draft":540},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Seu arquivo .env está exposto? Os doze caminhos para testar","Seu arquivo .env está exposto no seu próprio servidor web? Doze endereços dizem isso em um minuto, e um acerto significa que tudo nele já é público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":800,"title":801,"description":802,"published":803,"category":536,"image":804,"draft":540},"\u002Fblog\u002Fis-v0-safe","Segurança do v0: os 1.790 aplicativos v0 escaneados tiraram A","A segurança do v0 medida em 1.790 aplicativos v0 no ar: todos tiraram A. Só 17 citavam um banco de dados, e é sobretudo isso que esse A mede.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":806,"title":807,"description":808,"published":809,"category":536,"image":810,"draft":540},"\u002Fblog\u002Fis-bolt-safe","O Bolt é seguro? O que vimos em 1.123 aplicativos Bolt","O Bolt é seguro? Passamos 1.123 aplicativos Bolt no ar por nove verificações. A hospedagem saiu limpa. Os achados: chaves e tabelas abertas nos aplicativos.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":121,"title":812,"description":813,"published":814,"category":536,"image":815,"draft":540},"O Supabase caiu ou o problema é o seu app? Como saber","O Supabase caiu ou o problema é o seu app? Um projeto pausado, um banco cheio e um erro seu parecem iguais. Quatro verificações separam os casos.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":817,"title":818,"description":819,"published":820,"category":536,"image":821,"draft":540},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","O Supabase criptografa meus dados? Sim. Veja o que isso impede","O Supabase criptografa os dados? Sim: AES-256 em repouso, TLS em trânsito, SOC 2 e ISO 27001. O que cada um cobre, e o vazamento que nenhum deles impede.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":351,"title":823,"description":824,"published":825,"category":536,"image":826,"draft":540},"O Supabase é gratuito? Sim, com estes limites e sem backups","Sim: o plano gratuito do Supabase vai até 500 MB de banco e 5 GB de egress, sem nenhum backup. O que para em cada limite e o que muda no Pro de $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":828,"title":829,"description":830,"published":831,"category":647,"image":832,"draft":540},"\u002Fblog\u002Ftest-your-supabase-backup","Teste o backup do seu Supabase antes do dia em que precisar","Como testar o backup do seu Supabase: restaurar num projeto de teste, contar as linhas, entrar e procurar a linha que falta num arquivo cortado.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":834,"title":835,"description":836,"published":837,"category":647,"image":838,"draft":540},"\u002Fblog\u002Fsupabase-backup-github-action","Backup grátis do Supabase com uma GitHub Action, e a pegadinha","Um backup do Supabase com GitHub Action é grátis e serve para muitos apps. O workflow, a connection string certa e o egress de cada execução.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":840,"title":841,"description":842,"published":843,"category":647,"image":844,"draft":540},"\u002Fblog\u002Fdownload-your-supabase-backup","Por que você não consegue baixar seu backup do Supabase","Você não consegue baixar seu backup do Supabase num projeto atual, porque a cópia diária é um snapshot físico. Como conferir e como ter uma cópia só sua.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":846,"title":847,"description":848,"published":843,"category":536,"image":849,"draft":540},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": o grant que falta","A partir de 30 de outubro, uma tabela nova no Supabase responde \"permission denied for table\" até receber um grant. O e-mail mostra só metade.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":851,"title":852,"description":853,"published":854,"category":536,"image":855,"draft":540},"\u002Fblog\u002Fopen-api-endpoint-exposed","Um endpoint de API aberto é um problema? Leia o JSON","Seu scan apontou um endpoint de API aberto. Se isso importa depende do que voltou, e a maioria dos que encontramos era da própria plataforma.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":857,"title":858,"description":859,"published":860,"category":536,"image":861,"draft":540},"\u002Fblog\u002Flovable-security-scan","Escaneamento de segurança do Lovable: o que ele não prova","Escaneamento de segurança do Lovable: o que o Quick scan e o Deep scan checam, quando cada um roda, e a única coisa que nenhum escaneamento por dentro prova.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":863,"title":864,"description":865,"published":866,"category":647,"image":867,"draft":540},"\u002Fblog\u002Fsupabase-backup-auth-users","Por que seu dump do Supabase não tem usuários dentro","Rode supabase db dump sozinho e você recebe a forma do seu banco e nenhuma das linhas dele, sem o schema auth onde seus usuários moram.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":869,"title":870,"description":871,"published":872,"category":536,"image":873,"draft":540},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domínio expirado, site fora do ar: o que acontece agora","Seu domínio expirou e seu site está fora do ar. O relógio que começa a correr, por que o certificado é o problema menor, e como conferir os dois.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":875,"title":876,"description":877,"published":878,"category":536,"image":879,"draft":540},"\u002Fblog\u002Fis-lovable-safe","O Lovable é seguro? O que vimos em 18.554 aplicativos Lovable","O Lovable é seguro? Passamos 18.554 aplicativos Lovable no ar por nove verificações. A plataforma foi a mais limpa de cinco. Os achados estavam nos aplicativos.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":881,"title":882,"description":883,"published":884,"category":536,"image":885,"draft":540},"\u002Fblog\u002Fvibe-coded-app-security-checklist","O checklist de segurança do vibe coding, em nove verificações","Um checklist de segurança do vibe coding com nove itens, cada um verificável no seu app de fora por qualquer pessoa, e cada um com um teste de uma linha.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":887,"title":888,"description":889,"published":890,"category":536,"image":891,"draft":540},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Uma chave secreta da Stripe no frontend pode mover dinheiro","Uma chave secreta da Stripe exposta no seu frontend pode reembolsar, cobrar e ler cada ficha de cliente que você tem. Sua chave pk_live_ é que deve estar aí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":893,"title":894,"description":895,"published":896,"category":536,"image":897,"draft":540},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variáveis de ambiente do Vite expostas: o prefixo diz publique isto","Variáveis de ambiente do Vite expostas no seu app: fizeram o que o prefixo pediu. VITE_ e NEXT_PUBLIC_ significam publique isto, e a IA nunca soube o custo.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":899,"title":900,"description":901,"published":902,"category":536,"image":903,"draft":540},"\u002Fblog\u002Fbase44-source-maps","Segurança no Base44: o que um scan aponta e o que é seu para corrigir","Segurança no Base44 em 5.438 apps escaneados: três achados em quase todos são da plataforma, o source map é o selo do Base44, e a sua parte é uma lista curta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":905,"title":906,"description":907,"published":908,"category":536,"image":909,"draft":540},"\u002Fblog\u002Fis-cursor-ai-safe","O Cursor AI é seguro? O editor, o código e o app que você publicou","O Cursor AI é seguro? Três perguntas em uma busca: o que o Cursor guarda, o que o código que ele escreve erra, e se o app que você publicou está aberto.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":911,"title":912,"description":913,"published":914,"category":536,"image":915,"draft":540},"\u002Fblog\u002Fis-replit-safe","O Replit é seguro? O que vimos em 3.042 aplicativos Replit no ar","O Replit é seguro? Passamos 3.042 aplicativos Replit no ar por nove verificações externas. Os achados estavam no aplicativo publicado, não no host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":917,"title":918,"description":919,"published":920,"category":647,"image":921,"draft":540},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: sua cópia do banco não tem nenhum arquivo","Um Supabase storage backup é uma tarefa à parte. Os backups do banco guardam a lista dos seus arquivos e nenhum deles, então cada upload fica quebrado.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":923,"title":924,"description":925,"published":926,"category":647,"image":927,"draft":540},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery do Supabase: preço e limites","O point-in-time recovery do Supabase rebobina seu banco para qualquer segundo da última semana. Custa $100 por mês além do Pro e cobre só o banco.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":929,"title":930,"description":931,"published":932,"category":647,"image":933,"draft":540},"\u002Fblog\u002Fsupabase-project-paused-recover","Projeto Supabase pausado? Seus dados continuam lá","O Supabase pausou seu projeto depois de uma semana sem atividade. Nada foi apagado, Restaurar fica ao lado do nome e você tem um ano antes disso mudar.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":935,"title":936,"description":937,"published":938,"category":536,"image":939,"draft":540},"\u002Fblog\u002Fsafest-ai-app-builder","Qual builder de apps com IA é mais seguro? 30.998 apps testados","Qual builder de apps com IA é mais seguro? Escaneamos 30.998 apps no ar do Lovable, Base44, Replit, v0 e Bolt. O builder não é o que decide sua nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":941,"title":942,"description":943,"published":944,"category":536,"image":945,"draft":540},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Ative Row Level Security em toda tabela do Supabase e comprove","Ativar Row Level Security no Supabase sem política fecha a tabela por completo. Uma política sem a chave ligada não faz nada. Aqui está o SQL, e o teste.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":947,"title":948,"description":949,"published":950,"category":536,"image":951,"draft":540},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": o que o aviso não vê","O Supabase marca \"RLS disabled in public\" como erro. Ele não diz nada sobre a política de leitura que deixa a sua tabela igualmente aberta.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":953,"title":954,"description":955,"published":956,"category":536,"image":957,"draft":540},"\u002Fblog\u002Frotate-supabase-service-role-key","Como rotacionar uma chave service_role do Supabase vazada","O Supabase manda fechar o vazamento primeiro. Outros guias mandam rotacionar agora. O que vale depende de para onde a sua chave service_role vazou.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":959,"title":960,"description":961,"published":962,"category":536,"image":963,"draft":540},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de segurança para vibe coding comparados, o nosso incluído","O melhor scanner de segurança para vibe coding depende de três perguntas que nenhuma lista de recursos responde. Oito ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":965,"title":966,"description":967,"published":968,"category":536,"image":969,"draft":540},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: faça você mesmo as cinco verificações","Um Supabase security checker lê o seu app publicado em vez das configurações do projeto. Aqui estão as cinco verificações e como fazer cada uma sozinho.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":971,"title":972,"description":973,"published":974,"category":536,"image":975,"draft":540},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de segurança para vibe coding: o que ele não vê","Um scanner de segurança para vibe coding lê seu app no ar, de fora. O que isso cobre, as quatro coisas que ele não consegue ver e como ler o resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":977,"title":978,"description":979,"published":980,"category":536,"image":981,"draft":540},"\u002Fblog\u002Fmissing-security-headers","Cabeçalhos de segurança faltando: quando isso importa","Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":983,"title":984,"description":985,"published":986,"category":536,"image":987,"draft":540},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Sua chave de API da OpenAI está exposta no frontend. Troque-a.","Uma chave de API da OpenAI exposta no frontend não pode ser presa a um domínio. Troque-a hoje, mova a chamada para o seu servidor e limite o gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":989,"title":990,"description":991,"published":992,"category":536,"image":993,"draft":540},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chave de API exposta no frontend: o que 30.998 apps entregam","Uma chave de API exposta no seu frontend costuma ser uma chave do Google Maps. Escaneamos 30.998 apps vibe-coded e contamos quais segredos vazam de verdade.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":995,"title":996,"description":997,"published":998,"category":647,"image":999,"draft":540},"\u002Fblog\u002Fsupabase-backup-tools-compared","Ferramentas de backup do Supabase comparadas, a nossa incluída","Quatro tipos de ferramenta de backup do Supabase, o que cada uma copia de verdade e quando uma GitHub Action gratuita ganha de pagar, nós inclusive.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1001,"title":1002,"description":1003,"published":1004,"category":536,"image":1005,"draft":540},"\u002Fblog\u002Freplit-secrets-explained","Como usar secrets no Replit, e o que ainda assim é publicado","Como usar secrets no Replit: adicionar um, ler de volta e resolver as duas causas do undefined. E as chaves que a ferramenta Secrets não consegue proteger.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1007,"title":1008,"description":1009,"published":1010,"category":647,"image":1011,"draft":540},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups do plano gratuito do Supabase: como fazer sem terminal","No plano gratuito do Supabase não existe backup nenhum: a cópia é você que faz. Como fazer uma pelo painel e o que a rota do CSV deixa para trás.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1013,"title":1014,"description":1015,"published":1016,"category":536,"image":1017,"draft":540},"\u002Fblog\u002Fis-supabase-secure","O Supabase é seguro? É. Seu projeto é outra pergunta","O Supabase é seguro? A plataforma é auditada, criptografada e passa por pentests. A documentação deles diz onde isso termina e começam suas configurações.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1019,"title":1020,"description":1021,"published":1022,"category":536,"image":1023,"draft":540},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Onde ficam as chaves de API do Supabase: anon, service_role e URL","A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1025,"title":1026,"description":1027,"published":1028,"category":536,"image":1029,"draft":540},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1031,"title":1032,"description":1033,"published":1034,"category":536,"image":1035,"draft":540},"\u002Fblog\u002Fcors-wildcard-security-risk","Um curinga CORS é um risco de segurança? Quase nunca.","Um curinga CORS é um risco de segurança? Em geral é o padrão do seu builder e não entrega nada que o seu servidor já não desse a qualquer um que pedisse.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1037,"title":1038,"description":1039,"published":1040,"category":647,"image":1041,"draft":540},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching do Supabase não é backup. Ele só anda para a frente.","Por que o branching do Supabase não é backup: um branch começa sem os seus dados e um merge só leva o esquema. Para que ele serve e o que usar no lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":1043,"title":1044,"description":1045,"published":1046,"category":647,"image":1047,"draft":540},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Como restaurar um backup do Supabase, e o que quebra depois","Como restaurar um backup do Supabase pelo painel ou por um arquivo de dump, o que a restauração substitui e por que o seu app pode continuar quebrado no fim.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1049,"title":1050,"description":1051,"published":1052,"category":536,"image":1053,"draft":540},"\u002Fblog\u002Fsupabase-storage-bucket-public","Seu bucket do Supabase Storage é público. Isso é um problema?","Um bucket público do Supabase Storage significa que quem tem a URL de um arquivo pode abri-lo. Não significa que alguém possa listar o que está lá dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1055,"title":1056,"description":1057,"published":1058,"category":536,"image":1059,"draft":540},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Uma chave de API do Google no frontend é um problema?","Uma chave de API do Google exposta no seu frontend é a chave que nosso scanner mais encontra, e quase sempre está tudo bem. Um ajuste gratuito decide isso.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1061,"title":1062,"description":1063,"published":1064,"category":647,"image":1065,"draft":540},"\u002Fblog\u002Fai-agent-deleted-my-database","Um agente de IA apagou meus dados do Supabase. O que eu recupero?","Um agente de IA apagou dados do seu banco. O que você recupera já estava decidido antes de ele rodar, e os próximos minutos decidem o resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1067,"title":1068,"description":1069,"published":1070,"category":536,"image":1071,"draft":540},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Qualquer um consegue ler seu banco Supabase? Testamos 3.680 apps","Qualquer um consegue ler seu banco de dados Supabase sem fazer login? Escaneamos 30.998 apps no ar criadas com builders de IA e medimos quantas dizem que sim.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1073,"title":1074,"description":1075,"published":1070,"category":536,"image":1076,"draft":540},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expostos: seu app está publicando o código original","Um source map exposto deixa qualquer um ler o código original do seu app, comentários incluídos. A verificação de 30 segundos e o que importa de verdade.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1078,"title":1079,"description":1080,"published":1081,"category":536,"image":1082,"draft":540},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: é a mesma coisa que a anon key?","O Supabase trocou anon e service_role por chaves publicáveis e secretas. Qual delas pertence ao seu app e qual nunca deve estar lá?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1084,"title":1085,"description":1086,"published":1087,"category":647,"image":1088,"draft":540},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","O Supabase faz backup do meu banco de dados? Depende do plano.","O Supabase faz backup do seu banco de dados? Todo dia nos planos pagos, e nada no gratuito. Como descobrir o que você tem e o que essa cópia não cobre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1090,"title":1091,"description":1092,"published":1093,"category":536,"image":1094,"draft":540},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","O Supabase Row Level Security está ligado. A tabela continua pública.","Ligar o Supabase Row Level Security não protege uma tabela. Quem protege são as políticas, e a que consertou o seu app pode deixar qualquer um entrar.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1096,"title":1097,"description":1098,"published":1093,"category":647,"image":1099,"draft":540},"\u002Fblog\u002Fversion-history-is-not-a-backup","O histórico de versões não é backup. Ele não desfaz um delete.","Lovable e Bolt guardam um histórico de versões do seu código. Seu banco de dados é um serviço à parte, e voltar atrás não traz os seus dados de volta.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1101,"title":1102,"description":1103,"published":1104,"category":647,"image":1105,"draft":540},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Três formas de fazer backup de um banco Supabase, e o que falta","O painel, o pg_dump e um serviço gerenciado. O que cada um salva de verdade, o que deixa de fora sem avisar e qual sobrevive a perder a conta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1107,"title":1108,"description":1109,"published":1104,"category":536,"image":1110,"draft":540},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Quais chaves de API são seguras no navegador e quais não são","Sua chave anon do Supabase foi feita para ser pública. Sua chave service_role não, e ela ignora todas as regras que você criar. Como diferenciar as duas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213649189]