[{"data":1,"prerenderedAt":1223},["ShallowReactive",2],{"blog-es-test-your-supabase-backup":3,"blog-index-es":870},{"id":4,"title":5,"body":6,"category":825,"cover":826,"coverAlt":827,"description":828,"draft":829,"extension":830,"faq":831,"image":847,"keywords":848,"meta":857,"navigation":858,"ogTitle":859,"path":860,"published":861,"seo":862,"stem":863,"tldr":864,"updated":868,"__hash__":869},"blog_es\u002Fblog\u002Ftest-your-supabase-backup.md","Prueba tu backup de Supabase antes del día que lo necesites",{"type":7,"value":8,"toc":809},"minimark",[9,13,21,24,29,32,35,39,42,146,155,161,165,172,186,211,221,238,243,247,250,275,301,319,329,332,347,351,354,429,437,470,474,477,483,491,494,504,510,513,574,578,584,590,596,617,623,627,635,638,644,647,651,658,674,677,681,684,687,690,694,699,748,760,764,796],[10,11,12],"p",{},"En algún sitio hay un archivo con tu base de datos dentro. Una GitHub Action\nescribe uno cada noche, o ejecutaste una vez los tres comandos de backup de\nSupabase, o tu plan hace copias diarias. Tiene el nombre correcto y más o menos\nel tamaño que esperarías. Nadie lo ha abierto nunca.",[10,14,15,16,20],{},"Esta es la parte que las guías de configuración dejan para después: ",[17,18,19],"strong",{},"un\nbackup que nunca se ha restaurado es una promesa, no una copia."," La única\nforma de probar un backup de Supabase es restaurarlo, a propósito, en un sitio\ndonde no importe, y mirar lo que vuelve. Un dump cortado a la mitad, un dump\nsin ninguna fila y un dump del proyecto equivocado están todos en el\nalmacenamiento con el mismo aspecto que uno bueno.",[10,22,23],{},"Piensa en un simulacro de incendio. Un edificio lo hace una mañana cualquiera,\ncuando no arde nada, porque nadie debería bajar esas escaleras por primera vez\nel día en que se llenan de humo. Fuera, alguien pasa lista contra la lista de\nquién estaba dentro, y alguien apunta la fecha en la hoja junto a la puerta. Un\nsimulacro de restauración es lo mismo: recorrer el camino, contar y apuntarlo.",[25,26,28],"h2",{"id":27},"cómo-sé-si-mi-backup-de-supabase-funciona-de-verdad","¿Cómo sé si mi backup de Supabase funciona de verdad?",[10,30,31],{},"Restáuralo y mira. Es la única prueba que existe, porque nada en el propio\narchivo separa un backup bueno de uno roto.",[10,33,34],{},"El simulacro toma tu copia más reciente, la carga en un proyecto que no\nimporta y le hace tres preguntas al resultado. ¿Está cada tabla, con más o\nmenos tantas filas como la de producción? ¿La fila más reciente es de la noche\nen que se hizo la copia? ¿Puedes iniciar sesión como tú? Un archivo bueno\nresponde que sí a las tres, y cada forma en que un backup sale mal falla al\nmenos una de ellas.",[25,36,38],{"id":37},"cinco-formas-en-que-un-backup-está-mal-y-aun-así-parece-bien","Cinco formas en que un backup está mal y aun así parece bien",[10,40,41],{},"Las cinco terminan esa noche sin ningún error, y las cinco dejan un archivo con\nel nombre de siempre en el sitio de siempre. Solo se distinguen cuando se\ncarga el archivo.",[43,44,45,61],"table",{},[46,47,48],"thead",{},[49,50,51,55,58],"tr",{},[52,53,54],"th",{},"Qué le pasa al archivo",[52,56,57],{},"Cómo suele llegar a eso",[52,59,60],{},"El paso del simulacro que lo detecta",[62,63,64,88,106,124,135],"tbody",{},[49,65,66,70,85],{},[67,68,69],"td",{},"Se detiene a mitad de camino",[67,71,72,73,77,78,81,82,84],{},"Un script que pasa ",[74,75,76],"code",{},"pg_dump"," a ",[74,79,80],{},"gzip"," informa de lo que hizo ",[74,83,80],{},". Un dump que murió a la mitad se guarda, y el job dice que salió bien. Un disco lleno o una subida que se rindió hacen lo mismo",[67,86,87],{},"La línea final, y luego los recuentos",[49,89,90,93,103],{},[67,91,92],{},"Tiene tus tablas y ninguna de sus filas",[67,94,95,98,99,102],{},[74,96,97],{},"supabase db dump"," se ejecutó sin ",[74,100,101],{},"--data-only",", que así solo escribe la estructura",[67,104,105],{},"Los recuentos: todas las tablas en cero",[49,107,108,111,117],{},[67,109,110],{},"Tiene las filas y ninguna de las cuentas",[67,112,113,114],{},"El dump solo nombró tu propio esquema, y tus usuarios viven en uno llamado ",[74,115,116],{},"auth",[67,118,119,120,123],{},"La búsqueda de ",[74,121,122],{},"auth.users",", y luego el inicio de sesión",[49,125,126,129,132],{},[67,127,128],{},"Son los datos de otro proyecto",[67,130,131],{},"El connection string apunta a una copia de staging o a un proyecto antiguo",[67,133,134],{},"La fila más reciente, del día equivocado",[49,136,137,140,143],{},[67,138,139],{},"No se carga en absoluto",[67,141,142],{},"Un dump de Postgres 17 cargado en Postgres 15, o líneas de propietario que el proyecto nuevo rechaza",[67,144,145],{},"La restauración se detiene con un error",[10,147,148,149,154],{},"La segunda y la tercera son el tema de\n",[150,151,153],"a",{"href":152},"\u002Fblog\u002Fsupabase-backup-auth-users","por qué tu dump de Supabase no tiene usuarios",",\ny las dos salen de un comando de dump ejecutado con menos opciones de las que\nnecesitaba. La primera nos sorprendió, así que tiene una sección propia.",[156,157],"diagram",{"alt":158,"caption":159,"src":160},"Seis archivos sellados idénticos en fila, cada uno cae en una base de datos restaurada. La primera tiene tablas llenas y un registro de personas, con marca. Cinco están tachadas: una tabla cortada junto a una vacía, todas las tablas vacías, un registro vacío, filas grises marcadas como distintas y una carga detenida en una barra.","En el almacenamiento, los seis archivos parecen iguales. Al cargarlos, solo el primero te devuelve la base de datos que tenías.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fsix-files-one-good-copy-1600x760.png",[25,162,164],{"id":163},"falla-la-restauración-de-un-archivo-de-backup-cortado","¿Falla la restauración de un archivo de backup cortado?",[10,166,167,168,171],{},"No siempre. Cortamos uno a mitad de una tabla, lo cargamos con las opciones que\nusa la propia guía de Supabase, y ",[74,169,170],{},"psql"," terminó sin ningún error.",[10,173,174,175,177,178,181,182,185],{},"La prueba fue pequeña y fácil de repetir. El 27 de septiembre de 2026 hicimos\nun dump de una base de datos con dos tablas, una de 5.000 filas y otra de 300,\ncortamos el archivo en tres puntos distintos y cargamos cada versión con ",[74,176,170],{},"\nde Postgres 17.11. Cada carga usó ",[74,179,180],{},"--single-transaction"," y\n",[74,183,184],{},"--variable ON_ERROR_STOP=1",", las dos opciones que están ahí para detener una\nrestauración ante el primer problema y deshacer todo lo hecho.",[187,188,189,199,205],"ul",{},[190,191,192,195,196,198],"li",{},[17,193,194],{},"Cortado a mitad de un valor",", ",[74,197,170],{}," se detuvo con un error y no escribió\nnada. Es el resultado que esperarías.",[190,200,201,204],{},[17,202,203],{},"Cortado dentro de la última columna de una fila",", terminó con código de\nsalida 0, que es como un programa dice que salió bien. La primera tabla\nvolvió con 2.596 de sus 5.000 filas, a la última le faltaba la mitad del\ntexto, y la segunda tabla volvió vacía.",[190,206,207,210],{},[17,208,209],{},"Cortado justo entre las dos tablas",", también terminó con 0. La primera\ntabla estaba completa y la segunda vacía.",[10,212,213,214,217,218,220],{},"La razón está en cómo guarda las filas un dump. Las filas de cada tabla van en\nun bloque que termina con una línea que solo contiene ",[74,215,216],{},"\\.",", y cuando el archivo\nse acaba antes de esa línea, ",[74,219,170],{}," toma el final del archivo como el final del\nbloque. La única señal de que faltaba algo es una línea que debería estar al\nfinal del todo.",[10,222,223,224,226,227,230,231,234,235,237],{},"Esa línea es la despedida de ",[74,225,76],{},". Un dump completo tiene las palabras\n",[74,228,229],{},"PostgreSQL database dump complete"," cerca del final, y uno cortado no. De los\ntres archivos que escribe la CLI de Supabase, la línea solo sobrevive en\n",[74,232,233],{},"data.sql",", porque la CLI quita todos los comentarios del archivo de esquema\n(comprobado con la versión 2.111 de la CLI). Así que ",[74,236,233],{}," es el archivo\ndonde buscar, y esa búsqueda es el segundo paso del simulacro.",[156,239],{"alt":240,"caption":241,"src":242},"Un archivo con el borde inferior arrancado entra en un paso de restauración marcado ON_ERROR_STOP=1 con una marca verde. Detrás, dos tablas: la primera llena más o menos a la mitad, 2596 de 5000, con la última fila rota; la segunda vacía, 0 de 300.","La carga informó de éxito. La primera tabla volvió a medio llenar y la segunda volvió vacía.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fa-short-file-restores-clean-1600x680.png",[25,244,246],{"id":245},"dónde-debería-restaurarlo","¿Dónde debería restaurarlo?",[10,248,249],{},"En un proyecto de Supabase que no importe: un proyecto de prueba en tu cuenta,\no un Supabase que corra en tu propio ordenador. Nunca en el proyecto que usa tu\napp.",[10,251,252,255,256,262,263,268,269,274],{},[17,253,254],{},"Un proyecto de prueba en Supabase"," es lo más parecido a tu proyecto real, y\nes el destino para el que está escrita\n",[150,257,261],{"href":258,"rel":259},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fmigrating-within-supabase\u002Fbackup-restore",[260],"nofollow","la guía de backup y restauración de Supabase",":\nsu primer paso es crear un proyecto nuevo. En el plan gratuito\n",[150,264,267],{"href":265,"rel":266},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fbilling-faq",[260],"tienes derecho a dos proyectos gratuitos activos",",\ny los pausados no cuentan, así que un proyecto de prueba normalmente no cuesta\nnada mientras tu base de datos quepa en el plan gratuito. En una organización\nde pago, el cómputo de un proyecto nuevo se\n",[150,270,273],{"href":271,"rel":272},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fmanage-your-usage\u002Fcompute",[260],"cobra por horas",",\nasí que bórralo cuando termine el simulacro.",[10,276,277,280,281,292,293,296,297,300],{},[17,278,279],{},"Supabase en tu propio ordenador"," no cuesta nada y no necesita cuenta. La CLI\nde Supabase ejecuta todo el stack en local con Docker:\n",[150,282,285,288,289],{"href":283,"rel":284},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Flocal-development\u002Fcli\u002Fgetting-started",[260],[74,286,287],{},"supabase init",", luego ",[74,290,291],{},"supabase start",",\ny muestra una dirección de base de datos en el puerto 54322 y una publishable\nkey para el proyecto local. Antes de arrancarlo, abre ",[74,294,295],{},"supabase\u002Fconfig.toml"," y\npon en ",[74,298,299],{},"major_version"," la versión mayor de Postgres de tu proyecto. El\ncomentario encima de ese ajuste dice que tienen que coincidir, y la versión de\ntu proyecto está en Project Settings, luego General.",[10,302,303,304,306,307,310,311,313,314,318],{},"En Postgres 15 hay una trampa. Salvo que el job de backup fijara una versión, la\nCLI hizo la copia con ",[74,305,76],{}," 17, y el archivo de datos lleva entonces, cerca\ndel principio, ",[74,308,309],{},"SET transaction_timeout = 0",", un ajuste que Postgres 15 no\nreconoce, así que la carga se detiene en esa línea. Para el simulacro, pon\n",[74,312,299],{}," en 17. Después aplica al job de backup el arreglo de una línea\nque explica\n",[150,315,317],{"href":316},"\u002Fblog\u002Fsupabase-backup-github-action","el artículo sobre la GitHub Action",",\nporque el proyecto en el que restaurarías de verdad sigue en 15.",[10,320,321,322,324,325,328],{},"Un Postgres pelado en Docker, sin nada de Supabase dentro, no basta. Un dump de\nSupabase hace referencia a cosas que solo crea Supabase, como el esquema ",[74,323,116],{},"\ndonde viven tus usuarios y el rol ",[74,326,327],{},"authenticated"," que nombran tus reglas de\nseguridad, y la restauración se detiene en la primera línea que menciona una\nde ellas.",[10,330,331],{},"Una precaución, porque el proyecto de prueba ahora guarda una copia real. Tiene\nlas direcciones de email de tus usuarios, así que no apuntes tu app ni sus\nwebhooks a él, y bórralo cuando termines.",[10,333,334,335,338,339,342,343,346],{},"Las tareas programadas son lo que no viene. Si tu proyecto las ejecuta con la\nextensión ",[74,336,337],{},"pg_cron",", los tres archivos de la CLI traen de vuelta la extensión y\nninguna de sus tareas, porque las tareas son filas de ",[74,340,341],{},"cron.job"," y el dump de\ndatos deja esas filas fuera. Lo comprobamos el 4 de octubre de 2026 con la\nversión 2.119 de la CLI, restaurando una base de datos que tenía una tarea\nprogramada. Por eso el proyecto de prueba se queda quieto, y una restauración de\nverdad a partir de estos archivos también arranca sin ninguna tarea programada,\nasí que guarda tus llamadas a ",[74,344,345],{},"cron.schedule"," en algún sitio desde el que puedas\nvolver a ejecutarlas.",[25,348,350],{"id":349},"cómo-probar-un-backup-de-supabase-paso-a-paso","Cómo probar un backup de Supabase, paso a paso",[10,352,353],{},"Seis pasos, y los tres primeros ocurren antes de restaurar nada.",[355,356,357,363,386,402,417,423],"ol",{},[190,358,359,362],{},[17,360,361],{},"Busca la copia más reciente y lee su fecha."," Si es más antigua que la\núltima ejecución programada, el job se ha parado, y ese es tu primer\nhallazgo.",[190,364,365,375,376],{},[17,366,367,368,371,372,374],{},"Busca ",[74,369,370],{},"dump complete"," en ",[74,373,233],{},"."," Una coincidencia significa que el\narchivo llegó hasta el final. Ninguna significa que se cortó, sea cual sea\nsu tamaño. La búsqueda de un editor de texto sirve igual que una terminal:",[377,378,383],"pre",{"className":379,"code":381,"language":382},[380],"language-text","grep -c 'dump complete' data.sql\n","text",[74,384,381],{"__ignoreMap":385},"",[190,387,388,391,392,395,396],{},[17,389,390],{},"Busca en él a tus usuarios."," Una línea que empieza por\n",[74,393,394],{},"COPY \"auth\".\"users\""," con filas debajo significa que tus cuentas están en el\narchivo:",[377,397,400],{"className":398,"code":399,"language":382},[380],"grep -n 'COPY .*auth.*users' data.sql\n",[74,401,399],{"__ignoreMap":385},[190,403,404,407,408,374,411],{},[17,405,406],{},"Cárgalo en el proyecto de prueba"," con el comando de la guía de Supabase,\napuntado al connection string del proyecto de prueba. En un Supabase local\nese string es ",[74,409,410],{},"postgresql:\u002F\u002Fpostgres:postgres@127.0.0.1:54322\u002Fpostgres",[377,412,415],{"className":413,"code":414,"language":382},[380],"psql \\\n  --single-transaction \\\n  --variable ON_ERROR_STOP=1 \\\n  --file roles.sql \\\n  --file schema.sql \\\n  --command 'SET session_replication_role = replica' \\\n  --file data.sql \\\n  --dbname \"postgresql:\u002F\u002F…the spare's connection string…\"\n",[74,416,414],{"__ignoreMap":385},[190,418,419,422],{},[17,420,421],{},"Cuenta las filas y lee la más reciente",", en las dos bases de datos. La\nconsulta está en la sección siguiente.",[190,424,425,428],{},[17,426,427],{},"Inicia sesión en el proyecto de prueba como tú."," El comando está en la\nsección de después.",[10,430,431,432,436],{},"Si el paso 4 se detiene con un error, el simulacro ya ha hecho su trabajo. Las\nnotas de solución de problemas al final de la guía de Supabase cubren los dos\nerrores más habituales, los dos sobre roles, y\n",[150,433,435],{"href":434},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","cómo restaurar un backup de Supabase","\nexplica de qué te protege cada opción de ese comando.",[10,438,439,440,443,444,447,448,451,452,455,456,459,460,463,464,469],{},"Faltan en esas notas otras dos paradas en ",[74,441,442],{},"roles.sql",". Nos encontramos con las\ndos el 4 de octubre de 2026, al cargar los archivos de dos bases de datos\nPostgres 17, una de ellas un proyecto de Supabase, en una copia local nueva de\nSupabase: ",[74,445,446],{},"\"supabase_admin\" is a reserved role, only superusers can modify it",",\nen una línea que empieza por ",[74,449,450],{},"ALTER ROLE \"supabase_admin\"",", y\n",[74,453,454],{},"permission denied for parameter log_min_messages",", en una línea que empieza por\n",[74,457,458],{},"GRANT SET ON PARAMETER",". Las dos líneas configuran roles que Supabase crea por\nsu cuenta en cada proyecto, así que pon ",[74,461,462],{},"--"," al principio de cada una para\nconvertirla en un comentario y vuelve a ejecutar el comando.\n",[150,465,468],{"href":466,"rel":467},"https:\u002F\u002Fgithub.com\u002FReeve-page\u002Fsupabase-backup-action",[260],"Nuestra Action de backup","\nlas comenta ya al hacer la copia.",[25,471,473],{"id":472},"qué-contar-y-contra-qué","Qué contar, y contra qué",[10,475,476],{},"Cuenta cada tabla en el proyecto de prueba y en tu proyecto en producción con\nla misma consulta, y pon las dos listas una al lado de la otra. La copia\ndebería ir una noche por detrás de la base en producción: un poco más baja en\nuna tabla que crece, y nunca en cero en una tabla que tenía filas.",[10,478,479,480,482],{},"Es pasar lista contra la lista de quién estaba dentro. Pega la consulta en el\neditor SQL de cada proyecto y pulsa Run. Cuenta las filas de cada tabla de tu\npropio esquema y de ",[74,481,116],{},":",[377,484,489],{"className":485,"code":487,"language":488,"meta":385},[486],"language-sql","select table_schema, table_name,\n       (xpath('\u002Frow\u002Fn\u002Ftext()',\n         query_to_xml(format('select count(*) as n from %I.%I', table_schema, table_name),\n                      false, true, '')))[1]::text::bigint as row_count\n  from information_schema.tables\n where table_schema in ('public', 'auth')\n   and table_type = 'BASE TABLE'\n order by table_schema, table_name;\n","sql",[74,490,487],{"__ignoreMap":385},[10,492,493],{},"Lee cada fila de cada tabla, así que en una base de datos grande ejecútala\nfuera de tus horas de más actividad.",[10,495,496,497,500,501,482],{},"Luego lee la fila más reciente de una tabla que conozcas, solo en el proyecto\nde prueba. Sirve cualquier tabla con una columna ",[74,498,499],{},"created_at","; pon su nombre en\nlugar de ",[74,502,503],{},"orders",[377,505,508],{"className":506,"code":507,"language":488,"meta":385},[486],"select max(created_at) from public.orders;\n",[74,509,507],{"__ignoreMap":385},[10,511,512],{},"La respuesta debería estar cerca de la hora en que se hizo el backup. Una fecha\nsemanas más antigua, o filas que no reconoces, significan que el archivo vino\nde otro proyecto.",[43,514,515,528],{},[46,516,517],{},[49,518,519,522,525],{},[52,520,521],{},"Comprobación",[52,523,524],{},"Dónde",[52,526,527],{},"Lo que muestra una copia buena",[62,529,530,541,552,564],{},[49,531,532,535,538],{},[67,533,534],{},"Filas en cada tabla",[67,536,537],{},"En los dos",[67,539,540],{},"Las mismas tablas, cada una un poco por detrás de producción, ninguna vacía que tuviera filas",[49,542,543,546,549],{},[67,544,545],{},"La fila más reciente",[67,547,548],{},"Proyecto de prueba",[67,550,551],{},"Una hora de la noche en que se hizo la copia",[49,553,554,557,559],{},[67,555,556],{},"Tu propia cuenta",[67,558,548],{},[67,560,561,562],{},"Tu email en ",[74,563,122],{},[49,565,566,569,571],{},[67,567,568],{},"Un inicio de sesión",[67,570,548],{},[67,572,573],{},"Vuelve un token",[25,575,577],{"id":576},"por-qué-el-inicio-de-sesión-es-la-prueba-que-demuestra-tus-cuentas","Por qué el inicio de sesión es la prueba que demuestra tus cuentas",[10,579,580,581,583],{},"Un recuento de ",[74,582,122],{}," demuestra que las filas llegaron. Un inicio de\nsesión demuestra que funcionan: que la contraseña guardada, el servicio de\ninicio de sesión del proyecto de prueba y tu dirección de email siguen de\nacuerdo entre sí.",[10,585,586,587,589],{},"Usa tu propia cuenta, con una contraseña que conozcas. La dirección del\nproyecto y la publishable key del proyecto de prueba están en su panel Connect,\no en la salida de ",[74,588,291],{}," en un Supabase local:",[377,591,594],{"className":592,"code":593,"language":382},[380],"curl -X POST 'https:\u002F\u002F…the spare's project ref….supabase.co\u002Fauth\u002Fv1\u002Ftoken?grant_type=password' \\\n  -H \"apikey: sb_publishable_…\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\": \"you@example.com\", \"password\": \"…\"}'\n",[74,595,593],{"__ignoreMap":385},[10,597,598,599,604,605,608,609,612,613,616],{},"Es la llamada de inicio de sesión de\n",[150,600,603],{"href":601,"rel":602},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fpasswords",[260],"la propia documentación de Supabase",",\ndirigida al proyecto de prueba. Una respuesta que contiene ",[74,606,607],{},"access_token","\nsignifica que tu cuenta llegó con una contraseña que funciona.\n",[74,610,611],{},"Invalid login credentials",", para una cuenta que inicia sesión sin problemas en\ntu app en producción, significa que no llegó, y\n",[150,614,615],{"href":152},"por qué un dump llega sin las cuentas"," es el\nartículo para ese resultado.",[10,618,619,620,622],{},"Si todo el mundo inicia sesión en tu app con Google, esta llamada no tiene nada\nque probar, porque el proyecto de prueba no tiene configurado el inicio de\nsesión con Google. Busca en su lugar tu propio email en ",[74,621,122],{}," después de\nrestaurar. Eso muestra que la fila de la cuenta llegó, aunque no que su\ncontraseña funcione.",[25,624,626],{"id":625},"archivos-la-mitad-que-una-restauración-de-la-base-no-puede-probar","Archivos: la mitad que una restauración de la base no puede probar",[10,628,629,630,634],{},"La copia de la base de datos guarda una fila por cada archivo subido y ninguno\nde los archivos. Si copias tus buckets de Storage con un job propio, que\n",[150,631,633],{"href":632},"\u002Fblog\u002Fsupabase-storage-backup","es la única forma de que se copien",", hazle un\nsimulacro a esa copia también.",[10,636,637],{},"Toma las tres filas más recientes de la base restaurada:",[377,639,642],{"className":640,"code":641,"language":488,"meta":385},[486],"select bucket_id, name from storage.objects order by created_at desc limit 3;\n",[74,643,641],{"__ignoreMap":385},[10,645,646],{},"Busca esas tres rutas en tu copia de los archivos y abre cada una. Una ruta sin\narchivo detrás es una imagen que tus usuarios verían rota después de una\nrestauración real.",[25,648,650],{"id":649},"puedo-probar-los-backups-que-supabase-hace-por-mí","¿Puedo probar los backups que Supabase hace por mí?",[10,652,653,654,374],{},"En un plan de pago, sí, con Restore to a New Project. Es la única forma de\nabrir una de las copias diarias de Supabase, porque en los proyectos actuales\n",[150,655,657],{"href":656},"\u002Fblog\u002Fdownload-your-supabase-backup","no puedes descargarlas",[10,659,660,661,666,667,669,670,673],{},"Supabase describe la función como una forma de\n",[150,662,665],{"href":663,"rel":664},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fclone-project",[260],"hacer pruebas sin riesgo",".\nElige una copia en la pestaña Restore to a New Project de la página Backups, y\nSupabase crea con ella un proyecto nuevo con tus usuarios y sus contraseñas\nhasheadas, listo para los mismos recuentos y el mismo inicio de sesión. Dos\ncosas que conviene saber antes de pulsar. El proyecto nuevo se factura como un\nproyecto aparte, y Supabase te muestra el coste antes de empezar. Y lo copia\ntodo, tareas programadas incluidas: Supabase dice que las tareas de ",[74,668,337],{},",\n",[74,671,672],{},"pg_net"," y los wrappers empiezan a ejecutarse en cuanto termina la\nrestauración, sin forma de pausarlas antes. Si una tarea de tu app envía emails\no cobra una tarjeta, el proyecto de prueba también lo hará.",[10,675,676],{},"Si además guardas un archivo fuera de la cuenta, ese archivo necesita su propio\nsimulacro.",[25,678,680],{"id":679},"cada-cuánto-debería-probar-una-restauración","¿Cada cuánto debería probar una restauración?",[10,682,683],{},"Una vez ahora, luego cada tres meses, y otra vez siempre que cambie algo en\ncómo se hace el backup.",[10,685,686],{},"Los cambios que importan son los que rompen un backup en silencio: un workflow\nnuevo o editado, una contraseña de base de datos restablecida, un cambio a un\nplan nuevo o a una versión nueva de Postgres, una tabla nueva en la que tu app\nha empezado a escribir. Después de cada uno, el simulacro del trimestre pasado\nya no describe el archivo de este trimestre.",[10,688,689],{},"Luego apúntalo, que es la hoja junto a la puerta. Una línea por simulacro, en\nun sitio al que llegues sin lo que se ha roto: la fecha, qué archivo, los\nrecuentos que importaban, si el inicio de sesión funcionó y cuánto tardó el\nsimulacro entero. Vale un archivo de texto en el repositorio del backup, y\ntambién un evento recurrente en el calendario con los resultados pegados. La\nfecha responde a «cuándo lo comprobamos por última vez» en la hora en que\nalguien necesita saberlo, y lo que tardó es tu primera estimación de cuánto\ntiempo una restauración real dejaría tu app parada.",[25,691,693],{"id":692},"dónde-encaja-reeve-care","Dónde encaja Reeve Care",[10,695,696],{},[17,697,698],{},"Care guarda copias de tu base de datos de Supabase fuera de tu cuenta de\nSupabase, según el horario de tu plan, comprueba cada copia en el momento de\nhacerla y la devuelve a su sitio con un botón.",[187,700,701,707,716,722,728,734],{},[190,702,703,706],{},[17,704,705],{},"Las copias siguen el horario de tu plan",", desde una vez al día hasta cada\nseis horas.",[190,708,709,712,713,715],{},[17,710,711],{},"Una copia cortada se detecta en el momento de hacerla."," La línea final de\n",[74,714,76],{}," tiene que estar en el archivo, o la copia no pasa la comprobación y\nnunca se convierte en la fecha de tu panel.",[190,717,718,721],{},[17,719,720],{},"Cada tabla se cuenta mientras se escribe la copia."," Cuando una tabla que\ntenía filas en la copia anterior no tiene ninguna en esta, una persona de\nReeve se entera.",[190,723,724,727],{},[17,725,726],{},"Tus cuentas van dentro",", y tus archivos subidos también vienen en cuanto\nconectas una credencial de Storage.",[190,729,730,733],{},[17,731,732],{},"Restaurar es un botón",", y antes de reemplazar nada se hace una copia del\nestado actual.",[190,735,736,739,740,195,743,669,745,747],{},[17,737,738],{},"Cualquier copia se descarga como zip"," con ",[74,741,742],{},"schema.sql",[74,744,233],{},[74,746,442],{}," y un manifiesto con el número de filas de cada tabla, que es la\nmitad «contra qué» de este artículo, ya apuntada.",[10,749,750,751,451,755,759],{},"Un simulacro trimestral demuestra la copia que elegiste ese día, y la\ncomprobación se hace en cada copia en el momento de hacerla. La copia, la\ncomprobación y la restauración están dibujadas paso a paso en la\n",[150,752,754],{"href":753},"\u002Fsupabase-backups","página de backups de Supabase",[150,756,758],{"href":757},"\u002Fpricing","qué incluye cada plan",", horario incluido, está en la página de\nprecios.",[25,761,763],{"id":762},"qué-hacer-esta-semana","Qué hacer esta semana",[765,766,767],"key-takeaways",{},[187,768,769,772,782,788,791,793],{},[190,770,771],{},"Busca tu backup más reciente y lee su fecha. Si es más antiguo que la última ejecución programada, arregla el job antes que nada.",[190,773,367,774,776,777,371,779,781],{},[74,775,370],{}," y ",[74,778,394],{},[74,780,233],{},". Dos búsquedas te dicen si el archivo llega al final y si tus cuentas están dentro.",[190,783,784,785,787],{},"Crea un proyecto de prueba, o arranca Supabase en tu propio ordenador, y carga el archivo con el comando ",[74,786,170],{}," de la guía de Supabase.",[190,789,790],{},"Ejecuta la consulta de recuento en las dos bases de datos y pon las dos listas una al lado de la otra. Lee la fila más reciente de una tabla que conozcas.",[190,792,427],{},[190,794,795],{},"Apunta la fecha, los recuentos y cuánto tardó, y luego borra el proyecto de prueba.",[10,797,798,799,801,802,804,805,808],{},"Antes de cerrar esta pestaña, busca ",[74,800,370],{}," en tu ",[74,803,233],{}," más\nreciente. Es una sola búsqueda, y te dice si el archivo al que llamas backup\nllega a su propia última línea. Si todavía no tienes un archivo en el que\nbuscar, ",[150,806,807],{"href":316},"una GitHub Action gratuita"," es la\nforma más rápida de empezar a generarlos.",{"title":385,"searchDepth":810,"depth":810,"links":811},3,[812,814,815,816,817,818,819,820,821,822,823,824],{"id":27,"depth":813,"text":28},2,{"id":37,"depth":813,"text":38},{"id":163,"depth":813,"text":164},{"id":245,"depth":813,"text":246},{"id":349,"depth":813,"text":350},{"id":472,"depth":813,"text":473},{"id":576,"depth":813,"text":577},{"id":625,"depth":813,"text":626},{"id":649,"depth":813,"text":650},{"id":679,"depth":813,"text":680},{"id":692,"depth":813,"text":693},{"id":762,"depth":813,"text":763},"Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcover-1200x630.png","Una fila de archivos de backup sellados e idénticos, el primero iluminado, junto a una base de datos vacía y punteada que espera uno.","Cómo probar tu backup de Supabase: restaurarlo en un proyecto de prueba, contar filas, iniciar sesión y buscar la línea que le falta a un archivo cortado.",false,"md",[832,834,836,839,842,845],{"q":28,"a":833},"Restáuralo en un proyecto que no importe y mira lo que vuelve. Compara el número de filas de cada tabla con la base de datos en producción, comprueba que la fila más reciente es de la noche en que se hizo la copia e inicia sesión como tú. Nada en el propio archivo distingue un dump bueno de uno roto: su nombre, su tamaño y la marca verde junto al job son iguales en los dos casos.",{"q":680,"a":835},"Una vez ahora, luego cada tres meses, y otra vez siempre que cambie la forma en que se hace el backup: un workflow nuevo o editado, una contraseña de base de datos restablecida, un plan o una versión de Postgres nuevos, o una tabla nueva en la que escribe tu app. Apunta la fecha cada vez, con los recuentos y cuánto tardó, para que la pregunta de cuándo se comprobó por última vez tenga respuesta.",{"q":837,"a":838},"¿Puedo probar una restauración sin tocar mi base de datos en producción?","Sí, y siempre deberías hacerlo así. Restaura en un proyecto de prueba de Supabase, algo que el plan gratuito permite, o en un Supabase que corre en tu propio ordenador con la CLI y Docker. Lo único que el simulacro le hace a la base en producción es leerla una vez para contar sus filas. Borra el proyecto de prueba después, porque guarda una copia real de tus usuarios.",{"q":840,"a":841},"¿Qué debería comprobar después de restaurar un backup?","Cuatro cosas. El número de filas de cada tabla junto al de producción, donde la copia debería ir un poco por detrás y nunca en cero para una tabla que tenía filas. La fila más reciente de una tabla que conozcas, que debería ser de la noche de la copia. Tu propio email en auth.users. Y un inicio de sesión como tú, la única comprobación que demuestra que las cuentas funcionan y no solo que llegaron.",{"q":843,"a":844},"La restauración funcionó, pero nadie puede iniciar sesión. ¿Por qué?","Casi siempre porque el archivo nunca tuvo tus cuentas. Supabase las guarda en un esquema llamado auth, y un dump que solo nombró tu propio esquema, o un supabase db dump sin opciones, las deja fuera mientras cada una de tus tablas se restaura sin problema. Busca primero COPY \"auth\".\"users\" en el archivo. Si no está, haz un dump de datos con --data-only, que recorre el esquema auth y se lleva a tus usuarios.",{"q":164,"a":846},"No siempre. Cortamos un archivo de pg_dump en tres puntos y cargamos cada versión con --single-transaction y ON_ERROR_STOP, las opciones de la guía de restauración de Supabase. Un corte a mitad de un valor se detuvo con un error. Un corte dentro de la última columna de una fila y un corte entre dos tablas terminaron los dos sin error, con las tablas incompletas. Un dump completo lleva la línea PostgreSQL database dump complete cerca del final, así que búscala antes de fiarte de un archivo.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",[849,850,851,852,853,854,855,856],"probar backup supabase","verificar backup supabase","prueba de restauración supabase","cómo probar un backup de base de datos","restaurar backup en base de datos de prueba","funciona mi backup de supabase","verificación de backup supabase","simulacro de restauración",{},true,"Prueba tu backup de Supabase antes de necesitarlo","\u002Fblog\u002Ftest-your-supabase-backup","2026-09-28",{"title":5,"description":828},"blog\u002Ftest-your-supabase-backup",[865,866,867],"Para probar un backup de Supabase, restáuralo en un proyecto que no importe, compara sus números de filas con la base de datos en producción e inicia sesión como tú. Solo una restauración distingue un archivo bueno de uno roto.","Cortamos un dump a mitad de una tabla y lo cargamos con las opciones que recomienda Supabase. psql terminó sin ningún error, y las tablas volvieron incompletas.","Haz el simulacro una vez ahora, luego cada tres meses y después de cualquier cambio en cómo se hace el backup, y apunta la fecha cada vez.","2026-10-05","MXUIeIUjfIgwNZ0Xl-6uPdySwBn2a4Pe8wPTTZbRT7Y",[871,878,884,890,896,902,908,913,919,925,931,937,943,949,950,955,960,965,971,977,982,988,994,1000,1006,1012,1018,1024,1030,1035,1041,1047,1053,1059,1065,1071,1077,1083,1089,1095,1101,1107,1113,1119,1125,1131,1137,1143,1149,1155,1160,1166,1172,1178,1184,1189,1195,1201,1207,1212,1218],{"path":872,"title":873,"description":874,"published":875,"category":876,"image":877,"draft":829},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" al subir","\"New row violates row-level security policy for table objects\" significa que tu subida no tiene regla insert. Hacer público el bucket no añade ninguna.","2026-10-11","Fundamentos de seguridad","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":879,"title":880,"description":881,"published":882,"category":876,"image":883,"draft":829},"\u002Fblog\u002Fbase44-security-scan","Escaneo de seguridad de Base44: lo que solo él ve","El escaneo de seguridad de Base44 revisa siete tipos de problema desde dentro. Esta es la mitad que lee y nadie más puede leer, y la mitad que nunca mira.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":885,"title":886,"description":887,"published":888,"category":876,"image":889,"draft":829},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Tu clave API se filtró. El orden en el que hay que actuar","Una clave API se filtró y no sabes por dónde empezar. No todas las claves de tu frontend lo son, y el orden importa más que la velocidad.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":891,"title":892,"description":893,"published":894,"category":876,"image":895,"draft":829},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" sin desactivar RLS","\"Infinite recursion detected in policy for relation\" significa que tu policy preguntó a la tabla que protege. Así se rompe el círculo.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":897,"title":898,"description":899,"published":900,"category":876,"image":901,"draft":829},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" en Supabase, y el arreglo equivocado","\"No API key found in request\" significa que tu petición llegó a Supabase sin clave. Casi todas las respuestas apuntan a las reglas de tu base de datos.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":903,"title":904,"description":905,"published":906,"category":876,"image":907,"draft":829},"\u002Fblog\u002Fis-base44-safe","¿Es seguro Base44? Lo que vimos en 5.442 apps Base44","¿Es seguro Base44? Pasamos nueve comprobaciones a 5.442 apps Base44 en producción. Casi todas sacaron B por motivos que su dueño nunca eligió.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":909,"title":910,"description":911,"published":868,"category":876,"image":912,"draft":829},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Ocultar una clave API: muévela a una Edge Function de Supabase","Ocultar una clave API significa sacarla del navegador, y una Edge Function de Supabase es el sitio más pequeño donde ponerla. Dos pasos importan más.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":914,"title":915,"description":916,"published":917,"category":876,"image":918,"draft":829},"\u002Fblog\u002Fenv-file-exposed-on-your-server","¿Tu archivo .env está expuesto? Las doce rutas a revisar","¿Tu archivo .env está expuesto en tu propio servidor web? Doce direcciones te lo dicen, y un acierto significa que todo lo que contiene ya es público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":920,"title":921,"description":922,"published":923,"category":876,"image":924,"draft":829},"\u002Fblog\u002Fis-v0-safe","Seguridad de v0: las 1.790 aplicaciones escaneadas sacaron una A","Seguridad de v0, medida en 1.790 aplicaciones v0 en vivo: todas sacaron A. Solo 17 nombraban una base de datos, y eso es casi todo lo que mide la A.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":926,"title":927,"description":928,"published":929,"category":876,"image":930,"draft":829},"\u002Fblog\u002Fis-bolt-safe","¿Es seguro Bolt? Lo que vimos en 1.123 aplicaciones Bolt","¿Es seguro Bolt? Pasamos 1.123 aplicaciones Bolt en vivo por nueve comprobaciones. El hosting salió limpio. Los hallazgos eran claves y tablas abiertas dentro.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":932,"title":933,"description":934,"published":935,"category":876,"image":936,"draft":829},"\u002Fblog\u002Fis-supabase-down-or-your-app","¿Supabase está caído o es tu app? Cómo distinguirlo","¿Supabase está caído o es tu app? Un proyecto pausado, una base de datos llena y un fallo tuyo parecen lo mismo. Cuatro comprobaciones los separan.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":938,"title":939,"description":940,"published":941,"category":876,"image":942,"draft":829},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","¿Supabase cifra mis datos? Sí. Esto es lo que detiene","¿Supabase cifra los datos? Sí: AES-256 en reposo, TLS en tránsito, SOC 2 e ISO 27001. Qué cubre cada uno, y la fuga que ninguno de ellos detiene.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":944,"title":945,"description":946,"published":947,"category":876,"image":948,"draft":829},"\u002Fblog\u002Fsupabase-free-plan-limits","¿Cuánto cuesta Supabase? Los límites del plan gratuito","Los límites del plan gratuito de Supabase: 500 MB de base de datos, 5 GB de egress y ningún backup. Qué pasa en cada uno y qué cambia Pro por $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":860,"title":5,"description":828,"published":861,"category":825,"image":847,"draft":829},{"path":316,"title":951,"description":952,"published":953,"category":825,"image":954,"draft":829},"Backup gratis de Supabase con una GitHub Action, y la trampa","Un backup de Supabase con GitHub Action es gratis y sirve a muchas apps. El workflow, el connection string correcto y el egress de cada ejecución.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":656,"title":956,"description":957,"published":958,"category":825,"image":959,"draft":829},"Por qué no puedes descargar tu backup de Supabase","No puedes descargar tu backup de Supabase en un proyecto actual: la copia diaria es una instantánea física. Cómo comprobarlo y tener tu propia copia.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":961,"title":962,"description":963,"published":958,"category":876,"image":964,"draft":829},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": el grant que falta","Desde el 30 de octubre, una tabla nueva de Supabase responde \"permission denied for table\" hasta que le das acceso. El grant del email es la mitad del arreglo.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":966,"title":967,"description":968,"published":969,"category":876,"image":970,"draft":829},"\u002Fblog\u002Fopen-api-endpoint-exposed","¿Un endpoint de API abierto es un problema? Mira el JSON","Tu escaneo señaló un endpoint de API abierto. Que importe depende de lo que devolvió, y la mayoría de los que encontramos eran de la plataforma.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":972,"title":973,"description":974,"published":975,"category":876,"image":976,"draft":829},"\u002Fblog\u002Flovable-security-scan","Escaneo de seguridad de Lovable: lo que no puede probar","Escaneo de seguridad de Lovable: qué revisan el Quick scan y el Deep scan, cuándo corre cada uno, y lo único que ningún escaneo desde dentro puede probar.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":152,"title":978,"description":979,"published":980,"category":825,"image":981,"draft":829},"Por qué tu dump de Supabase no tiene usuarios dentro","Ejecuta supabase db dump por sí solo y obtienes la forma de tu base de datos y ninguna de sus filas, sin el esquema auth donde viven tus usuarios.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":983,"title":984,"description":985,"published":986,"category":876,"image":987,"draft":829},"\u002Fblog\u002Fdomain-and-certificate-expiry","Dominio caducado, web caída: qué pasa a partir de ahora","Tu dominio caducó y tu web está caída. Aquí tienes el reloj que acaba de arrancar, por qué el certificado es el menor problema, y cómo comprobar ambos.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":989,"title":990,"description":991,"published":992,"category":876,"image":993,"draft":829},"\u002Fblog\u002Fis-lovable-safe","¿Es seguro Lovable? Lo que vimos en 18.554 aplicaciones Lovable","¿Es seguro Lovable? Pasamos 18.554 aplicaciones Lovable por nueve comprobaciones. La plataforma fue la más limpia de cinco. Los hallazgos estaban dentro.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":995,"title":996,"description":997,"published":998,"category":876,"image":999,"draft":829},"\u002Fblog\u002Fvibe-coded-app-security-checklist","La lista de seguridad del vibe coding, en nueve comprobaciones","Una lista de seguridad del vibe coding con nueve puntos, cada uno verificable en tu app desde fuera por cualquiera, y cada uno con una prueba de una línea.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":1001,"title":1002,"description":1003,"published":1004,"category":876,"image":1005,"draft":829},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Una clave secreta de Stripe en tu frontend puede mover dinero","Una clave secreta de Stripe expuesta en tu frontend puede reembolsar, cobrar y leer cada ficha de cliente que tienes. Tu clave pk_live_ sí debe estar ahí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":1007,"title":1008,"description":1009,"published":1010,"category":876,"image":1011,"draft":829},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variables de entorno de Vite expuestas: el prefijo dice publica esto","Variables de entorno de Vite expuestas en tu app: hicieron lo que pedía el prefijo. VITE_ y NEXT_PUBLIC_ significan publica esto, y la IA nunca supo el coste.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":1013,"title":1014,"description":1015,"published":1016,"category":876,"image":1017,"draft":829},"\u002Fblog\u002Fbase44-source-maps","Seguridad en Base44: qué marca un escaneo y qué te toca arreglar a ti","Seguridad en Base44 en 5.438 apps escaneadas: tres hallazgos en casi todas son de la plataforma, el source map es la insignia de Base44 y lo tuyo es poco.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":1019,"title":1020,"description":1021,"published":1022,"category":876,"image":1023,"draft":829},"\u002Fblog\u002Fis-cursor-ai-safe","¿Es seguro Cursor AI? El editor, el código y la app que publicaste","¿Es seguro Cursor AI? Tres preguntas en una búsqueda: qué guarda Cursor, en qué falla el código que escribe y si la app que publicaste está abierta.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1025,"title":1026,"description":1027,"published":1028,"category":876,"image":1029,"draft":829},"\u002Fblog\u002Fis-replit-safe","¿Es seguro Replit? Lo que vimos en 3.042 aplicaciones Replit en vivo","¿Es seguro Replit? Pasamos 3.042 aplicaciones Replit en vivo por nueve comprobaciones externas. Los hallazgos estaban en la aplicación publicada, no en el host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":632,"title":1031,"description":1032,"published":1033,"category":825,"image":1034,"draft":829},"Supabase storage backup: tu copia de la base no tiene archivos","Un Supabase storage backup es una tarea aparte. Las copias de la base guardan la lista de tus archivos y ninguno de ellos, así que cada upload queda roto.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1036,"title":1037,"description":1038,"published":1039,"category":825,"image":1040,"draft":829},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery de Supabase: precio y límites","El point-in-time recovery de Supabase rebobina tu base de datos a cualquier segundo de la última semana. Cuesta $100 al mes sobre Pro y solo cubre la base.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1042,"title":1043,"description":1044,"published":1045,"category":825,"image":1046,"draft":829},"\u002Fblog\u002Fsupabase-project-paused-recover","¿Proyecto de Supabase pausado? Tus datos siguen ahí","Supabase pausó tu proyecto tras una semana sin actividad. No se ha borrado nada, Restaurar está junto al nombre y tienes un año antes de que eso cambie.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1048,"title":1049,"description":1050,"published":1051,"category":876,"image":1052,"draft":829},"\u002Fblog\u002Fsafest-ai-app-builder","¿Qué builder de apps con IA es más seguro? 30.998 apps escaneadas","¿Qué builder de apps con IA es más seguro? Escaneamos 30.998 apps activas de Lovable, Base44, Replit, v0 y Bolt. El builder no es lo que decide tu nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":1054,"title":1055,"description":1056,"published":1057,"category":876,"image":1058,"draft":829},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Activa Row Level Security en cada tabla de Supabase y compruébalo","Activar Row Level Security en Supabase sin política cierra la tabla del todo. Una política sin el interruptor no hace nada. Aquí tienes el SQL y la prueba.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1060,"title":1061,"description":1062,"published":1063,"category":876,"image":1064,"draft":829},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": lo que el aviso no ve","Supabase marca \"RLS disabled in public\" como error. No dice nada de la política de lectura que deja tu tabla igual de abierta a cualquiera.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1066,"title":1067,"description":1068,"published":1069,"category":876,"image":1070,"draft":829},"\u002Fblog\u002Frotate-supabase-service-role-key","Cómo rotar una clave service_role de Supabase filtrada","Supabase dice que primero cierres la fuga. Otras guías dicen que rotes ya. Cuál es lo correcto depende de dónde se filtró tu clave service_role.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1072,"title":1073,"description":1074,"published":1075,"category":876,"image":1076,"draft":829},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Escáneres de seguridad vibe coding comparados, el nuestro incluido","El mejor escáner de seguridad para vibe coding depende de tres preguntas que ninguna lista de funciones responde. Diez herramientas, con precios.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1078,"title":1079,"description":1080,"published":1081,"category":876,"image":1082,"draft":829},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: haz tú mismo las cinco comprobaciones","Un Supabase security checker lee tu app publicada en lugar de la configuración de tu proyecto. Estas son las cinco comprobaciones y cómo hacer cada una.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1084,"title":1085,"description":1086,"published":1087,"category":876,"image":1088,"draft":829},"\u002Fblog\u002Fvibe-coding-security-scanner","Escáner de seguridad para vibe coding: qué se le escapa","Un escáner de seguridad para vibe coding lee tu app en vivo desde fuera. Qué cubre eso, las cuatro cosas que no puede ver y cómo leer el resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1090,"title":1091,"description":1092,"published":1093,"category":876,"image":1094,"draft":829},"\u002Fblog\u002Fmissing-security-headers","Faltan cabeceras de seguridad: cuándo importa de verdad","Que falten cabeceras de seguridad es el hallazgo que más imprime nuestro escáner. Contra qué protegen y cuándo son la línea menos urgente de tu informe.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1096,"title":1097,"description":1098,"published":1099,"category":876,"image":1100,"draft":829},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Tu clave de API de OpenAI está expuesta en tu frontend. Rótala.","Una clave de API de OpenAI expuesta en tu frontend no se puede atar a un dominio. Rótala hoy, mueve la llamada a tu servidor y limita el gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1102,"title":1103,"description":1104,"published":1105,"category":876,"image":1106,"draft":829},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Clave de API expuesta en el frontend: qué llevan 30.998 apps","Una clave de API expuesta en tu frontend suele ser una clave de Google Maps. Escaneamos 30.998 apps vibe-coded y contamos qué secretos se filtran de verdad.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1108,"title":1109,"description":1110,"published":1111,"category":825,"image":1112,"draft":829},"\u002Fblog\u002Fsupabase-backup-tools-compared","Herramientas de backup de Supabase comparadas, la nuestra incluida","Cuatro tipos de herramienta de backup de Supabase, qué copia cada una y cuándo una GitHub Action gratuita le gana a pagar a cualquiera, nosotros incluidos.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1114,"title":1115,"description":1116,"published":1117,"category":876,"image":1118,"draft":829},"\u002Fblog\u002Freplit-secrets-explained","Cómo usar secrets en Replit, y qué se publica de todos modos","Cómo usar secrets en Replit: añadir uno, leerlo y arreglar las dos causas del undefined. Y las claves que la herramienta Secrets no puede mantener privadas.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1120,"title":1121,"description":1122,"published":1123,"category":825,"image":1124,"draft":829},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups del plan gratuito de Supabase: cómo hacer uno sin terminal","No hay backups en el plan gratuito de Supabase: la copia tienes que hacerla tú. Cómo sacarla desde el panel y qué deja fuera la vía CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1126,"title":1127,"description":1128,"published":1129,"category":876,"image":1130,"draft":829},"\u002Fblog\u002Fis-supabase-secure","¿Supabase es seguro? Sí. Tu proyecto es otra pregunta","¿Supabase es seguro? La plataforma está auditada, cifrada y sometida a pentests. Su propia documentación dice dónde termina eso y empiezan tus ajustes.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1132,"title":1133,"description":1134,"published":1135,"category":876,"image":1136,"draft":829},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Dónde están tus claves API de Supabase: anon, service_role y URL","La URL del proyecto, la clave anon y la clave service_role están en una sola página del panel. Aquí tienes dónde está, y cuál de los cuatro va en tu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1138,"title":1139,"description":1140,"published":1141,"category":876,"image":1142,"draft":829},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy en Supabase. ¿Y ahora?","\"New row violates row-level security policy\" significa que Supabase rechazó una escritura. El arreglo rápido vuelve a abrir la tabla para cualquiera.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1144,"title":1145,"description":1146,"published":1147,"category":876,"image":1148,"draft":829},"\u002Fblog\u002Fcors-wildcard-security-risk","¿Es un comodín CORS un riesgo de seguridad? Casi nunca.","¿Es un comodín CORS un riesgo de seguridad? Casi siempre es el ajuste por defecto de tu builder y no entrega nada que tu servidor no diera ya a cualquiera.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1150,"title":1151,"description":1152,"published":1153,"category":825,"image":1154,"draft":829},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase branching no es un backup. Solo va hacia adelante.","Por qué el branching de Supabase no es un backup: una rama arranca sin tus datos y un merge solo mueve el esquema. Para qué sirve y qué usar en su lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":434,"title":1156,"description":1157,"published":1158,"category":825,"image":1159,"draft":829},"Cómo restaurar un backup de Supabase, y qué se rompe después","Cómo restaurar un backup de Supabase desde el panel o desde un archivo de volcado, qué reemplaza la restauración y por qué tu app puede seguir rota al terminar.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1161,"title":1162,"description":1163,"published":1164,"category":876,"image":1165,"draft":829},"\u002Fblog\u002Fsupabase-storage-bucket-public","Tu bucket de Supabase Storage es público. ¿Es un problema?","Un bucket público de Supabase Storage significa que quien tenga la URL de un archivo puede abrirlo. No significa que alguien pueda listar lo que hay dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1167,"title":1168,"description":1169,"published":1170,"category":876,"image":1171,"draft":829},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","¿Es un problema una clave de API de Google en tu frontend?","Una clave de API de Google en tu frontend es la clave que más encuentra nuestro escáner, y casi siempre no pasa nada. Un ajuste gratuito decide cuál es cuál.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1173,"title":1174,"description":1175,"published":1176,"category":825,"image":1177,"draft":829},"\u002Fblog\u002Fai-agent-deleted-my-database","Un agente de IA borró mis datos de Supabase. ¿Qué puedo recuperar?","Un agente de IA borró datos de tu base. Lo que puedes recuperar ya estaba decidido antes de que se ejecutara, y los próximos minutos deciden el resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1179,"title":1180,"description":1181,"published":1182,"category":876,"image":1183,"draft":829},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","¿Puede cualquiera leer tu base de datos Supabase? 3.680 apps","¿Puede cualquiera leer tu base de datos Supabase sin iniciar sesión? Escaneamos 30.998 apps activas hechas con builders de IA y medimos cuántas dicen que sí.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1185,"title":1186,"description":1187,"published":1182,"category":876,"image":1188,"draft":829},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expuestos: tu app está publicando su código original","Un source map expuesto deja que cualquiera lea el código original de tu app, comentarios incluidos. La comprobación de 30 segundos y lo que de verdad importa.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1190,"title":1191,"description":1192,"published":1193,"category":876,"image":1194,"draft":829},"\u002Fblog\u002Fsupabase-new-api-keys","Las nuevas claves de API de Supabase: ¿cuál va en tu app?","Supabase sustituyó anon y service_role por claves publicables y secretas. ¿Cuál pertenece a tu app y cuál no debe estar nunca?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1196,"title":1197,"description":1198,"published":1199,"category":825,"image":1200,"draft":829},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","¿Supabase respalda mi base de datos? Depende de tu plan.","¿Supabase respalda tu base de datos? A diario en los planes de pago, y nada en el gratuito. Cómo saber cuál tienes y qué es lo que esa copia no cubre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1202,"title":1203,"description":1204,"published":1205,"category":876,"image":1206,"draft":829},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security está activado. Tu tabla sigue pública.","Activar Supabase Row Level Security no protege una tabla. Lo hacen tus políticas, y la que arregló tu app rota puede dejar entrar a cualquiera.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1208,"title":1209,"description":1210,"published":1205,"category":825,"image":1211,"draft":829},"\u002Fblog\u002Fversion-history-is-not-a-backup","El historial de versiones no es un backup. No recupera una tabla.","Lovable y Bolt guardan un historial de versiones de tu código. Tu base de datos es un servicio aparte, y volver atrás no te devuelve tus datos.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1213,"title":1214,"description":1215,"published":1216,"category":825,"image":1217,"draft":829},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Tres formas de respaldar una base Supabase, y qué falta en cada una","El panel, pg_dump y un servicio gestionado. Qué guarda de verdad cada uno, qué deja fuera sin avisar y cuál sobrevive a perder la cuenta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1219,"title":1220,"description":1221,"published":1216,"category":876,"image":1222,"draft":829},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Qué claves de API son seguras en el navegador y cuáles no","Tu clave anon de Supabase está pensada para ser pública. Tu clave service_role no, y se salta todas las reglas que pongas. Cómo distinguirlas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791705962992]