[{"data":1,"prerenderedAt":31508},["ShallowReactive",2],{"blog-es-list":3},[4,3396,4412,5380,6398,7514,8777,11790,12756,13850,14951,15819,16743,17821,18380,19119,19810,20410,21772,22494,23047,23641,24196,25354,25908,26432,27077,27536,28330,29028,29762,30373,31049],{"id":5,"title":6,"author":7,"body":8,"category":3379,"cover":3380,"date":3381,"description":3382,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":3385,"navigation":411,"path":3386,"readingTime":3387,"seo":3388,"sitemap":3389,"stem":3390,"tags":3391,"__hash__":3395},"blog_es\u002Fes\u002Fblog\u002Fdeploy-cero-downtime-sin-kubernetes.md","Deploy cero-downtime sin Kubernetes: tutorial práctico en 2026","Equipo HeroCtl",{"type":9,"value":10,"toc":3354},"minimark",[11,15,18,23,39,42,56,59,63,66,88,91,95,102,105,108,111,115,118,205,208,211,213,217,220,223,275,286,289,314,317,339,346,350,357,367,372,916,920,1000,1004,1080,1094,1097,1101,1104,1140,1143,1208,1211,1236,1239,1243,1246,1249,1252,1266,1273,1363,1369,1372,1434,1440,1457,1460,1464,1467,2346,2357,2383,2386,2444,2447,2451,2454,2457,2506,2509,2520,2525,2533,2536,2538,2542,2545,2607,2611,2618,2624,2638,2710,2713,2727,2731,2734,2755,2758,2762,2765,2783,2786,2790,2793,2941,2944,2947,2968,2971,2975,3168,3171,3175,3223,3227,3232,3239,3244,3247,3252,3255,3260,3266,3271,3274,3279,3285,3290,3293,3298,3305,3307,3311,3314,3317,3333,3347,3350],[12,13,14],"p",{},"Hay un mito persistente de que el deploy cero-downtime es exclusividad de quien ejecutó Kubernetes en producción. No lo es. La técnica existe desde antes de que el coloso tuviera nombre — cualquier equipo que ejecutó un par de servidores físicos detrás de un balanceador en la década pasada ya hacía esto, con scripts de cincuenta líneas y ningún CRD en la vida. Lo que cambió fue el marketing alrededor de la práctica, no la práctica en sí.",[12,16,17],{},"Este post es un tutorial paso a paso para montar deploy sin downtime desde cero, en dos máquinas Linux, sin orquestador pesado, sin panel mágico. Al final vas a tener un script de bash que cambia una instancia por vez, espera a que la nueva esté saludable, y rota a la siguiente — exactamente el algoritmo que los orquestadores grandes implementan, solo que sin el boilerplate.",[19,20,22],"h2",{"id":21},"tldr","TL;DR",[12,24,25,26,30,31,34,35,38],{},"El deploy cero-downtime depende de tres ingredientes, no de una herramienta específica. Primero: ",[27,28,29],"strong",{},"dos o más instancias de la aplicación corriendo en paralelo",", detrás de un proxy básico. Segundo: ",[27,32,33],{},"un endpoint de health check confiable"," que valida dependencias reales (base, cache, cola), no solo responde 200 instantáneamente. Tercero: ",[27,36,37],{},"un script u orquestador que sustituya un contenedor por vez",", esperando a que el nuevo esté saludable antes de proseguir al siguiente.",[12,40,41],{},"Este tutorial monta el setup completo en dos VPS Linux con Docker, Caddy por delante como proxy + balanceador, y un script bash de cincuenta líneas que hace rolling update con health check activo, tiempo mínimo saludable, y rollback automático si falla. Resultado: deploy sin 5xx visible para el usuario, en menos de un minuto, sin ventana de mantenimiento.",[12,43,44,47,48,51,52,55],{},[27,45,46],{},"Prerequisitos:"," dos VPS Linux con Docker (Hetzner CPX11 a 5 € cada una), dominio con DNS controlable, app con health check decente. ",[27,49,50],{},"Tiempo de setup:"," dos a tres horas. ",[27,53,54],{},"Coste mensual:"," 10 € (12 € si quieres una tercera VPS dedicada al proxy). Al final mostramos la versión \"robusta\" vía HeroCtl para quien quiere parar de scriptear.",[57,58],"hr",{},[19,60,62],{"id":61},"los-tres-ingredientes-sin-esto-no-es-cero-downtime","Los tres ingredientes (sin esto, no es cero-downtime)",[12,64,65],{},"Antes de cualquier comando, vale la pena fijar la teoría — porque toda configuración más elaborada que vas a ver en internet es variación de estas tres piezas.",[67,68,69,76,82],"ol",{},[70,71,72,75],"li",{},[27,73,74],{},"Múltiples instancias de la app corriendo en paralelo."," Mínimo dos. Si solo tienes una, cualquier reinicio es ventana de error. No hay forma de evitar esto con truco de configuración.",[70,77,78,81],{},[27,79,80],{},"Un proxy\u002Fbalanceador por delante, haciendo health check."," El proxy decide a qué instancia mandar tráfico. Si una se cae (o fue retirada deliberadamente para el deploy), el proxy solo manda a las restantes.",[70,83,84,87],{},[27,85,86],{},"Un script que cambia instancias una por vez."," Nunca todas juntas. Espera a que la nueva esté saludable antes de tocar la siguiente. Si la nueva falla, para el deploy y mantiene las antiguas sirviendo.",[12,89,90],{},"Es solo eso. El resto — Kubernetes, paneles modernos, orquestadores ligeros — es embalaje alrededor de esos tres puntos.",[19,92,94],{"id":93},"por-que-single-server-nunca-es-cero-downtime-incluso-si-es-rapido","Por qué single-server NUNCA es cero-downtime (incluso si es rápido)",[12,96,97,98,101],{},"Veo esta pregunta toda semana en el Discord de la comunidad: \"¿puedo lograr cero-downtime con un solo servidor, si el deploy es lo suficientemente rápido?\". Respuesta corta: ",[27,99,100],{},"no",".",[12,103,104],{},"En una máquina única, el ciclo de deploy es: para el contenedor antiguo, sube el nuevo. Aunque todo suceda en tres segundos, esos tres segundos existen. Conexiones TCP en curso son cortadas. Peticiones que llegan en ese intervalo reciben connection refused o 502. Si tienes cinco requests por segundo, son quince usuarios viendo error en cada deploy.",[12,106,107],{},"Hay variación astuta — subir el nuevo en un puerto diferente, cambiar el proxy local, tirar el antiguo. Eso mejora, pero no elimina. Si la app tarda en cerrar conexiones en curso, el cutover aún genera errores. Si el health check es débil, el proxy apunta tráfico a app que aún no terminó de subir. Siempre hay una ventana.",[12,109,110],{},"La única forma confiable de eliminar la ventana es tener al menos una instancia siempre disponible durante todo el deploy. Eso exige dos máquinas. Punto.",[19,112,114],{"id":113},"el-setup-minimo-dos-vps-un-proxy","El setup mínimo (dos VPS + un proxy)",[12,116,117],{},"La topología más barata que entrega cero-downtime real:",[119,120,121,140],"table",{},[122,123,124],"thead",{},[125,126,127,131,134,137],"tr",{},[128,129,130],"th",{},"Componente",[128,132,133],{},"Tamaño",[128,135,136],{},"Coste",[128,138,139],{},"Función",[141,142,143,158,170,189],"tbody",{},[125,144,145,149,152,155],{},[146,147,148],"td",{},"VPS A",[146,150,151],{},"2 vCPU \u002F 2 GB RAM",[146,153,154],{},"5 €\u002Fmes",[146,156,157],{},"App instancia 1",[125,159,160,163,165,167],{},[146,161,162],{},"VPS B",[146,164,151],{},[146,166,154],{},[146,168,169],{},"App instancia 2",[125,171,172,175,183,186],{},[146,173,174],{},"Proxy",[146,176,177,178,182],{},"corriendo en VPS A ",[179,180,181],"em",{},"o"," tercera VPS",[146,184,185],{},"0 € (compartido) o 3 €\u002Fmes",[146,187,188],{},"Caddy\u002Fnginx haciendo balance",[125,190,191,194,199,202],{},[146,192,193],{},"Base",[146,195,196,197,182],{},"Postgres gestionado ",[179,198,181],{},[146,200,201],{},"varía",[146,203,204],{},"Estado compartido entre A y B",[12,206,207],{},"Tener el proxy compartido en una de las propias VPS economiza, pero tiene trade-off: si la VPS que hospeda el proxy se cae entera, el sitio se cae con ella (incluso con la otra VPS corriendo). Para equipo pequeño eso es aceptable. Cuando crezca, el proxy migra a VPS dedicada o se vuelve par redundante.",[12,209,210],{},"DNS A record de tu dominio apunta al IP del proxy. Apps en A y B se conectan a la misma base — sin esa parte compartida, las dos instancias divergen y el usuario ve resultado diferente dependiendo de cuál respondió.",[57,212],{},[19,214,216],{"id":215},"paso-1-provisionar-dos-vps-15-min","Paso 1 — Provisionar dos VPS (15 min)",[12,218,219],{},"Yo uso Hetzner CPX11 (€4,75) como referencia. DigitalOcean Droplet de US$6, Vultr Cloud Compute de US$6 o Linode Nanode de US$5 entregan algo parecido. Lo importante es Linux moderno (Ubuntu 24.04 LTS o Debian 12) con Docker.",[12,221,222],{},"Provisiona las dos máquinas con la misma clave SSH:",[224,225,230],"pre",{"className":226,"code":227,"language":228,"meta":229,"style":229},"language-bash shiki shiki-themes github-dark-default","# desde tu laptop\nssh-keygen -t ed25519 -f ~\u002F.ssh\u002Fdeploy_key -C \"deploy@meudominio.com\"\n# añade ~\u002F.ssh\u002Fdeploy_key.pub en la consola del proveedor antes de crear la VPS\n","bash","",[231,232,233,242,269],"code",{"__ignoreMap":229},[234,235,238],"span",{"class":236,"line":237},"line",1,[234,239,241],{"class":240},"sH3jZ","# desde tu laptop\n",[234,243,245,249,253,257,260,263,266],{"class":236,"line":244},2,[234,246,248],{"class":247},"sQhOw","ssh-keygen",[234,250,252],{"class":251},"sFSAA"," -t",[234,254,256],{"class":255},"s9uIt"," ed25519",[234,258,259],{"class":251}," -f",[234,261,262],{"class":255}," ~\u002F.ssh\u002Fdeploy_key",[234,264,265],{"class":251}," -C",[234,267,268],{"class":255}," \"deploy@meudominio.com\"\n",[234,270,272],{"class":236,"line":271},3,[234,273,274],{"class":240},"# añade ~\u002F.ssh\u002Fdeploy_key.pub en la consola del proveedor antes de crear la VPS\n",[12,276,277,278,281,282,285],{},"Crea cada VPS, anota los IPs. Voy a usar ",[231,279,280],{},"203.0.113.10"," (VPS A) y ",[231,283,284],{},"203.0.113.20"," (VPS B) como placeholders en el resto del post.",[12,287,288],{},"Instala Docker en cada una:",[224,290,292],{"className":226,"code":291,"language":228,"meta":229,"style":229},"ssh root@203.0.113.10 \"curl -fsSL https:\u002F\u002Fget.docker.com | sh\"\nssh root@203.0.113.20 \"curl -fsSL https:\u002F\u002Fget.docker.com | sh\"\n",[231,293,294,305],{"__ignoreMap":229},[234,295,296,299,302],{"class":236,"line":237},[234,297,298],{"class":247},"ssh",[234,300,301],{"class":255}," root@203.0.113.10",[234,303,304],{"class":255}," \"curl -fsSL https:\u002F\u002Fget.docker.com | sh\"\n",[234,306,307,309,312],{"class":236,"line":244},[234,308,298],{"class":247},[234,310,311],{"class":255}," root@203.0.113.20",[234,313,304],{"class":255},[12,315,316],{},"Configura firewall para permitir solo 22 (SSH) y 8080 (puerto interno donde la app va a escuchar). Tráfico HTTP\u002FHTTPS llega solo al proxy:",[224,318,320],{"className":226,"code":319,"language":228,"meta":229,"style":229},"ssh root@203.0.113.10 \"ufw allow 22 && ufw allow 8080\u002Ftcp && ufw --force enable\"\nssh root@203.0.113.20 \"ufw allow 22 && ufw allow 8080\u002Ftcp && ufw --force enable\"\n",[231,321,322,331],{"__ignoreMap":229},[234,323,324,326,328],{"class":236,"line":237},[234,325,298],{"class":247},[234,327,301],{"class":255},[234,329,330],{"class":255}," \"ufw allow 22 && ufw allow 8080\u002Ftcp && ufw --force enable\"\n",[234,332,333,335,337],{"class":236,"line":244},[234,334,298],{"class":247},[234,336,311],{"class":255},[234,338,330],{"class":255},[12,340,341,342,345],{},"Validación: ",[231,343,344],{},"docker run --rm hello-world"," en cada máquina debe completar sin error.",[19,347,349],{"id":348},"paso-2-app-con-health-check-decente-30-min","Paso 2 — App con health check decente (30 min)",[12,351,352,353,356],{},"El endpoint ",[231,354,355],{},"\u002Fhealthz"," es el corazón del esquema. Si retorna 200 cuando la app no está realmente lista, el proxy manda tráfico a la instancia rota y el usuario ve error. Si retorna 500 cuando la app está saludable, el proxy retira la instancia buena del balanceo. O sea: el health check es la fuente de verdad del sistema entero.",[12,358,359,360,362,363,366],{},"Regla de oro: el ",[231,361,355],{}," valida ",[27,364,365],{},"dependencias reales que la app necesita para responder",". Mínimo: conexión con la base. Si tienes cache (Redis), incluye. Si tienes cola (SQS, RabbitMQ), incluye. NO retornes 200 nada más arrancar — espera a que assets compilen, cache caliente, conexiones abran.",[368,369,371],"h3",{"id":370},"nodejs-express","Node.js (Express)",[224,373,377],{"className":374,"code":375,"language":376,"meta":229,"style":229},"language-js shiki shiki-themes github-dark-default","import express from \"express\"\nimport { Pool } from \"pg\"\n\nconst app = express()\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL })\n\nlet ready = false\n\n\u002F\u002F warm-up assíncrono — só fica ready quando dependencies validam\n;(async () => {\n  await pool.query(\"SELECT 1\")\n  \u002F\u002F outras inicializações: cache prime, etc.\n  ready = true\n})()\n\napp.get(\"\u002Fhealthz\", async (_req, res) => {\n  if (!ready) return res.status(503).send(\"warming up\")\n  try {\n    await pool.query(\"SELECT 1\")\n    res.status(200).send(\"ok\")\n  } catch (e) {\n    res.status(503).send(\"db down\")\n  }\n})\n\napp.get(\"\u002F\", (_req, res) => res.send(\"Hello v1\"))\n\nconst server = app.listen(8080, () => console.log(\"listening 8080\"))\n\n\u002F\u002F graceful shutdown — drena conexões antes de morrer\nprocess.on(\"SIGTERM\", () => {\n  ready = false  \u002F\u002F health check passa a falhar imediatamente\n  setTimeout(() => {\n    server.close(() => process.exit(0))\n  }, 5000)  \u002F\u002F 5s pro proxy notar e parar de mandar tráfego novo\n})\n","js",[231,378,379,395,407,413,432,457,462,477,482,488,506,527,533,544,550,555,592,633,641,657,681,693,715,721,727,732,769,774,813,818,824,844,857,870,896,911],{"__ignoreMap":229},[234,380,381,385,389,392],{"class":236,"line":237},[234,382,384],{"class":383},"suJrU","import",[234,386,388],{"class":387},"sZEs4"," express ",[234,390,391],{"class":383},"from",[234,393,394],{"class":255}," \"express\"\n",[234,396,397,399,402,404],{"class":236,"line":244},[234,398,384],{"class":383},[234,400,401],{"class":387}," { Pool } ",[234,403,391],{"class":383},[234,405,406],{"class":255}," \"pg\"\n",[234,408,409],{"class":236,"line":271},[234,410,412],{"emptyLinePlaceholder":411},true,"\n",[234,414,416,419,422,425,429],{"class":236,"line":415},4,[234,417,418],{"class":383},"const",[234,420,421],{"class":251}," app",[234,423,424],{"class":383}," =",[234,426,428],{"class":427},"sc3cj"," express",[234,430,431],{"class":387},"()\n",[234,433,435,437,440,442,445,448,451,454],{"class":236,"line":434},5,[234,436,418],{"class":383},[234,438,439],{"class":251}," pool",[234,441,424],{"class":383},[234,443,444],{"class":383}," new",[234,446,447],{"class":427}," Pool",[234,449,450],{"class":387},"({ connectionString: process.env.",[234,452,453],{"class":251},"DATABASE_URL",[234,455,456],{"class":387}," })\n",[234,458,460],{"class":236,"line":459},6,[234,461,412],{"emptyLinePlaceholder":411},[234,463,465,468,471,474],{"class":236,"line":464},7,[234,466,467],{"class":383},"let",[234,469,470],{"class":387}," ready ",[234,472,473],{"class":383},"=",[234,475,476],{"class":251}," false\n",[234,478,480],{"class":236,"line":479},8,[234,481,412],{"emptyLinePlaceholder":411},[234,483,485],{"class":236,"line":484},9,[234,486,487],{"class":240},"\u002F\u002F warm-up assíncrono — só fica ready quando dependencies validam\n",[234,489,491,494,497,500,503],{"class":236,"line":490},10,[234,492,493],{"class":387},";(",[234,495,496],{"class":383},"async",[234,498,499],{"class":387}," () ",[234,501,502],{"class":383},"=>",[234,504,505],{"class":387}," {\n",[234,507,509,512,515,518,521,524],{"class":236,"line":508},11,[234,510,511],{"class":383},"  await",[234,513,514],{"class":387}," pool.",[234,516,517],{"class":427},"query",[234,519,520],{"class":387},"(",[234,522,523],{"class":255},"\"SELECT 1\"",[234,525,526],{"class":387},")\n",[234,528,530],{"class":236,"line":529},12,[234,531,532],{"class":240},"  \u002F\u002F outras inicializações: cache prime, etc.\n",[234,534,536,539,541],{"class":236,"line":535},13,[234,537,538],{"class":387},"  ready ",[234,540,473],{"class":383},[234,542,543],{"class":251}," true\n",[234,545,547],{"class":236,"line":546},14,[234,548,549],{"class":387},"})()\n",[234,551,553],{"class":236,"line":552},15,[234,554,412],{"emptyLinePlaceholder":411},[234,556,558,561,564,566,569,572,574,577,580,582,585,588,590],{"class":236,"line":557},16,[234,559,560],{"class":387},"app.",[234,562,563],{"class":427},"get",[234,565,520],{"class":387},[234,567,568],{"class":255},"\"\u002Fhealthz\"",[234,570,571],{"class":387},", ",[234,573,496],{"class":383},[234,575,576],{"class":387}," (",[234,578,579],{"class":247},"_req",[234,581,571],{"class":387},[234,583,584],{"class":247},"res",[234,586,587],{"class":387},") ",[234,589,502],{"class":383},[234,591,505],{"class":387},[234,593,595,598,600,603,606,609,612,615,617,620,623,626,628,631],{"class":236,"line":594},17,[234,596,597],{"class":383},"  if",[234,599,576],{"class":387},[234,601,602],{"class":383},"!",[234,604,605],{"class":387},"ready) ",[234,607,608],{"class":383},"return",[234,610,611],{"class":387}," res.",[234,613,614],{"class":427},"status",[234,616,520],{"class":387},[234,618,619],{"class":251},"503",[234,621,622],{"class":387},").",[234,624,625],{"class":427},"send",[234,627,520],{"class":387},[234,629,630],{"class":255},"\"warming up\"",[234,632,526],{"class":387},[234,634,636,639],{"class":236,"line":635},18,[234,637,638],{"class":383},"  try",[234,640,505],{"class":387},[234,642,644,647,649,651,653,655],{"class":236,"line":643},19,[234,645,646],{"class":383},"    await",[234,648,514],{"class":387},[234,650,517],{"class":427},[234,652,520],{"class":387},[234,654,523],{"class":255},[234,656,526],{"class":387},[234,658,660,663,665,667,670,672,674,676,679],{"class":236,"line":659},20,[234,661,662],{"class":387},"    res.",[234,664,614],{"class":427},[234,666,520],{"class":387},[234,668,669],{"class":251},"200",[234,671,622],{"class":387},[234,673,625],{"class":427},[234,675,520],{"class":387},[234,677,678],{"class":255},"\"ok\"",[234,680,526],{"class":387},[234,682,684,687,690],{"class":236,"line":683},21,[234,685,686],{"class":387},"  } ",[234,688,689],{"class":383},"catch",[234,691,692],{"class":387}," (e) {\n",[234,694,696,698,700,702,704,706,708,710,713],{"class":236,"line":695},22,[234,697,662],{"class":387},[234,699,614],{"class":427},[234,701,520],{"class":387},[234,703,619],{"class":251},[234,705,622],{"class":387},[234,707,625],{"class":427},[234,709,520],{"class":387},[234,711,712],{"class":255},"\"db down\"",[234,714,526],{"class":387},[234,716,718],{"class":236,"line":717},23,[234,719,720],{"class":387},"  }\n",[234,722,724],{"class":236,"line":723},24,[234,725,726],{"class":387},"})\n",[234,728,730],{"class":236,"line":729},25,[234,731,412],{"emptyLinePlaceholder":411},[234,733,735,737,739,741,744,747,749,751,753,755,757,759,761,763,766],{"class":236,"line":734},26,[234,736,560],{"class":387},[234,738,563],{"class":427},[234,740,520],{"class":387},[234,742,743],{"class":255},"\"\u002F\"",[234,745,746],{"class":387},", (",[234,748,579],{"class":247},[234,750,571],{"class":387},[234,752,584],{"class":247},[234,754,587],{"class":387},[234,756,502],{"class":383},[234,758,611],{"class":387},[234,760,625],{"class":427},[234,762,520],{"class":387},[234,764,765],{"class":255},"\"Hello v1\"",[234,767,768],{"class":387},"))\n",[234,770,772],{"class":236,"line":771},27,[234,773,412],{"emptyLinePlaceholder":411},[234,775,777,779,782,784,787,790,792,795,798,800,803,806,808,811],{"class":236,"line":776},28,[234,778,418],{"class":383},[234,780,781],{"class":251}," server",[234,783,424],{"class":383},[234,785,786],{"class":387}," app.",[234,788,789],{"class":427},"listen",[234,791,520],{"class":387},[234,793,794],{"class":251},"8080",[234,796,797],{"class":387},", () ",[234,799,502],{"class":383},[234,801,802],{"class":387}," console.",[234,804,805],{"class":427},"log",[234,807,520],{"class":387},[234,809,810],{"class":255},"\"listening 8080\"",[234,812,768],{"class":387},[234,814,816],{"class":236,"line":815},29,[234,817,412],{"emptyLinePlaceholder":411},[234,819,821],{"class":236,"line":820},30,[234,822,823],{"class":240},"\u002F\u002F graceful shutdown — drena conexões antes de morrer\n",[234,825,827,830,833,835,838,840,842],{"class":236,"line":826},31,[234,828,829],{"class":387},"process.",[234,831,832],{"class":427},"on",[234,834,520],{"class":387},[234,836,837],{"class":255},"\"SIGTERM\"",[234,839,797],{"class":387},[234,841,502],{"class":383},[234,843,505],{"class":387},[234,845,847,849,851,854],{"class":236,"line":846},32,[234,848,538],{"class":387},[234,850,473],{"class":383},[234,852,853],{"class":251}," false",[234,855,856],{"class":240},"  \u002F\u002F health check passa a falhar imediatamente\n",[234,858,860,863,866,868],{"class":236,"line":859},33,[234,861,862],{"class":427},"  setTimeout",[234,864,865],{"class":387},"(() ",[234,867,502],{"class":383},[234,869,505],{"class":387},[234,871,873,876,879,881,883,886,889,891,894],{"class":236,"line":872},34,[234,874,875],{"class":387},"    server.",[234,877,878],{"class":427},"close",[234,880,865],{"class":387},[234,882,502],{"class":383},[234,884,885],{"class":387}," process.",[234,887,888],{"class":427},"exit",[234,890,520],{"class":387},[234,892,893],{"class":251},"0",[234,895,768],{"class":387},[234,897,899,902,905,908],{"class":236,"line":898},35,[234,900,901],{"class":387},"  }, ",[234,903,904],{"class":251},"5000",[234,906,907],{"class":387},")  ",[234,909,910],{"class":240},"\u002F\u002F 5s pro proxy notar e parar de mandar tráfego novo\n",[234,912,914],{"class":236,"line":913},36,[234,915,726],{"class":387},[368,917,919],{"id":918},"python-django-gunicorn","Python (Django + gunicorn)",[224,921,925],{"className":922,"code":923,"language":924,"meta":229,"style":229},"language-python shiki shiki-themes github-dark-default","# health\u002Fviews.py\nfrom django.db import connection\nfrom django.http import JsonResponse, HttpResponse\nimport redis, os\n\n_r = redis.from_url(os.environ[\"REDIS_URL\"])\n\ndef healthz(request):\n    try:\n        with connection.cursor() as c:\n            c.execute(\"SELECT 1\")\n        _r.ping()\n        return HttpResponse(\"ok\", status=200)\n    except Exception as e:\n        return HttpResponse(f\"unhealthy: {e}\", status=503)\n","python",[231,926,927,932,937,942,947,951,956,960,965,970,975,980,985,990,995],{"__ignoreMap":229},[234,928,929],{"class":236,"line":237},[234,930,931],{},"# health\u002Fviews.py\n",[234,933,934],{"class":236,"line":244},[234,935,936],{},"from django.db import connection\n",[234,938,939],{"class":236,"line":271},[234,940,941],{},"from django.http import JsonResponse, HttpResponse\n",[234,943,944],{"class":236,"line":415},[234,945,946],{},"import redis, os\n",[234,948,949],{"class":236,"line":434},[234,950,412],{"emptyLinePlaceholder":411},[234,952,953],{"class":236,"line":459},[234,954,955],{},"_r = redis.from_url(os.environ[\"REDIS_URL\"])\n",[234,957,958],{"class":236,"line":464},[234,959,412],{"emptyLinePlaceholder":411},[234,961,962],{"class":236,"line":479},[234,963,964],{},"def healthz(request):\n",[234,966,967],{"class":236,"line":484},[234,968,969],{},"    try:\n",[234,971,972],{"class":236,"line":490},[234,973,974],{},"        with connection.cursor() as c:\n",[234,976,977],{"class":236,"line":508},[234,978,979],{},"            c.execute(\"SELECT 1\")\n",[234,981,982],{"class":236,"line":529},[234,983,984],{},"        _r.ping()\n",[234,986,987],{"class":236,"line":535},[234,988,989],{},"        return HttpResponse(\"ok\", status=200)\n",[234,991,992],{"class":236,"line":546},[234,993,994],{},"    except Exception as e:\n",[234,996,997],{"class":236,"line":552},[234,998,999],{},"        return HttpResponse(f\"unhealthy: {e}\", status=503)\n",[368,1001,1003],{"id":1002},"ruby-rails","Ruby (Rails)",[224,1005,1009],{"className":1006,"code":1007,"language":1008,"meta":229,"style":229},"language-ruby shiki shiki-themes github-dark-default","# config\u002Froutes.rb\nget \"\u002Fhealthz\", to: \"health#show\"\n\n# app\u002Fcontrollers\u002Fhealth_controller.rb\nclass HealthController \u003C ApplicationController\n  def show\n    ActiveRecord::Base.connection.execute(\"SELECT 1\")\n    Rails.cache.read(\"__healthcheck__\")\n    head :ok\n  rescue => e\n    Rails.logger.warn(\"healthcheck failed: #{e.message}\")\n    head :service_unavailable\n  end\nend\n","ruby",[231,1010,1011,1016,1021,1025,1030,1035,1040,1045,1050,1055,1060,1065,1070,1075],{"__ignoreMap":229},[234,1012,1013],{"class":236,"line":237},[234,1014,1015],{},"# config\u002Froutes.rb\n",[234,1017,1018],{"class":236,"line":244},[234,1019,1020],{},"get \"\u002Fhealthz\", to: \"health#show\"\n",[234,1022,1023],{"class":236,"line":271},[234,1024,412],{"emptyLinePlaceholder":411},[234,1026,1027],{"class":236,"line":415},[234,1028,1029],{},"# app\u002Fcontrollers\u002Fhealth_controller.rb\n",[234,1031,1032],{"class":236,"line":434},[234,1033,1034],{},"class HealthController \u003C ApplicationController\n",[234,1036,1037],{"class":236,"line":459},[234,1038,1039],{},"  def show\n",[234,1041,1042],{"class":236,"line":464},[234,1043,1044],{},"    ActiveRecord::Base.connection.execute(\"SELECT 1\")\n",[234,1046,1047],{"class":236,"line":479},[234,1048,1049],{},"    Rails.cache.read(\"__healthcheck__\")\n",[234,1051,1052],{"class":236,"line":484},[234,1053,1054],{},"    head :ok\n",[234,1056,1057],{"class":236,"line":490},[234,1058,1059],{},"  rescue => e\n",[234,1061,1062],{"class":236,"line":508},[234,1063,1064],{},"    Rails.logger.warn(\"healthcheck failed: #{e.message}\")\n",[234,1066,1067],{"class":236,"line":529},[234,1068,1069],{},"    head :service_unavailable\n",[234,1071,1072],{"class":236,"line":535},[234,1073,1074],{},"  end\n",[234,1076,1077],{"class":236,"line":546},[234,1078,1079],{},"end\n",[12,1081,1082,1083,1086,1087,1090,1091,1093],{},"El detalle que diferencia health check amateur de profesional es el ",[27,1084,1085],{},"graceful shutdown",": al recibir ",[231,1088,1089],{},"SIGTERM",", la app pasa a retornar 503 en ",[231,1092,355],{}," inmediatamente, pero sigue aceptando conexiones en curso por algunos segundos más. El proxy nota el 503, deja de mandar tráfico nuevo, y cuando la app finalmente cierra ya no hay nadie esperando respuesta.",[12,1095,1096],{},"Sin esto, el cutover siempre filtra algunos errores incluso con todo lo demás correcto.",[19,1098,1100],{"id":1099},"paso-3-subir-dos-instancias-docker-15-min","Paso 3 — Subir dos instancias Docker (15 min)",[12,1102,1103],{},"Haz build de tu app en imagen Docker. Para el tutorial voy a usar una imagen genérica que sustituyes:",[224,1105,1107],{"className":226,"code":1106,"language":228,"meta":229,"style":229},"# en tu laptop, push al registry (Docker Hub, ECR, GHCR)\ndocker build -t meuusuario\u002Fmyapp:v1 .\ndocker push meuusuario\u002Fmyapp:v1\n",[231,1108,1109,1114,1130],{"__ignoreMap":229},[234,1110,1111],{"class":236,"line":237},[234,1112,1113],{"class":240},"# en tu laptop, push al registry (Docker Hub, ECR, GHCR)\n",[234,1115,1116,1119,1122,1124,1127],{"class":236,"line":244},[234,1117,1118],{"class":247},"docker",[234,1120,1121],{"class":255}," build",[234,1123,252],{"class":251},[234,1125,1126],{"class":255}," meuusuario\u002Fmyapp:v1",[234,1128,1129],{"class":255}," .\n",[234,1131,1132,1134,1137],{"class":236,"line":271},[234,1133,1118],{"class":247},[234,1135,1136],{"class":255}," push",[234,1138,1139],{"class":255}," meuusuario\u002Fmyapp:v1\n",[12,1141,1142],{},"Sube instancia en VPS A:",[224,1144,1146],{"className":226,"code":1145,"language":228,"meta":229,"style":229},"ssh root@203.0.113.10 \"\n  docker pull meuusuario\u002Fmyapp:v1 &&\n  docker run -d --name app --restart=unless-stopped \\\n    -p 8080:8080 \\\n    -e DATABASE_URL='postgres:\u002F\u002Fuser:pass@db.example.com:5432\u002Fapp' \\\n    --health-cmd='curl -f http:\u002F\u002Flocalhost:8080\u002Fhealthz || exit 1' \\\n    --health-interval=5s --health-timeout=2s --health-retries=3 \\\n    meuusuario\u002Fmyapp:v1\n\"\n",[231,1147,1148,1157,1162,1170,1177,1184,1191,1198,1203],{"__ignoreMap":229},[234,1149,1150,1152,1154],{"class":236,"line":237},[234,1151,298],{"class":247},[234,1153,301],{"class":255},[234,1155,1156],{"class":255}," \"\n",[234,1158,1159],{"class":236,"line":244},[234,1160,1161],{"class":255},"  docker pull meuusuario\u002Fmyapp:v1 &&\n",[234,1163,1164,1167],{"class":236,"line":271},[234,1165,1166],{"class":255},"  docker run -d --name app --restart=unless-stopped ",[234,1168,1169],{"class":383},"\\\n",[234,1171,1172,1175],{"class":236,"line":415},[234,1173,1174],{"class":255},"    -p 8080:8080 ",[234,1176,1169],{"class":383},[234,1178,1179,1182],{"class":236,"line":434},[234,1180,1181],{"class":255},"    -e DATABASE_URL='postgres:\u002F\u002Fuser:pass@db.example.com:5432\u002Fapp' ",[234,1183,1169],{"class":383},[234,1185,1186,1189],{"class":236,"line":459},[234,1187,1188],{"class":255},"    --health-cmd='curl -f http:\u002F\u002Flocalhost:8080\u002Fhealthz || exit 1' ",[234,1190,1169],{"class":383},[234,1192,1193,1196],{"class":236,"line":464},[234,1194,1195],{"class":255},"    --health-interval=5s --health-timeout=2s --health-retries=3 ",[234,1197,1169],{"class":383},[234,1199,1200],{"class":236,"line":479},[234,1201,1202],{"class":255},"    meuusuario\u002Fmyapp:v1\n",[234,1204,1205],{"class":236,"line":484},[234,1206,1207],{"class":255},"\"\n",[12,1209,1210],{},"Repite para VPS B cambiando el IP. Valida:",[224,1212,1214],{"className":226,"code":1213,"language":228,"meta":229,"style":229},"curl http:\u002F\u002F203.0.113.10:8080\u002Fhealthz   # debe retornar \"ok\"\ncurl http:\u002F\u002F203.0.113.20:8080\u002Fhealthz   # debe retornar \"ok\"\n",[231,1215,1216,1227],{"__ignoreMap":229},[234,1217,1218,1221,1224],{"class":236,"line":237},[234,1219,1220],{"class":247},"curl",[234,1222,1223],{"class":255}," http:\u002F\u002F203.0.113.10:8080\u002Fhealthz",[234,1225,1226],{"class":240},"   # debe retornar \"ok\"\n",[234,1228,1229,1231,1234],{"class":236,"line":244},[234,1230,1220],{"class":247},[234,1232,1233],{"class":255}," http:\u002F\u002F203.0.113.20:8080\u002Fhealthz",[234,1235,1226],{"class":240},[12,1237,1238],{},"Si las dos vuelven 200, la base está lista.",[19,1240,1242],{"id":1241},"paso-4-caddy-como-reverse-proxy-balanceador-30-min","Paso 4 — Caddy como reverse proxy + balanceador (30 min)",[12,1244,1245],{},"Caddy es más fácil de empezar que nginx por el TLS automático embebido — Let's Encrypt funciona out of the box, sin configurar bot externo. nginx es más flexible y tiene ecosistema mayor; Caddy es más simple para este caso. Para el tutorial voy con Caddy.",[12,1247,1248],{},"Voy a ejecutar Caddy en la VPS A, compartiendo la máquina con una de las instancias de la app. Si prefieres una tercera VPS dedicada, cambia el IP donde sea relevante.",[12,1250,1251],{},"Primero, libera puertos 80 y 443 en la VPS A:",[224,1253,1255],{"className":226,"code":1254,"language":228,"meta":229,"style":229},"ssh root@203.0.113.10 \"ufw allow 80 && ufw allow 443\"\n",[231,1256,1257],{"__ignoreMap":229},[234,1258,1259,1261,1263],{"class":236,"line":237},[234,1260,298],{"class":247},[234,1262,301],{"class":255},[234,1264,1265],{"class":255}," \"ufw allow 80 && ufw allow 443\"\n",[12,1267,1268,1269,1272],{},"Crea el ",[231,1270,1271],{},"Caddyfile",":",[224,1274,1278],{"className":1275,"code":1276,"language":1277,"meta":229,"style":229},"language-caddyfile shiki shiki-themes github-dark-default","meudominio.com {\n    reverse_proxy 203.0.113.10:8080 203.0.113.20:8080 {\n        lb_policy round_robin\n        health_uri \u002Fhealthz\n        health_interval 5s\n        health_timeout 2s\n        health_status 200\n\n        fail_duration 30s\n        max_fails 2\n        unhealthy_status 5xx\n\n        transport http {\n            dial_timeout 2s\n        }\n    }\n}\n","caddyfile",[231,1279,1280,1285,1290,1295,1300,1305,1310,1315,1319,1324,1329,1334,1338,1343,1348,1353,1358],{"__ignoreMap":229},[234,1281,1282],{"class":236,"line":237},[234,1283,1284],{},"meudominio.com {\n",[234,1286,1287],{"class":236,"line":244},[234,1288,1289],{},"    reverse_proxy 203.0.113.10:8080 203.0.113.20:8080 {\n",[234,1291,1292],{"class":236,"line":271},[234,1293,1294],{},"        lb_policy round_robin\n",[234,1296,1297],{"class":236,"line":415},[234,1298,1299],{},"        health_uri \u002Fhealthz\n",[234,1301,1302],{"class":236,"line":434},[234,1303,1304],{},"        health_interval 5s\n",[234,1306,1307],{"class":236,"line":459},[234,1308,1309],{},"        health_timeout 2s\n",[234,1311,1312],{"class":236,"line":464},[234,1313,1314],{},"        health_status 200\n",[234,1316,1317],{"class":236,"line":479},[234,1318,412],{"emptyLinePlaceholder":411},[234,1320,1321],{"class":236,"line":484},[234,1322,1323],{},"        fail_duration 30s\n",[234,1325,1326],{"class":236,"line":490},[234,1327,1328],{},"        max_fails 2\n",[234,1330,1331],{"class":236,"line":508},[234,1332,1333],{},"        unhealthy_status 5xx\n",[234,1335,1336],{"class":236,"line":529},[234,1337,412],{"emptyLinePlaceholder":411},[234,1339,1340],{"class":236,"line":535},[234,1341,1342],{},"        transport http {\n",[234,1344,1345],{"class":236,"line":546},[234,1346,1347],{},"            dial_timeout 2s\n",[234,1349,1350],{"class":236,"line":552},[234,1351,1352],{},"        }\n",[234,1354,1355],{"class":236,"line":557},[234,1356,1357],{},"    }\n",[234,1359,1360],{"class":236,"line":594},[234,1361,1362],{},"}\n",[12,1364,1365,1366,1368],{},"Quince líneas. Todo lo que importa está ahí: round-robin entre los dos IPs, health check activo cada cinco segundos en ",[231,1367,355],{},", marca como unhealthy después de dos fallos seguidos en 30s, timeout de dos segundos para abrir conexión.",[12,1370,1371],{},"Sube Caddy:",[224,1373,1375],{"className":226,"code":1374,"language":228,"meta":229,"style":229},"ssh root@203.0.113.10 \"\n  mkdir -p \u002Fetc\u002Fcaddy &&\n  docker run -d --name caddy --restart=unless-stopped \\\n    --network host \\\n    -v \u002Fetc\u002Fcaddy\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile \\\n    -v caddy_data:\u002Fdata \\\n    -v caddy_config:\u002Fconfig \\\n    caddy:2-alpine\n\"\n",[231,1376,1377,1385,1390,1397,1404,1411,1418,1425,1430],{"__ignoreMap":229},[234,1378,1379,1381,1383],{"class":236,"line":237},[234,1380,298],{"class":247},[234,1382,301],{"class":255},[234,1384,1156],{"class":255},[234,1386,1387],{"class":236,"line":244},[234,1388,1389],{"class":255},"  mkdir -p \u002Fetc\u002Fcaddy &&\n",[234,1391,1392,1395],{"class":236,"line":271},[234,1393,1394],{"class":255},"  docker run -d --name caddy --restart=unless-stopped ",[234,1396,1169],{"class":383},[234,1398,1399,1402],{"class":236,"line":415},[234,1400,1401],{"class":255},"    --network host ",[234,1403,1169],{"class":383},[234,1405,1406,1409],{"class":236,"line":434},[234,1407,1408],{"class":255},"    -v \u002Fetc\u002Fcaddy\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile ",[234,1410,1169],{"class":383},[234,1412,1413,1416],{"class":236,"line":459},[234,1414,1415],{"class":255},"    -v caddy_data:\u002Fdata ",[234,1417,1169],{"class":383},[234,1419,1420,1423],{"class":236,"line":464},[234,1421,1422],{"class":255},"    -v caddy_config:\u002Fconfig ",[234,1424,1169],{"class":383},[234,1426,1427],{"class":236,"line":479},[234,1428,1429],{"class":255},"    caddy:2-alpine\n",[234,1431,1432],{"class":236,"line":484},[234,1433,1207],{"class":255},[12,1435,1436,1437,1439],{},"Apunta el DNS A de tu dominio a ",[231,1438,280],{},". En unos minutos:",[224,1441,1443],{"className":226,"code":1442,"language":228,"meta":229,"style":229},"curl https:\u002F\u002Fmeudominio.com\u002F\n# debe retornar \"Hello v1\" (alternando entre las dos instancias)\n",[231,1444,1445,1452],{"__ignoreMap":229},[234,1446,1447,1449],{"class":236,"line":237},[234,1448,1220],{"class":247},[234,1450,1451],{"class":255}," https:\u002F\u002Fmeudominio.com\u002F\n",[234,1453,1454],{"class":236,"line":244},[234,1455,1456],{"class":240},"# debe retornar \"Hello v1\" (alternando entre las dos instancias)\n",[12,1458,1459],{},"Caddy emitió certificado Let's Encrypt automáticamente. Eso funciona porque el dominio resuelve al IP donde Caddy está escuchando en el puerto 80 (challenge HTTP-01).",[19,1461,1463],{"id":1462},"paso-5-script-bash-de-deploy-60-min","Paso 5 — Script bash de deploy (60 min)",[12,1465,1466],{},"Este es el corazón del tutorial. Un script que orquesta rolling update entre las dos VPS:",[224,1468,1470],{"className":226,"code":1469,"language":228,"meta":229,"style":229},"#!\u002Fusr\u002Fbin\u002Fenv bash\n# deploy.sh — rolling deploy zero-downtime entre duas VPS\nset -euo pipefail\n\nIMAGE=\"${1:?Uso: .\u002Fdeploy.sh meuusuario\u002Fmyapp:v2}\"\nHOSTS=(\"203.0.113.10\" \"203.0.113.20\")\nHEALTH_DEADLINE=300   # max segundos esperando health check\nMIN_HEALTHY_TIME=10   # segundos saudável sustentado antes de prosseguir\nSSH_OPTS=\"-o StrictHostKeyChecking=no -o ConnectTimeout=5\"\n\ndeploy_host() {\n  local host=$1\n  local image=$2\n  echo \"==> [${host}] pulling ${image}\"\n  ssh ${SSH_OPTS} \"root@${host}\" \"docker pull ${image}\"\n\n  # guarda imagem antiga pro caso de rollback\n  local old_image\n  old_image=$(ssh ${SSH_OPTS} \"root@${host}\" \"docker inspect app --format '{{.Config.Image}}' 2>\u002Fdev\u002Fnull || echo none\")\n  echo \"==> [${host}] versão atual: ${old_image}\"\n\n  echo \"==> [${host}] substituindo contêiner\"\n  ssh ${SSH_OPTS} \"root@${host}\" \"\n    docker stop app 2>\u002Fdev\u002Fnull || true\n    docker rm app 2>\u002Fdev\u002Fnull || true\n    docker run -d --name app --restart=unless-stopped \\\n      -p 8080:8080 \\\n      -e DATABASE_URL='${DATABASE_URL}' \\\n      --health-cmd='curl -f http:\u002F\u002Flocalhost:8080\u002Fhealthz || exit 1' \\\n      --health-interval=5s --health-timeout=2s --health-retries=3 \\\n      ${image}\n  \"\n\n  echo \"==> [${host}] esperando health check (max ${HEALTH_DEADLINE}s)\"\n  local start=$(date +%s)\n  local healthy_since=0\n  while true; do\n    local now=$(date +%s)\n    if (( now - start > HEALTH_DEADLINE )); then\n      echo \"!!  [${host}] healthy_deadline excedido — fazendo rollback pra ${old_image}\"\n      ssh ${SSH_OPTS} \"root@${host}\" \"\n        docker stop app && docker rm app &&\n        docker run -d --name app --restart=unless-stopped \\\n          -p 8080:8080 -e DATABASE_URL='${DATABASE_URL}' \\\n          ${old_image}\n      \"\n      return 1\n    fi\n\n    if curl -sf --max-time 2 \"http:\u002F\u002F${host}:8080\u002Fhealthz\" > \u002Fdev\u002Fnull; then\n      if (( healthy_since == 0 )); then\n        healthy_since=${now}\n        echo \"    [${host}] saudável — confirmando por ${MIN_HEALTHY_TIME}s\"\n      elif (( now - healthy_since >= MIN_HEALTHY_TIME )); then\n        echo \"==> [${host}] saudável sustentado — promovendo\"\n        return 0\n      fi\n    else\n      healthy_since=0\n    fi\n    sleep 2\n  done\n}\n\necho \"### Deploy ${IMAGE} em ${#HOSTS[@]} hosts (rolling, max_parallel=1)\"\nfor host in \"${HOSTS[@]}\"; do\n  if ! deploy_host \"${host}\" \"${IMAGE}\"; then\n    echo \"### Deploy abortado em ${host}. Hosts anteriores mantidos como estavam.\"\n    exit 1\n  fi\ndone\necho \"### Deploy completo: todos os hosts em ${IMAGE}\"\n",[231,1471,1472,1477,1482,1493,1497,1550,1567,1580,1593,1603,1607,1615,1628,1640,1660,1683,1687,1692,1699,1724,1740,1744,1755,1769,1774,1779,1786,1793,1805,1812,1819,1828,1833,1837,1853,1872,1884,1899,1918,1942,1960,1976,1982,1990,2002,2012,2018,2027,2033,2038,2073,2093,2104,2123,2144,2156,2165,2171,2177,2187,2192,2201,2207,2212,2217,2245,2273,2300,2314,2322,2328,2334],{"__ignoreMap":229},[234,1473,1474],{"class":236,"line":237},[234,1475,1476],{"class":240},"#!\u002Fusr\u002Fbin\u002Fenv bash\n",[234,1478,1479],{"class":236,"line":244},[234,1480,1481],{"class":240},"# deploy.sh — rolling deploy zero-downtime entre duas VPS\n",[234,1483,1484,1487,1490],{"class":236,"line":271},[234,1485,1486],{"class":251},"set",[234,1488,1489],{"class":251}," -euo",[234,1491,1492],{"class":255}," pipefail\n",[234,1494,1495],{"class":236,"line":415},[234,1496,412],{"emptyLinePlaceholder":411},[234,1498,1499,1502,1504,1507,1510,1513,1516,1518,1521,1524,1527,1529,1532,1535,1537,1540,1542,1545,1548],{"class":236,"line":434},[234,1500,1501],{"class":387},"IMAGE",[234,1503,473],{"class":383},[234,1505,1506],{"class":255},"\"",[234,1508,1509],{"class":251},"${1",[234,1511,1512],{"class":383},":?",[234,1514,1515],{"class":387},"Uso",[234,1517,1272],{"class":383},[234,1519,1520],{"class":255}," .",[234,1522,1523],{"class":383},"\u002F",[234,1525,1526],{"class":387},"deploy",[234,1528,101],{"class":255},[234,1530,1531],{"class":387},"sh",[234,1533,1534],{"class":387}," meuusuario",[234,1536,1523],{"class":383},[234,1538,1539],{"class":387},"myapp",[234,1541,1272],{"class":383},[234,1543,1544],{"class":387},"v2",[234,1546,1547],{"class":251},"}",[234,1549,1207],{"class":255},[234,1551,1552,1555,1557,1559,1562,1565],{"class":236,"line":459},[234,1553,1554],{"class":387},"HOSTS",[234,1556,473],{"class":383},[234,1558,520],{"class":387},[234,1560,1561],{"class":255},"\"203.0.113.10\"",[234,1563,1564],{"class":255}," \"203.0.113.20\"",[234,1566,526],{"class":387},[234,1568,1569,1572,1574,1577],{"class":236,"line":464},[234,1570,1571],{"class":387},"HEALTH_DEADLINE",[234,1573,473],{"class":383},[234,1575,1576],{"class":255},"300",[234,1578,1579],{"class":240},"   # max segundos esperando health check\n",[234,1581,1582,1585,1587,1590],{"class":236,"line":479},[234,1583,1584],{"class":387},"MIN_HEALTHY_TIME",[234,1586,473],{"class":383},[234,1588,1589],{"class":255},"10",[234,1591,1592],{"class":240},"   # segundos saudável sustentado antes de prosseguir\n",[234,1594,1595,1598,1600],{"class":236,"line":484},[234,1596,1597],{"class":387},"SSH_OPTS",[234,1599,473],{"class":383},[234,1601,1602],{"class":255},"\"-o StrictHostKeyChecking=no -o ConnectTimeout=5\"\n",[234,1604,1605],{"class":236,"line":490},[234,1606,412],{"emptyLinePlaceholder":411},[234,1608,1609,1612],{"class":236,"line":508},[234,1610,1611],{"class":427},"deploy_host",[234,1613,1614],{"class":387},"() {\n",[234,1616,1617,1620,1623,1625],{"class":236,"line":529},[234,1618,1619],{"class":383},"  local",[234,1621,1622],{"class":387}," host",[234,1624,473],{"class":383},[234,1626,1627],{"class":247},"$1\n",[234,1629,1630,1632,1635,1637],{"class":236,"line":535},[234,1631,1619],{"class":383},[234,1633,1634],{"class":387}," image",[234,1636,473],{"class":383},[234,1638,1639],{"class":247},"$2\n",[234,1641,1642,1645,1648,1651,1654,1657],{"class":236,"line":546},[234,1643,1644],{"class":251},"  echo",[234,1646,1647],{"class":255}," \"==> [${",[234,1649,1650],{"class":387},"host",[234,1652,1653],{"class":255},"}] pulling ${",[234,1655,1656],{"class":387},"image",[234,1658,1659],{"class":255},"}\"\n",[234,1661,1662,1665,1668,1671,1673,1676,1679,1681],{"class":236,"line":552},[234,1663,1664],{"class":247},"  ssh",[234,1666,1667],{"class":387}," ${SSH_OPTS} ",[234,1669,1670],{"class":255},"\"root@${",[234,1672,1650],{"class":387},[234,1674,1675],{"class":255},"}\"",[234,1677,1678],{"class":255}," \"docker pull ${",[234,1680,1656],{"class":387},[234,1682,1659],{"class":255},[234,1684,1685],{"class":236,"line":557},[234,1686,412],{"emptyLinePlaceholder":411},[234,1688,1689],{"class":236,"line":594},[234,1690,1691],{"class":240},"  # guarda imagem antiga pro caso de rollback\n",[234,1693,1694,1696],{"class":236,"line":635},[234,1695,1619],{"class":383},[234,1697,1698],{"class":387}," old_image\n",[234,1700,1701,1704,1706,1709,1711,1713,1715,1717,1719,1722],{"class":236,"line":643},[234,1702,1703],{"class":387},"  old_image",[234,1705,473],{"class":383},[234,1707,1708],{"class":387},"$(",[234,1710,298],{"class":247},[234,1712,1667],{"class":387},[234,1714,1670],{"class":255},[234,1716,1650],{"class":387},[234,1718,1675],{"class":255},[234,1720,1721],{"class":255}," \"docker inspect app --format '{{.Config.Image}}' 2>\u002Fdev\u002Fnull || echo none\"",[234,1723,526],{"class":387},[234,1725,1726,1728,1730,1732,1735,1738],{"class":236,"line":659},[234,1727,1644],{"class":251},[234,1729,1647],{"class":255},[234,1731,1650],{"class":387},[234,1733,1734],{"class":255},"}] versão atual: ${",[234,1736,1737],{"class":387},"old_image",[234,1739,1659],{"class":255},[234,1741,1742],{"class":236,"line":683},[234,1743,412],{"emptyLinePlaceholder":411},[234,1745,1746,1748,1750,1752],{"class":236,"line":695},[234,1747,1644],{"class":251},[234,1749,1647],{"class":255},[234,1751,1650],{"class":387},[234,1753,1754],{"class":255},"}] substituindo contêiner\"\n",[234,1756,1757,1759,1761,1763,1765,1767],{"class":236,"line":717},[234,1758,1664],{"class":247},[234,1760,1667],{"class":387},[234,1762,1670],{"class":255},[234,1764,1650],{"class":387},[234,1766,1675],{"class":255},[234,1768,1156],{"class":255},[234,1770,1771],{"class":236,"line":723},[234,1772,1773],{"class":255},"    docker stop app 2>\u002Fdev\u002Fnull || true\n",[234,1775,1776],{"class":236,"line":729},[234,1777,1778],{"class":255},"    docker rm app 2>\u002Fdev\u002Fnull || true\n",[234,1780,1781,1784],{"class":236,"line":734},[234,1782,1783],{"class":255},"    docker run -d --name app --restart=unless-stopped ",[234,1785,1169],{"class":383},[234,1787,1788,1791],{"class":236,"line":771},[234,1789,1790],{"class":255},"      -p 8080:8080 ",[234,1792,1169],{"class":383},[234,1794,1795,1798,1800,1803],{"class":236,"line":776},[234,1796,1797],{"class":255},"      -e DATABASE_URL='${",[234,1799,453],{"class":387},[234,1801,1802],{"class":255},"}' ",[234,1804,1169],{"class":383},[234,1806,1807,1810],{"class":236,"line":815},[234,1808,1809],{"class":255},"      --health-cmd='curl -f http:\u002F\u002Flocalhost:8080\u002Fhealthz || exit 1' ",[234,1811,1169],{"class":383},[234,1813,1814,1817],{"class":236,"line":820},[234,1815,1816],{"class":255},"      --health-interval=5s --health-timeout=2s --health-retries=3 ",[234,1818,1169],{"class":383},[234,1820,1821,1824,1826],{"class":236,"line":826},[234,1822,1823],{"class":255},"      ${",[234,1825,1656],{"class":387},[234,1827,1362],{"class":255},[234,1829,1830],{"class":236,"line":846},[234,1831,1832],{"class":255},"  \"\n",[234,1834,1835],{"class":236,"line":859},[234,1836,412],{"emptyLinePlaceholder":411},[234,1838,1839,1841,1843,1845,1848,1850],{"class":236,"line":872},[234,1840,1644],{"class":251},[234,1842,1647],{"class":255},[234,1844,1650],{"class":387},[234,1846,1847],{"class":255},"}] esperando health check (max ${",[234,1849,1571],{"class":387},[234,1851,1852],{"class":255},"}s)\"\n",[234,1854,1855,1857,1860,1862,1864,1867,1870],{"class":236,"line":898},[234,1856,1619],{"class":383},[234,1858,1859],{"class":387}," start",[234,1861,473],{"class":383},[234,1863,1708],{"class":387},[234,1865,1866],{"class":247},"date",[234,1868,1869],{"class":255}," +%s",[234,1871,526],{"class":387},[234,1873,1874,1876,1879,1881],{"class":236,"line":913},[234,1875,1619],{"class":383},[234,1877,1878],{"class":387}," healthy_since",[234,1880,473],{"class":383},[234,1882,1883],{"class":251},"0\n",[234,1885,1887,1890,1893,1896],{"class":236,"line":1886},37,[234,1888,1889],{"class":383},"  while",[234,1891,1892],{"class":251}," true",[234,1894,1895],{"class":387},"; ",[234,1897,1898],{"class":383},"do\n",[234,1900,1902,1905,1908,1910,1912,1914,1916],{"class":236,"line":1901},38,[234,1903,1904],{"class":383},"    local",[234,1906,1907],{"class":387}," now",[234,1909,473],{"class":383},[234,1911,1708],{"class":387},[234,1913,1866],{"class":247},[234,1915,1869],{"class":255},[234,1917,526],{"class":387},[234,1919,1921,1924,1927,1930,1933,1936,1939],{"class":236,"line":1920},39,[234,1922,1923],{"class":383},"    if",[234,1925,1926],{"class":387}," (( now ",[234,1928,1929],{"class":383},"-",[234,1931,1932],{"class":387}," start ",[234,1934,1935],{"class":383},">",[234,1937,1938],{"class":387}," HEALTH_DEADLINE )); ",[234,1940,1941],{"class":383},"then\n",[234,1943,1945,1948,1951,1953,1956,1958],{"class":236,"line":1944},40,[234,1946,1947],{"class":251},"      echo",[234,1949,1950],{"class":255}," \"!!  [${",[234,1952,1650],{"class":387},[234,1954,1955],{"class":255},"}] healthy_deadline excedido — fazendo rollback pra ${",[234,1957,1737],{"class":387},[234,1959,1659],{"class":255},[234,1961,1963,1966,1968,1970,1972,1974],{"class":236,"line":1962},41,[234,1964,1965],{"class":247},"      ssh",[234,1967,1667],{"class":387},[234,1969,1670],{"class":255},[234,1971,1650],{"class":387},[234,1973,1675],{"class":255},[234,1975,1156],{"class":255},[234,1977,1979],{"class":236,"line":1978},42,[234,1980,1981],{"class":255},"        docker stop app && docker rm app &&\n",[234,1983,1985,1988],{"class":236,"line":1984},43,[234,1986,1987],{"class":255},"        docker run -d --name app --restart=unless-stopped ",[234,1989,1169],{"class":383},[234,1991,1993,1996,1998,2000],{"class":236,"line":1992},44,[234,1994,1995],{"class":255},"          -p 8080:8080 -e DATABASE_URL='${",[234,1997,453],{"class":387},[234,1999,1802],{"class":255},[234,2001,1169],{"class":383},[234,2003,2005,2008,2010],{"class":236,"line":2004},45,[234,2006,2007],{"class":255},"          ${",[234,2009,1737],{"class":387},[234,2011,1362],{"class":255},[234,2013,2015],{"class":236,"line":2014},46,[234,2016,2017],{"class":255},"      \"\n",[234,2019,2021,2024],{"class":236,"line":2020},47,[234,2022,2023],{"class":383},"      return",[234,2025,2026],{"class":251}," 1\n",[234,2028,2030],{"class":236,"line":2029},48,[234,2031,2032],{"class":383},"    fi\n",[234,2034,2036],{"class":236,"line":2035},49,[234,2037,412],{"emptyLinePlaceholder":411},[234,2039,2041,2043,2046,2049,2052,2055,2058,2060,2063,2066,2069,2071],{"class":236,"line":2040},50,[234,2042,1923],{"class":383},[234,2044,2045],{"class":247}," curl",[234,2047,2048],{"class":251}," -sf",[234,2050,2051],{"class":251}," --max-time",[234,2053,2054],{"class":251}," 2",[234,2056,2057],{"class":255}," \"http:\u002F\u002F${",[234,2059,1650],{"class":387},[234,2061,2062],{"class":255},"}:8080\u002Fhealthz\"",[234,2064,2065],{"class":383}," >",[234,2067,2068],{"class":255}," \u002Fdev\u002Fnull",[234,2070,1895],{"class":387},[234,2072,1941],{"class":383},[234,2074,2076,2079,2082,2085,2088,2091],{"class":236,"line":2075},51,[234,2077,2078],{"class":383},"      if",[234,2080,2081],{"class":387}," (( healthy_since ",[234,2083,2084],{"class":383},"==",[234,2086,2087],{"class":251}," 0",[234,2089,2090],{"class":387}," )); ",[234,2092,1941],{"class":383},[234,2094,2096,2099,2101],{"class":236,"line":2095},52,[234,2097,2098],{"class":387},"        healthy_since",[234,2100,473],{"class":383},[234,2102,2103],{"class":387},"${now}\n",[234,2105,2107,2110,2113,2115,2118,2120],{"class":236,"line":2106},53,[234,2108,2109],{"class":251},"        echo",[234,2111,2112],{"class":255}," \"    [${",[234,2114,1650],{"class":387},[234,2116,2117],{"class":255},"}] saudável — confirmando por ${",[234,2119,1584],{"class":387},[234,2121,2122],{"class":255},"}s\"\n",[234,2124,2126,2129,2131,2133,2136,2139,2142],{"class":236,"line":2125},54,[234,2127,2128],{"class":383},"      elif",[234,2130,1926],{"class":387},[234,2132,1929],{"class":383},[234,2134,2135],{"class":387}," healthy_since ",[234,2137,2138],{"class":383},">=",[234,2140,2141],{"class":387}," MIN_HEALTHY_TIME )); ",[234,2143,1941],{"class":383},[234,2145,2147,2149,2151,2153],{"class":236,"line":2146},55,[234,2148,2109],{"class":251},[234,2150,1647],{"class":255},[234,2152,1650],{"class":387},[234,2154,2155],{"class":255},"}] saudável sustentado — promovendo\"\n",[234,2157,2159,2162],{"class":236,"line":2158},56,[234,2160,2161],{"class":383},"        return",[234,2163,2164],{"class":251}," 0\n",[234,2166,2168],{"class":236,"line":2167},57,[234,2169,2170],{"class":383},"      fi\n",[234,2172,2174],{"class":236,"line":2173},58,[234,2175,2176],{"class":383},"    else\n",[234,2178,2180,2183,2185],{"class":236,"line":2179},59,[234,2181,2182],{"class":387},"      healthy_since",[234,2184,473],{"class":383},[234,2186,1883],{"class":255},[234,2188,2190],{"class":236,"line":2189},60,[234,2191,2032],{"class":383},[234,2193,2195,2198],{"class":236,"line":2194},61,[234,2196,2197],{"class":247},"    sleep",[234,2199,2200],{"class":251}," 2\n",[234,2202,2204],{"class":236,"line":2203},62,[234,2205,2206],{"class":383},"  done\n",[234,2208,2210],{"class":236,"line":2209},63,[234,2211,1362],{"class":387},[234,2213,2215],{"class":236,"line":2214},64,[234,2216,412],{"emptyLinePlaceholder":411},[234,2218,2220,2223,2226,2228,2231,2234,2236,2239,2242],{"class":236,"line":2219},65,[234,2221,2222],{"class":251},"echo",[234,2224,2225],{"class":255}," \"### Deploy ${",[234,2227,1501],{"class":387},[234,2229,2230],{"class":255},"} em ${",[234,2232,2233],{"class":383},"#",[234,2235,1554],{"class":387},[234,2237,2238],{"class":255},"[",[234,2240,2241],{"class":383},"@",[234,2243,2244],{"class":255},"]} hosts (rolling, max_parallel=1)\"\n",[234,2246,2248,2251,2254,2257,2260,2262,2264,2266,2269,2271],{"class":236,"line":2247},66,[234,2249,2250],{"class":383},"for",[234,2252,2253],{"class":387}," host ",[234,2255,2256],{"class":383},"in",[234,2258,2259],{"class":255}," \"${",[234,2261,1554],{"class":387},[234,2263,2238],{"class":255},[234,2265,2241],{"class":383},[234,2267,2268],{"class":255},"]}\"",[234,2270,1895],{"class":387},[234,2272,1898],{"class":383},[234,2274,2276,2278,2281,2284,2286,2288,2290,2292,2294,2296,2298],{"class":236,"line":2275},67,[234,2277,597],{"class":383},[234,2279,2280],{"class":383}," !",[234,2282,2283],{"class":247}," deploy_host",[234,2285,2259],{"class":255},[234,2287,1650],{"class":387},[234,2289,1675],{"class":255},[234,2291,2259],{"class":255},[234,2293,1501],{"class":387},[234,2295,1675],{"class":255},[234,2297,1895],{"class":387},[234,2299,1941],{"class":383},[234,2301,2303,2306,2309,2311],{"class":236,"line":2302},68,[234,2304,2305],{"class":251},"    echo",[234,2307,2308],{"class":255}," \"### Deploy abortado em ${",[234,2310,1650],{"class":387},[234,2312,2313],{"class":255},"}. Hosts anteriores mantidos como estavam.\"\n",[234,2315,2317,2320],{"class":236,"line":2316},69,[234,2318,2319],{"class":251},"    exit",[234,2321,2026],{"class":251},[234,2323,2325],{"class":236,"line":2324},70,[234,2326,2327],{"class":383},"  fi\n",[234,2329,2331],{"class":236,"line":2330},71,[234,2332,2333],{"class":383},"done\n",[234,2335,2337,2339,2342,2344],{"class":236,"line":2336},72,[234,2338,2222],{"class":251},[234,2340,2341],{"class":255}," \"### Deploy completo: todos os hosts em ${",[234,2343,1501],{"class":387},[234,2345,1659],{"class":255},[12,2347,2348,2349,2352,2353,2356],{},"Guarda como ",[231,2350,2351],{},"deploy.sh",", dale ",[231,2354,2355],{},"chmod +x",", y:",[224,2358,2360],{"className":226,"code":2359,"language":228,"meta":229,"style":229},"export DATABASE_URL='postgres:\u002F\u002Fuser:pass@db.example.com:5432\u002Fapp'\n.\u002Fdeploy.sh meuusuario\u002Fmyapp:v2\n",[231,2361,2362,2375],{"__ignoreMap":229},[234,2363,2364,2367,2370,2372],{"class":236,"line":237},[234,2365,2366],{"class":383},"export",[234,2368,2369],{"class":387}," DATABASE_URL",[234,2371,473],{"class":383},[234,2373,2374],{"class":255},"'postgres:\u002F\u002Fuser:pass@db.example.com:5432\u002Fapp'\n",[234,2376,2377,2380],{"class":236,"line":244},[234,2378,2379],{"class":247},".\u002Fdeploy.sh",[234,2381,2382],{"class":255}," meuusuario\u002Fmyapp:v2\n",[12,2384,2385],{},"El algoritmo es literalmente lo que los orquestadores grandes hacen internamente:",[67,2387,2388,2394,2408,2414,2419,2425,2438],{},[70,2389,2390,2393],{},[27,2391,2392],{},"Para cada host, secuencialmente"," (max_parallel = 1)",[70,2395,2396,2399,2400,2403,2404,2407],{},[27,2397,2398],{},"Pull de la nueva imagen"," antes de tocar el contenedor — así el downtime entre ",[231,2401,2402],{},"docker stop"," y ",[231,2405,2406],{},"docker run"," es mínimo",[70,2409,2410,2413],{},[27,2411,2412],{},"Guarda referencia de la imagen antigua"," para rollback si algo sale mal",[70,2415,2416],{},[27,2417,2418],{},"Sustituye el contenedor",[70,2420,2421,2424],{},[27,2422,2423],{},"Loop esperando health check"," con deadline de cinco minutos",[70,2426,2427,2430,2431,2433,2434,2437],{},[27,2428,2429],{},"Min healthy time de diez segundos",": solo avanza cuando ",[231,2432,355],{}," retornó 200 ",[179,2435,2436],{},"sostenidamente"," por diez segundos (si cae en el medio, reinicia el conteo)",[70,2439,2440,2443],{},[27,2441,2442],{},"Rollback automático"," si pasa del deadline",[12,2445,2446],{},"Los números (max_parallel: 1, min_healthy_time: 10s, healthy_deadline: 300s) son exactamente los defaults que usamos en HeroCtl. No es coincidencia — son los valores que sobrevivieron a años de prueba y error. Min healthy time muy corto detecta síntomas transitorios como \"saludable\" y rompe; muy largo deja el deploy lento sin ganancia. Diez segundos es el punto donde ruido desaparece y el deploy aún termina rápido.",[19,2448,2450],{"id":2449},"paso-6-validar-con-test-de-carga-durante-deploy-15-min","Paso 6 — Validar con test de carga durante deploy (15 min)",[12,2452,2453],{},"Esta es la prueba de fuego: ejecutar carga sostenida y hacer deploy al mismo tiempo. Si algún 5xx aparece, alguna parte del esquema está rota.",[12,2455,2456],{},"En una máquina externa (tu laptop u otra VPS):",[224,2458,2460],{"className":226,"code":2459,"language":228,"meta":229,"style":229},"# instala hey\ngo install github.com\u002Frakyll\u002Fhey@latest\n\n# carga sustentada de 60s, 5 conexões concorrentes\nhey -z 60s -c 5 https:\u002F\u002Fmeudominio.com\u002F\n",[231,2461,2462,2467,2478,2482,2487],{"__ignoreMap":229},[234,2463,2464],{"class":236,"line":237},[234,2465,2466],{"class":240},"# instala hey\n",[234,2468,2469,2472,2475],{"class":236,"line":244},[234,2470,2471],{"class":247},"go",[234,2473,2474],{"class":255}," install",[234,2476,2477],{"class":255}," github.com\u002Frakyll\u002Fhey@latest\n",[234,2479,2480],{"class":236,"line":271},[234,2481,412],{"emptyLinePlaceholder":411},[234,2483,2484],{"class":236,"line":415},[234,2485,2486],{"class":240},"# carga sustentada de 60s, 5 conexões concorrentes\n",[234,2488,2489,2492,2495,2498,2501,2504],{"class":236,"line":434},[234,2490,2491],{"class":247},"hey",[234,2493,2494],{"class":251}," -z",[234,2496,2497],{"class":255}," 60s",[234,2499,2500],{"class":251}," -c",[234,2502,2503],{"class":251}," 5",[234,2505,1451],{"class":255},[12,2507,2508],{},"En otra ventana, simultáneamente:",[224,2510,2512],{"className":226,"code":2511,"language":228,"meta":229,"style":229},".\u002Fdeploy.sh meuusuario\u002Fmyapp:v2\n",[231,2513,2514],{"__ignoreMap":229},[234,2515,2516,2518],{"class":236,"line":237},[234,2517,2379],{"class":247},[234,2519,2382],{"class":255},[12,2521,2522,2523,1272],{},"Al final del ",[231,2524,2491],{},[224,2526,2531],{"className":2527,"code":2529,"language":2530},[2528],"language-text","Status code distribution:\n  [200] 1847 responses\n","text",[231,2532,2529],{"__ignoreMap":229},[12,2534,2535],{},"Solo 200. Si aparece un 502 o 503, alguna de las tres piezas está débil: health check retornando 200 demasiado pronto, graceful shutdown ausente, o min healthy time corto. Investiga y corrige.",[57,2537],{},[19,2539,2541],{"id":2540},"los-seis-detalles-que-separan-cero-downtime-real-de-aproximacion","Los seis detalles que separan cero-downtime real de aproximación",[12,2543,2544],{},"Cubrimos buena parte de ellos a lo largo del tutorial, pero vale la pena consolidar — porque uno solo de estos ausente convierte el esquema entero en \"mostly zero-downtime\", que es diferente.",[67,2546,2547,2556,2573,2589,2595,2601],{},[70,2548,2549,2552,2553,2555],{},[27,2550,2551],{},"Connection draining en SIGTERM."," Cuando el contenedor recibe señal de parada, la app marca ",[231,2554,355],{}," como fallando inmediatamente, pero sigue aceptando conexiones en curso por algunos segundos. Sin esto, conexiones abiertas en el momento del stop son cortadas.",[70,2557,2558,2561,2562,2565,2566,2569,2570,101],{},[27,2559,2560],{},"Pre-stop hook si tienes worker asíncrono."," Colas que procesan jobs en background necesitan pausa explícita antes de matar el proceso, o el job en ejecución queda huérfano. En Sidekiq, es el ",[231,2563,2564],{},":quiet"," antes del ",[231,2567,2568],{},":term",". En Celery, es ",[231,2571,2572],{},"--soft-time-limit",[70,2574,2575,2578,2579,2582,2583,2585,2586,2588],{},[27,2576,2577],{},"Health check ANTES de promover, no \"container running\"."," ",[231,2580,2581],{},"docker ps"," muestra \"running\" milisegundos después del ",[231,2584,2406],{},". No significa nada. Promueve solo después de que ",[231,2587,355],{}," retorne 200 sostenidamente.",[70,2590,2591,2594],{},[27,2592,2593],{},"Min healthy time de diez segundos sostenidos."," No vale ver un único 200 y seguir adelante — apps con warm-up irregular pasan un momento y vuelven a fallar.",[70,2596,2597,2600],{},[27,2598,2599],{},"Versión anterior pre-pulled para rollback rápido."," Si confiaste en \"mantener la imagen antigua en cache de Docker\", en algún momento es borrada por garbage collection y el rollback se vuelve lento. Mantén las últimas tres imágenes explícitamente.",[70,2602,2603,2606],{},[27,2604,2605],{},"Auto-revert al pasar del healthy deadline."," Sin esto, el deploy traba en un estado parcial — la mitad de los hosts en v2, la mitad en v1, sin nadie para decidir qué hacer.",[19,2608,2610],{"id":2609},"database-migrations-cero-downtime-la-parte-que-rompe-el-deploy-de-gente-experimentada","Database migrations + cero-downtime (la parte que rompe el deploy de gente experimentada)",[12,2612,2613,2614,2617],{},"Este es el tópico que más veo a desarrollador senior errar. Rolling update asume que ",[27,2615,2616],{},"las dos versiones de la app corren simultáneamente en producción por algún período",". Si la v2 espera schema incompatible con lo que la v1 entiende, alguna de las dos rompe durante la ventana de transición.",[12,2619,2620,2621,101],{},"Regla de oro innegociable: ",[27,2622,2623],{},"migrations son siempre backward-compatible",[12,2625,2626,2627,2630,2631,2634,2635,2637],{},"Caso clásico: quieres renombrar columna ",[231,2628,2629],{},"email"," a ",[231,2632,2633],{},"email_address",". Solución equivocada: haces la migration que renombra directo antes del deploy. Resultado: durante el rolling, instancias v1 aún escriben en ",[231,2636,2629],{}," (que ya no existe) y rompen. Solución correcta, en tres deploys:",[119,2639,2640,2653],{},[122,2641,2642],{},[125,2643,2644,2647,2650],{},[128,2645,2646],{},"Deploy",[128,2648,2649],{},"Migration",[128,2651,2652],{},"Código v*",[141,2654,2655,2677,2695],{},[125,2656,2657,2660,2666],{},[146,2658,2659],{},"1",[146,2661,2662,2663,2665],{},"Añade ",[231,2664,2633],{}," (nullable). Ninguna eliminación.",[146,2667,2668,2669,2671,2672,2674,2675,101],{},"App escribe en ",[231,2670,2629],{}," Y en ",[231,2673,2633],{},"; lee de ",[231,2676,2629],{},[125,2678,2679,2682,2689],{},[146,2680,2681],{},"2",[146,2683,2684,2685,2688],{},"Backfill: ",[231,2686,2687],{},"UPDATE users SET email_address = email WHERE email_address IS NULL",". NOT NULL constraint.",[146,2690,2691,2692,2694],{},"App lee de ",[231,2693,2633],{},"; aún escribe en las dos.",[125,2696,2697,2700,2705],{},[146,2698,2699],{},"3",[146,2701,2702,2703,101],{},"Drop ",[231,2704,2629],{},[146,2706,2707,2708,101],{},"App solo usa ",[231,2709,2633],{},[12,2711,2712],{},"Tres deploys, semanas de espaciamiento. Es tedioso, es la forma. Drop de columna directo siempre rompe. Cambio de tipo directo siempre rompe. Añadir NOT NULL sin default directo siempre rompe.",[12,2714,2715,2716,2403,2719,2722,2723,2726],{},"Herramientas que ayudan: ",[231,2717,2718],{},"pg-osc",[231,2720,2721],{},"pgroll"," (Postgres), ",[231,2724,2725],{},"gh-ost"," (MySQL) — hacen schema change online, sin lock largo. Para migrations ligeras, la forma manual en tres pasos resuelve.",[19,2728,2730],{"id":2729},"patrones-mas-alla-de-rolling","Patrones más allá de rolling",[12,2732,2733],{},"Rolling update es el patrón default y más económico. Hay otros que vale la pena conocer:",[2735,2736,2737,2743,2749],"ul",{},[70,2738,2739,2742],{},[27,2740,2741],{},"Blue-green."," Dos entornos paralelos completos — \"blue\" corriendo v1, \"green\" provisionado con v2 vacío. Subes v2 entero en green, validas, cambias DNS (o cutover del balanceador). Ventaja: rollback instantáneo (vuelve DNS a blue). Desventaja: cuesta el doble de recursos durante la ventana de deploy.",[70,2744,2745,2748],{},[27,2746,2747],{},"Canary."," Manda 5% del tráfico a v2, observa métricas (errores, latencia, tasa de conversión), decide si promueve a 100% o aborta. Detecta bugs sutiles que health check no agarra — tipo regression en conversión de checkout. Exige proxy con weighted routing y observabilidad decente.",[70,2750,2751,2754],{},[27,2752,2753],{},"Rainbow \u002F N+1."," Generalización del blue-green con N versiones coexistiendo. Útil cuando quieres A\u002FB test de larga duración entre versiones enteras.",[12,2756,2757],{},"Para el tutorial, rolling update es lo que tiene sentido. Los otros valen cuando el tamaño del tráfico justifica inversión extra.",[19,2759,2761],{"id":2760},"version-facil-coolify-o-dokploy","Versión \"fácil\" — Coolify o Dokploy",[12,2763,2764],{},"Si no quieres scriptear, dos paneles modernos hacen rolling update automáticamente:",[2735,2766,2767,2773],{},[70,2768,2769,2772],{},[27,2770,2771],{},"Coolify"," en modo multi-server hace rolling update con health check configurable. Multi-server fue añadido en las versiones más recientes — antes era single-server only. Vale la pena chequear la versión.",[70,2774,2775,2778,2779,2782],{},[27,2776,2777],{},"Dokploy"," sobre Docker Swarm hace rolling update con ",[231,2780,2781],{},"--update-parallelism 1 --update-delay",". Aprovecha lo que Swarm ya ofrece.",[12,2784,2785],{},"Trade-off: cambias el script de cincuenta líneas (que entiende todo lo que está sucediendo) por un panel (que es más rápido para subir, pero se vuelve caja-negra cuando algo sale mal). Para equipo pequeño donde una persona cuida operación parcialmente, el panel gana. Para equipo donde necesitas entender exactamente qué pasó a las 3h de la mañana, el script gana.",[19,2787,2789],{"id":2788},"version-robusta-heroctl","Versión \"robusta\" — HeroCtl",[12,2791,2792],{},"Para quien quiere parar de scriptear pero no quiere caja-negra, HeroCtl combina rolling update automático con plano de control replicado. Describes el servicio en archivo de configuración y el orquestador hace el resto:",[224,2794,2798],{"className":2795,"code":2796,"language":2797,"meta":229,"style":229},"language-hcl shiki shiki-themes github-dark-default","job \"minhaapp\" {\n  group \"web\" {\n    count = 2\n\n    task \"app\" {\n      driver = \"docker\"\n      config {\n        image = \"meuusuario\u002Fmyapp:v2\"\n        ports = [\"http\"]\n      }\n\n      service {\n        port = \"http\"\n        check {\n          type     = \"http\"\n          path     = \"\u002Fhealthz\"\n          interval = \"5s\"\n          timeout  = \"2s\"\n        }\n      }\n    }\n\n    update {\n      max_parallel      = 1\n      min_healthy_time  = \"10s\"\n      healthy_deadline  = \"5m\"\n      auto_revert       = true\n    }\n  }\n}\n","hcl",[231,2799,2800,2805,2810,2815,2819,2824,2829,2834,2839,2844,2849,2853,2858,2863,2868,2873,2878,2883,2888,2892,2896,2900,2904,2909,2914,2919,2924,2929,2933,2937],{"__ignoreMap":229},[234,2801,2802],{"class":236,"line":237},[234,2803,2804],{},"job \"minhaapp\" {\n",[234,2806,2807],{"class":236,"line":244},[234,2808,2809],{},"  group \"web\" {\n",[234,2811,2812],{"class":236,"line":271},[234,2813,2814],{},"    count = 2\n",[234,2816,2817],{"class":236,"line":415},[234,2818,412],{"emptyLinePlaceholder":411},[234,2820,2821],{"class":236,"line":434},[234,2822,2823],{},"    task \"app\" {\n",[234,2825,2826],{"class":236,"line":459},[234,2827,2828],{},"      driver = \"docker\"\n",[234,2830,2831],{"class":236,"line":464},[234,2832,2833],{},"      config {\n",[234,2835,2836],{"class":236,"line":479},[234,2837,2838],{},"        image = \"meuusuario\u002Fmyapp:v2\"\n",[234,2840,2841],{"class":236,"line":484},[234,2842,2843],{},"        ports = [\"http\"]\n",[234,2845,2846],{"class":236,"line":490},[234,2847,2848],{},"      }\n",[234,2850,2851],{"class":236,"line":508},[234,2852,412],{"emptyLinePlaceholder":411},[234,2854,2855],{"class":236,"line":529},[234,2856,2857],{},"      service {\n",[234,2859,2860],{"class":236,"line":535},[234,2861,2862],{},"        port = \"http\"\n",[234,2864,2865],{"class":236,"line":546},[234,2866,2867],{},"        check {\n",[234,2869,2870],{"class":236,"line":552},[234,2871,2872],{},"          type     = \"http\"\n",[234,2874,2875],{"class":236,"line":557},[234,2876,2877],{},"          path     = \"\u002Fhealthz\"\n",[234,2879,2880],{"class":236,"line":594},[234,2881,2882],{},"          interval = \"5s\"\n",[234,2884,2885],{"class":236,"line":635},[234,2886,2887],{},"          timeout  = \"2s\"\n",[234,2889,2890],{"class":236,"line":643},[234,2891,1352],{},[234,2893,2894],{"class":236,"line":659},[234,2895,2848],{},[234,2897,2898],{"class":236,"line":683},[234,2899,1357],{},[234,2901,2902],{"class":236,"line":695},[234,2903,412],{"emptyLinePlaceholder":411},[234,2905,2906],{"class":236,"line":717},[234,2907,2908],{},"    update {\n",[234,2910,2911],{"class":236,"line":723},[234,2912,2913],{},"      max_parallel      = 1\n",[234,2915,2916],{"class":236,"line":729},[234,2917,2918],{},"      min_healthy_time  = \"10s\"\n",[234,2920,2921],{"class":236,"line":734},[234,2922,2923],{},"      healthy_deadline  = \"5m\"\n",[234,2925,2926],{"class":236,"line":771},[234,2927,2928],{},"      auto_revert       = true\n",[234,2930,2931],{"class":236,"line":776},[234,2932,1357],{},[234,2934,2935],{"class":236,"line":815},[234,2936,720],{},[234,2938,2939],{"class":236,"line":820},[234,2940,1362],{},[12,2942,2943],{},"Los mismos parámetros del script bash, declarativos. La diferencia es que el orquestador coordina rolling update entre N servidores (no solo dos), hace elección automática de coordinador en alrededor de siete segundos si el nodo actual se cae, y mantiene el plano de control distribuido entre los primeros tres servidores. Cluster sobrevive a la pérdida de cualquier servidor único sin intervención humana.",[12,2945,2946],{},"Instalación:",[224,2948,2950],{"className":226,"code":2949,"language":228,"meta":229,"style":229},"curl -sSL https:\u002F\u002Fget.heroctl.com\u002Finstall.sh | sh\n",[231,2951,2952],{"__ignoreMap":229},[234,2953,2954,2956,2959,2962,2965],{"class":236,"line":237},[234,2955,1220],{"class":247},[234,2957,2958],{"class":251}," -sSL",[234,2960,2961],{"class":255}," https:\u002F\u002Fget.heroctl.com\u002Finstall.sh",[234,2963,2964],{"class":383}," |",[234,2966,2967],{"class":247}," sh\n",[12,2969,2970],{},"Plan Community es gratuito permanente — sin límite de servidores o jobs, con todas las features de orquestación descritas en el tutorial. Plan Business añade SSO\u002FSAML, RBAC granular, auditoría detallada y soporte con SLA, para equipos que tienen requisitos formales de plataforma. Plan Enterprise añade escrow de código fuente, contrato de continuidad y soporte 24×7. Los precios de Business y Enterprise están publicados en la página de planes — sin \"habla con ventas\" obligatorio.",[19,2972,2974],{"id":2973},"comparativo-cinco-caminos-lado-a-lado","Comparativo: cinco caminos lado a lado",[119,2976,2977,3002],{},[122,2978,2979],{},[125,2980,2981,2984,2987,2990,2993,2996,2999],{},[128,2982,2983],{},"Criterio",[128,2985,2986],{},"Script bash (2 servers)",[128,2988,2989],{},"Coolify multi-server",[128,2991,2992],{},"Dokploy + Swarm",[128,2994,2995],{},"HeroCtl",[128,2997,2998],{},"Kamal",[128,3000,3001],{},"Kubernetes",[141,3003,3004,3026,3049,3071,3089,3106,3128,3148],{},[125,3005,3006,3009,3012,3015,3018,3021,3023],{},[146,3007,3008],{},"Tiempo de setup",[146,3010,3011],{},"2-3h",[146,3013,3014],{},"30 min",[146,3016,3017],{},"1h",[146,3019,3020],{},"5 min",[146,3022,3017],{},[146,3024,3025],{},"4h-4 días",[125,3027,3028,3031,3034,3037,3040,3043,3046],{},[146,3029,3030],{},"Líneas de config",[146,3032,3033],{},"~50 (script)",[146,3035,3036],{},"UI",[146,3038,3039],{},"~20",[146,3041,3042],{},"~50",[146,3044,3045],{},"~40",[146,3047,3048],{},"300+",[125,3050,3051,3054,3057,3060,3063,3066,3068],{},[146,3052,3053],{},"HA del plano de control",[146,3055,3056],{},"N\u002FA",[146,3058,3059],{},"No",[146,3061,3062],{},"Limitado",[146,3064,3065],{},"Sí",[146,3067,3056],{},[146,3069,3070],{},"Sí (5+ componentes)",[125,3072,3073,3076,3079,3081,3083,3085,3087],{},[146,3074,3075],{},"Health check declarativo",[146,3077,3078],{},"Manual",[146,3080,3065],{},[146,3082,3065],{},[146,3084,3065],{},[146,3086,3065],{},[146,3088,3065],{},[125,3090,3091,3093,3096,3098,3100,3102,3104],{},[146,3092,2442],{},[146,3094,3095],{},"Manual en el script",[146,3097,3065],{},[146,3099,3065],{},[146,3101,3065],{},[146,3103,3065],{},[146,3105,3065],{},[125,3107,3108,3111,3114,3117,3120,3123,3125],{},[146,3109,3110],{},"Escala objetivo",[146,3112,3113],{},"1-3 servers",[146,3115,3116],{},"1-10 servers",[146,3118,3119],{},"1-20 servers",[146,3121,3122],{},"1-500 servers",[146,3124,3116],{},[146,3126,3127],{},"50+ servers",[125,3129,3130,3133,3136,3138,3141,3144,3146],{},[146,3131,3132],{},"¿Caja-negra?",[146,3134,3135],{},"No (lo escribiste tú)",[146,3137,3065],{},[146,3139,3140],{},"Parcial",[146,3142,3143],{},"No (declarativo corto)",[146,3145,3059],{},[146,3147,3065],{},[125,3149,3150,3153,3156,3158,3161,3163,3165],{},[146,3151,3152],{},"Curva de aprendizaje",[146,3154,3155],{},"Baja",[146,3157,3155],{},[146,3159,3160],{},"Media",[146,3162,3155],{},[146,3164,3155],{},[146,3166,3167],{},"Alta",[12,3169,3170],{},"Cada columna tiene su nicho. Script bash es insuperable cuando quieres entender cada línea. Coolify gana cuando solo quieres un panel. HeroCtl gana cuando necesitas HA real sin montar plano de control externo. Kubernetes gana en escala planetaria — donde la complejidad compensa.",[19,3172,3174],{"id":3173},"los-cinco-errores-mas-comunes","Los cinco errores más comunes",[67,3176,3177,3189,3195,3205,3217],{},[70,3178,3179,3185,3186,3188],{},[27,3180,3181,3182,3184],{},"Health check en ",[231,3183,1523],{}," retornando 200 sin validar dependencias."," La app retorna 200 antes de conectar a la base, el proxy promueve, y el usuario ve error 500 en las primeras requests. Solución: ",[231,3187,355],{}," valida base, cache, cola — cualquier cosa que la app necesite para responder de verdad.",[70,3190,3191,3194],{},[27,3192,3193],{},"Min healthy time de 1 segundo."," Apps con warm-up irregular pueden retornar 200 en un momento y 503 justo después (cache poblando, clase siendo lazy-loaded). El orquestador promueve en la primera ventana buena, y la próxima request golpea en estado malo. Diez segundos sostenidos eliminan noventa por ciento de esos casos.",[70,3196,3197,3200,3201,3204],{},[27,3198,3199],{},"Sin max_parallel (o max_parallel = N)."," Si cambias todas las instancias juntas, durante la ventana del cutover no hay nadie saludable sirviendo. Es single-server downtime disfrazado. Siempre ",[231,3202,3203],{},"max_parallel = 1"," para empezar.",[70,3206,3207,3210,3211,3213,3214,3216],{},[27,3208,3209],{},"Mix de versiones en producción sin schema compat."," v1 escribe en ",[231,3212,2629],{},", v2 lee de ",[231,3215,2633],{},", y durante el rolling de cinco minutos las dos conviven — usuarios que reciben v2 no ven datos que v1 acaba de grabar. Migration backward-compatible en tres pasos resuelve.",[70,3218,3219,3222],{},[27,3220,3221],{},"Cache stale en el cliente (CDN, browser, service worker)."," Backend ya es v2 pero el usuario tiene el JS de v1 en cache, y el JS antiguo llama a API que ya no existe. Solución: mantén endpoints antiguos por una ventana; versionado de API; cache-busting fuerte en assets críticos.",[19,3224,3226],{"id":3225},"faq","FAQ",[12,3228,3229],{},[27,3230,3231],{},"¿Puedo hacer cero-downtime con un solo servidor?",[12,3233,3234,3235,3238],{},"No. Toda variación que prometa eso tiene ventana de error mensurable cuando la mides con ",[231,3236,3237],{},"hey -c 20",". La única forma de tener cero-downtime real es mantener al menos una instancia siempre saludable durante todo el deploy — lo que exige dos máquinas como mínimo.",[12,3240,3241],{},[27,3242,3243],{},"¿DNS round-robin funciona como balanceador?",[12,3245,3246],{},"Funciona como balanceador básico, pero no como mecanismo de health check. DNS no retira IP muerto de la rotación rápidamente — TTLs cacheando en ISPs y clientes mantienen el IP equivocado en uso por minutos u horas. Para cero-downtime necesitas un proxy real (Caddy, nginx, HAProxy) que retira instancia unhealthy del balanceo en segundos.",[12,3248,3249],{},[27,3250,3251],{},"¿Caddy o Traefik — cuál es mejor para este setup?",[12,3253,3254],{},"Para dos servidores y un setup estático, Caddy es más simple — Caddyfile de quince líneas resuelve. Traefik brilla cuando tienes descubrimiento dinámico de servicios (tipo Docker labels o Consul) y muchos backends cambiando todo el tiempo. nginx queda en el medio: más flexible, sin TLS automático embebido (necesita certbot externo). Para este tutorial, Caddy.",[12,3256,3257],{},[27,3258,3259],{},"¿Conexiones WebSocket sobreviven durante rolling update?",[12,3261,3262,3263,3265],{},"Conexiones abiertas en instancia que está siendo tirada son cortadas. El cliente tiene que reconectar. Buena biblioteca de WebSocket (Socket.IO, Phoenix Channels) reconecta automáticamente — usuario ve un parpadeo de medio segundo en el estado. Connection draining ayuda: la instancia marca ",[231,3264,355],{}," fallando, el proxy deja de mandar conexiones nuevas, pero las existentes siguen hasta el pre-stop timer. Treinta segundos de drain suelen ser suficientes para que conexiones largas se vacíen naturalmente.",[12,3267,3268],{},[27,3269,3270],{},"Database migrations — ¿cuál es la regla de oro?",[12,3272,3273],{},"Toda migration tiene que ser backward-compatible. Drop de columna nunca directo. Rename nunca directo. Cambio de tipo nunca directo. En su lugar, tres deploys: añade estructura nueva, backfill, elimina la antigua. Lento, sí. Pero el rolling update depende de eso para no romper.",[12,3275,3276],{},[27,3277,3278],{},"Rollback automático — ¿cómo implementar?",[12,3280,3281,3282,101],{},"Dos piezas: deadline (tiempo máximo esperando health check) y referencia de la imagen anterior pre-pulled. Si pasa del deadline sin estar saludable, el script reinstala la versión anterior. El ejemplo en el Paso 5 hace exactamente eso. En orquestadores declarativos, se vuelve ",[231,3283,3284],{},"auto_revert = true",[12,3286,3287],{},[27,3288,3289],{},"¿Sticky sessions complican el cero-downtime?",[12,3291,3292],{},"Sí. Si la app guarda estado de sesión en memoria del proceso, tirar la instancia tira las sesiones de los usuarios conectados a ella. Solución: saca sesión de la memoria — Redis, Postgres o JWT signed. Ahí cualquier instancia sirve a cualquier usuario, y rolling update no corta ninguna sesión.",[12,3294,3295],{},[27,3296,3297],{},"¿Cuánto tiempo tarda un deploy completo?",[12,3299,3300,3301,3304],{},"Dos servidores, app que sube en quince segundos: cerca de un minuto. Detalle: pull de la imagen (5-15s, depende de la red y del tamaño), sustitución del contenedor (1s), warm-up + health check (10-30s), min healthy time de 10s, total unos 30-50s por host, multiplicado por dos hosts en secuencia = 1-2 min. Cuatro servidores quedan en torno a 2-4 min. Con cincuenta servidores, el deploy empieza a tomar diez o quince minutos — momento de aumentar ",[231,3302,3303],{},"max_parallel"," a dos o tres (manteniendo health check riguroso).",[57,3306],{},[19,3308,3310],{"id":3309},"cierre","Cierre",[12,3312,3313],{},"El deploy cero-downtime es arquitectura, no herramienta. Los tres ingredientes — múltiples instancias, proxy con health check, rolling update controlado — funcionan con bash y Caddy tanto como con orquestador grande. La diferencia está en cuánto de la operación quieres escribir a mano y cuánto delegar.",[12,3315,3316],{},"Para un SaaS pequeño, tres VPS y un script de cincuenta líneas resuelven indefinidamente. Cuando el cluster crece a decenas de servidores o el equipo necesita HA real del plano de control, vale la pena subir al orquestador declarativo:",[224,3318,3319],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,3320,3321],{"__ignoreMap":229},[234,3322,3323,3325,3327,3329,3331],{"class":236,"line":237},[234,3324,1220],{"class":247},[234,3326,2958],{"class":251},[234,3328,2961],{"class":255},[234,3330,2964],{"class":383},[234,3332,2967],{"class":247},[12,3334,3335,3336,3341,3342,3346],{},"Más sobre el algoritmo de rolling update en ",[3337,3338,3340],"a",{"href":3339},"\u002Fes\u002Fblog\u002Frolling-deploy-seguro-por-que-el-tuyo-puede-no-serlo","Rolling update seguro: por qué el tuyo puede no serlo",". Para quien está saliendo de Compose a setup multi-servidor, ",[3337,3343,3345],{"href":3344},"\u002Fes\u002Fblog\u002Fdeploy-docker-produccion-de-compose-a-cluster","Deploy Docker en producción: de compose a cluster"," cubre el camino intermedio.",[12,3348,3349],{},"Orquestación de contenedores, sin ceremonia.",[3351,3352,3353],"style",{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}",{"title":229,"searchDepth":244,"depth":244,"links":3355},[3356,3357,3358,3359,3360,3361,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378],{"id":21,"depth":244,"text":22},{"id":61,"depth":244,"text":62},{"id":93,"depth":244,"text":94},{"id":113,"depth":244,"text":114},{"id":215,"depth":244,"text":216},{"id":348,"depth":244,"text":349,"children":3362},[3363,3364,3365],{"id":370,"depth":271,"text":371},{"id":918,"depth":271,"text":919},{"id":1002,"depth":271,"text":1003},{"id":1099,"depth":244,"text":1100},{"id":1241,"depth":244,"text":1242},{"id":1462,"depth":244,"text":1463},{"id":2449,"depth":244,"text":2450},{"id":2540,"depth":244,"text":2541},{"id":2609,"depth":244,"text":2610},{"id":2729,"depth":244,"text":2730},{"id":2760,"depth":244,"text":2761},{"id":2788,"depth":244,"text":2789},{"id":2973,"depth":244,"text":2974},{"id":3173,"depth":244,"text":3174},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"engineering",null,"2026-06-09","No necesitas Kubernetes para tener deploy sin downtime. Tutorial completo con 2 servidores, Caddy\u002FTraefik por delante, y rolling update vía script u orquestador ligero.",false,"md",{},"\u002Fes\u002Fblog\u002Fdeploy-cero-downtime-sin-kubernetes","15 min",{"title":6,"description":3382},{"loc":3386},"es\u002Fblog\u002Fdeploy-cero-downtime-sin-kubernetes",[1526,3392,3393,3394],"cero-downtime","tutorial","ingenieria","DIdopGCYte4Yw34SS-f9-YpuJ3SLOw5rKbvHsED4tPc",{"id":3397,"title":3398,"author":7,"body":3399,"category":3379,"cover":3380,"date":4398,"description":4399,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":4400,"navigation":411,"path":4401,"readingTime":4402,"seo":4403,"sitemap":4404,"stem":4405,"tags":4406,"__hash__":4411},"blog_es\u002Fes\u002Fblog\u002Fapi-gateway-auto-hospedado-cuando-instalar.md","API Gateway auto-hospedado: cuándo vale la pena instalar Kong, Traefik o similar",{"type":9,"value":3400,"toc":4378},[3401,3404,3407,3411,3418,3421,3428,3432,3435,3517,3523,3583,3586,3590,3593,3597,3600,3606,3612,3618,3622,3625,3630,3635,3640,3644,3647,3652,3657,3662,3666,3669,3674,3679,3684,3688,3691,3696,3701,3706,3710,3713,3751,3754,3758,3761,3813,3816,3820,3823,3829,3832,3835,3839,4125,4132,4136,4139,4145,4151,4157,4163,4169,4172,4176,4179,4185,4191,4197,4203,4207,4210,4242,4246,4256,4262,4268,4278,4284,4290,4296,4310,4316,4320,4323,4326,4329,4332,4348,4362,4372,4375],[12,3402,3403],{},"\"API gateway\" es una de las categorías más sobrecargadas de jerga en la arquitectura de back-end. El término se volvió paraguas para cosas que un reverse proxy simple ya hace hace veinte años — enrutar, terminar TLS, balancear entre instancias — mezcladas con cosas que de hecho exigen un componente dedicado: validación de clave de API por cliente, límite de peticiones por usuario, transformación del cuerpo de la petición, agregación de múltiples back-ends en una sola respuesta. La confusión vende mucho producto. Y hace que muchas startups instalen un componente crítico que no necesitaban — pagando después en latencia, RAM, complejidad operacional y superficie de fallo.",[12,3405,3406],{},"Este post separa lo que cada cosa cubre, lista los cinco jugadores principales con números honestos de consumo de recursos, y dibuja una regla práctica: cuándo el reverse proxy embebido en el orquestador resuelve, cuándo vale levantar un Traefik standalone, y cuándo de hecho necesitas un Kong con plug-ins de autenticación. La audiencia es el tech lead que está mirando el stack actual y tratando de decidir si el siguiente dolor merece un componente más en el camino crítico — o si el dolor es falso.",[19,3408,3410],{"id":3409},"tldr-instalar-gateway-dedicado-es-decision-cara-manten-la-regla-corta","TL;DR — instalar gateway dedicado es decisión cara, mantén la regla corta",[12,3412,3413,3414,3417],{},"Reverse proxy simple cubre el tronco del problema: HTTPS terminado, certificados Let's Encrypt automáticos, enrutamiento por host y ruta, balanceo entre back-ends, health check, compresión. Para un SaaS B2B típico con web app + algunos micro-servicios HTTP, ",[27,3415,3416],{},"eso basta",". No hace falta instalar Kong, no hace falta Tyk, no hace falta KrakenD.",[12,3419,3420],{},"API gateway dedicado se vuelve inversión defendible cuando aparecen tres señales simultáneas: publicas una API para que terceros la consuman (no solo tu propia web\u002Fmobile), necesitas límite de peticiones por clave de cliente (no por IP), y quieres documentación interactiva con tentar-aquí para los consumidores. En ese escenario, Kong, Tyk o Traefik con middlewares ricos pagan su propio coste. Fuera de ese escenario, estás añadiendo 100–300 MB de RAM en el camino crítico, de 1 a 3 milisegundos de latencia por petición, y un componente más que puede caer en producción — a cambio de funcionalidades que nadie va a usar.",[12,3422,3423,3424,3427],{},"La regla más simple que conocemos: ",[27,3425,3426],{},"si tu cliente final es una persona abriendo un navegador, basta con reverse proxy. Si tu cliente final es un desarrollador con clave de API, considera el gateway."," Todo lo demás es variación sobre esas dos líneas.",[19,3429,3431],{"id":3430},"lo-que-un-reverse-proxy-simple-ya-cubre-y-lo-que-aun-falta","Lo que un reverse proxy simple ya cubre, y lo que aún falta",[12,3433,3434],{},"Antes de comparar gateways, vale fijar el suelo. Un reverse proxy decente — Caddy, nginx, o el router integrado de un orquestador moderno — entrega bastante cosa gratis. Esta lista representa el estado del arte en 2026, no el mínimo histórico:",[2735,3436,3437,3443,3449,3466,3472,3478,3484,3490,3496,3502],{},[70,3438,3439,3442],{},[27,3440,3441],{},"Terminación HTTP\u002FHTTPS con HTTP\u002F2 y HTTP\u002F3."," El proxy habla con el cliente en cualquier protocolo moderno y habla con el back-end en HTTP\u002F1.1 limpio si es el caso.",[70,3444,3445,3448],{},[27,3446,3447],{},"Certificados Let's Encrypt automáticos."," Emisión, renovación a los 60 días, recuperación de error. Hoy eso es commodity — cualquier router serio lo hace.",[70,3450,3451,2578,3454,3457,3458,3461,3462,3465],{},[27,3452,3453],{},"Enrutamiento por host y ruta.",[231,3455,3456],{},"api.ejemplo.com"," va a un back-end, ",[231,3459,3460],{},"app.ejemplo.com"," va a otro, ",[231,3463,3464],{},"\u002Fv1\u002Fusuarios"," va a un tercero. Reglas con prefijo, regex y prioridad.",[70,3467,3468,3471],{},[27,3469,3470],{},"Balanceo entre instancias."," Round-robin, menos conexiones, hash por IP. Suficiente para distribuir carga entre las réplicas de un mismo servicio.",[70,3473,3474,3477],{},[27,3475,3476],{},"Health check activo y pasivo."," Saca instancia enferma del pool. La re-incluye cuando vuelve.",[70,3479,3480,3483],{},[27,3481,3482],{},"Compresión gzip y brotli."," Negocia con el cliente, comprime lo que vale la pena.",[70,3485,3486,3489],{},[27,3487,3488],{},"Caché de contenido estático."," Para archivos inmutables, evita la ida al back-end.",[70,3491,3492,3495],{},[27,3493,3494],{},"Límite básico por IP."," Treinta peticiones por segundo por dirección, por ejemplo. Cubre buena parte del abuso tonto.",[70,3497,3498,3501],{},[27,3499,3500],{},"Timeouts y reintentos."," Falla rápido, intenta de nuevo en un back-end alternativo si es el caso.",[70,3503,3504,2578,3507,571,3510,571,3513,3516],{},[27,3505,3506],{},"Cabeceras de proxy.",[231,3508,3509],{},"X-Forwarded-For",[231,3511,3512],{},"X-Real-IP",[231,3514,3515],{},"X-Forwarded-Proto",". El back-end ve al cliente real.",[12,3518,3519,3520,3522],{},"Eso es mucha cosa. Para 80% de las aplicaciones web de SaaS B2B, es todo lo que se necesita en el camino de entrada. Lo que el reverse proxy simple ",[27,3521,100],{}," cubre es lo que diferencia al gateway:",[2735,3524,3525,3531,3541,3547,3553,3559,3565,3571,3577],{},[70,3526,3527,3530],{},[27,3528,3529],{},"Validación de clave de API por cliente."," Cada consumidor recibe una clave, el gateway valida, identifica al cliente, y usa esa identidad para límites y auditoría.",[70,3532,3533,3536,3537,3540],{},[27,3534,3535],{},"Validación de token JWT con claves rotables."," El gateway baja las claves públicas del emisor, valida firma y tiempo, expone ",[231,3538,3539],{},"claims"," al back-end.",[70,3542,3543,3546],{},[27,3544,3545],{},"Límite de peticiones por clave\u002Fusuario\u002Fruta."," Cliente A puede hacer 1.000 llamadas\u002Fhora; cliente B, 100. Por ruta, por día, con ventana deslizante. Difícil de hacer en proxy simple.",[70,3548,3549,3552],{},[27,3550,3551],{},"Transformación de petición y respuesta."," Añadir\u002Fquitar cabeceras, reescribir cuerpo JSON, traducir entre versiones de la API.",[70,3554,3555,3558],{},[27,3556,3557],{},"Versionado por cabecera o ruta."," Convivir con clientes en v1 mientras v2 gana tracción. Política de descontinuación.",[70,3560,3561,3564],{},[27,3562,3563],{},"Agregación de back-ends."," Endpoint compuesto que llama a tres micro-servicios y devuelve una respuesta unificada (patrón back-end-for-frontend).",[70,3566,3567,3570],{},[27,3568,3569],{},"Validación de esquema de la petición."," Rechazar en el gateway lo que no encaja con el contrato OpenAPI antes de tocar al back-end.",[70,3572,3573,3576],{},[27,3574,3575],{},"Portal de documentación con tentar-aquí."," Página interactiva para que los desarrolladores exploren la API.",[70,3578,3579,3582],{},[27,3580,3581],{},"Métricas granulares por clave de API."," Quién llamó, cuánto, cuándo, con qué latencia. Vital si la API es el producto.",[12,3584,3585],{},"Cada item de esa segunda lista es una feature que cuesta caro hacer en código de aplicación esparcido. Si necesitas la mayoría, el gateway paga. Si no necesitas casi nada — que es el caso común en SaaS de producto — el gateway es peso muerto.",[19,3587,3589],{"id":3588},"los-cinco-jugadores-que-importan-en-2026","Los cinco jugadores que importan en 2026",[12,3591,3592],{},"El mercado se asentó. Hay cinco elecciones defendibles para gateway auto-hospedado, con perfiles razonablemente distintos. Los números de RAM y latencia abajo se miden con configuración por defecto y workload modesto (algunas decenas de llamadas por segundo); plug-ins pesados o volumen alto cambian todo.",[368,3594,3596],{"id":3595},"kong-basado-en-lua-sobre-openresty","Kong (basado en Lua, sobre OpenResty)",[12,3598,3599],{},"El nombre más conocido de la categoría. Kong empezó en 2015 y tiene el catálogo más grande de plug-ins del espacio — autenticación OAuth, validación JWT, transformación, log a Elasticsearch, integración con cofres externos, todo pre-listo. La versión de código abierto cubre la mayoría de los casos; la pagada añade portal de desarrollador más pulido, RBAC fino, y soporte con SLA.",[12,3601,3602,3605],{},[27,3603,3604],{},"Recursos:"," mínimo realista de 200 MB de RAM por instancia, más la base de datos si no usas modo sin-base. Latencia añadida de 1 a 2 milisegundos por petición en llamada simple. Plug-ins pesados (validación de esquema con OpenAPI grande, transformación JSON compleja) pueden duplicar eso.",[12,3607,3608,3611],{},[27,3609,3610],{},"Cuándo tiene sentido:"," API pública seria con varios consumidores externos, necesidad de plug-ins del catálogo, equipo dispuesto a aprender Lua si necesita customizar. Empresa de medio de pagos, plataforma de comunicación, cualquier negocio donde la API es el producto vendido.",[12,3613,3614,3617],{},[27,3615,3616],{},"Trampa:"," el modo con PostgreSQL coloca la base en el camino crítico. La base se cae, el gateway no actualiza configuración. Usa el modo sin-base (configuración declarativa vía archivo) siempre que sea posible — elimina esa dependencia.",[368,3619,3621],{"id":3620},"traefik-escrito-en-go-hablando-varios-proxies-de-orquestador","Traefik (escrito en Go, hablando varios proxies de orquestador)",[12,3623,3624],{},"Conocido como controlador de entrada de Kubernetes, pero tiene middlewares ricos lo suficiente para cubrir muchos casos de gateway. Límite de peticiones por cliente, validación básica de JWT, transformación de cabecera, redirecciones complejas, autenticación reenviada (delegando a servicio externo). Versión pagada añade plug-ins comerciales y dashboard más robusto.",[12,3626,3627,3629],{},[27,3628,3604],{}," 50 a 100 MB de RAM, latencia añadida de 0,5 a 1 milisegundo. Discovery automático de back-ends vía etiquetas de contenedor es el punto fuerte — no escribes configuración de ruta, ella aparece cuando el servicio sube.",[12,3631,3632,3634],{},[27,3633,3610],{}," ya estás usando Traefik como router de entrada y quieres evitar añadir un componente más; necesitas middlewares razonables pero no del catálogo gigante de Kong; valoras configuración declarativa por etiqueta en lugar de base de datos.",[12,3636,3637,3639],{},[27,3638,3616],{}," algunos patrones avanzados (agregación de llamadas, validación OpenAPI completa, portal de documentación interactivo) no caben en Traefik. Si necesitas eso, la tentación de \"estirar\" Traefik vía plug-ins customizados lleva a complejidad que Kong resolvería de forma más limpia.",[368,3641,3643],{"id":3642},"tyk-escrito-en-go-foco-en-portal-de-desarrollador","Tyk (escrito en Go, foco en portal de desarrollador)",[12,3645,3646],{},"La versión de código abierto entrega mucho más que la mayoría — límite de peticiones por clave, gestión de claves, portal de desarrollador, todos en el plan gratis. La versión pagada añade panel multi-tenant, replicación multi-región, y soporte.",[12,3648,3649,3651],{},[27,3650,3604],{}," 100 MB de RAM, latencia añadida de 1 a 2 milisegundos. Base de datos (Redis) es parte central de la arquitectura — límite de peticiones y contadores viven ahí.",[12,3653,3654,3656],{},[27,3655,3610],{}," API con muchos consumidores externos, portal de desarrollador es parte del producto, quieres pagar menos de lo que Kong cobra por el equivalente en recursos. Equipos pequeños publicando API para socios han encontrado buen encaje aquí.",[12,3658,3659,3661],{},[27,3660,3616],{}," menos plug-ins listos que Kong. Si tu integración esperada existe en la lista de Kong pero no en la de Tyk, el trade-off cambia.",[368,3663,3665],{"id":3664},"krakend-escrito-en-go-sin-base-de-datos-foco-en-agregacion","KrakenD (escrito en Go, sin base de datos, foco en agregación)",[12,3667,3668],{},"KrakenD es el gateway pequeño que se especializa en agregación. Configuración 100% en archivo, sin estado externo, diseñado para componer endpoints — el cliente hace una llamada, KrakenD llama a tres back-ends en paralelo y devuelve una respuesta combinada. Excelente para patrón back-end-for-frontend.",[12,3670,3671,3673],{},[27,3672,3604],{}," 50 MB de RAM, latencia añadida de 0,5 milisegundo. El más liviano de la categoría. Sin base, sin panel — todo es archivo de configuración estático.",[12,3675,3676,3678],{},[27,3677,3610],{}," tienes múltiples micro-servicios y quieres exponer una API más limpia al front-end mobile\u002Fweb. No necesitas gestión dinámica de claves ni portal de desarrollador. Te gusta la configuración inmutable: cambias archivo, haces deploy nuevo, listo.",[12,3680,3681,3683],{},[27,3682,3616],{}," todo es estático. Añadir una clave nueva es deploy. Para equipo pequeño eso es simplificación; para plataforma de API con terceros registrándose, se vuelve cuello de botella.",[368,3685,3687],{"id":3686},"envoy-gateway-cncf-sobre-proxy-envoy","Envoy Gateway (CNCF, sobre proxy Envoy)",[12,3689,3690],{},"El benjamín serio de la lista. Envoy es el proxy de altísimo rendimiento usado en mallas de servicio grandes. Envoy Gateway es el proyecto que empaqueta Envoy como gateway de API con configuración declarativa. Foco en Kubernetes, alta tasa de transferencia, integración con malla.",[12,3692,3693,3695],{},[27,3694,3604],{}," Envoy puro consume 50 a 100 MB en el proxy de datos; el plano de control pesa más. Latencia añadida baja (\u003C 1 milisegundo) en llamada simple. Pero la complejidad operacional es la más alta de la lista.",[12,3697,3698,3700],{},[27,3699,3610],{}," ya corres malla de servicio con Envoy (Istio, Consul, Linkerd con proxy compatible) y quieres consistencia de configuración entre malla y gateway. Operas en escala lo suficientemente alta para que la tasa de Envoy importe (decenas de miles de peticiones por segundo).",[12,3702,3703,3705],{},[27,3704,3616],{}," para startup con 4 servidores y algunas decenas de peticiones por segundo, Envoy Gateway es overkill por dos o tres tamaños. La complejidad de configuración no se paga.",[19,3707,3709],{"id":3708},"cuando-basta-un-reverse-proxy-simple","¿Cuándo basta un reverse proxy simple?",[12,3711,3712],{},"Esta es la pregunta que ahorra dinero. La respuesta honesta es: en la gran mayoría de los SaaS B2B que vemos corriendo, basta. Los criterios para \"basta\":",[2735,3714,3715,3721,3727,3733,3739,3745],{},[70,3716,3717,3720],{},[27,3718,3719],{},"Público de tu API es tu propia aplicación."," Web, mobile, integraciones internas. No hay terceros desconocidos llamando endpoints con claves emitidas por ti.",[70,3722,3723,3726],{},[27,3724,3725],{},"Autenticación ocurre en la aplicación, no en el camino."," Sesión por cookie, token JWT emitido por el propio back-end y validado por middleware de la aplicación, OAuth vía biblioteca dentro del código. El proxy no necesita ver al usuario.",[70,3728,3729,3732],{},[27,3730,3731],{},"Límite de peticiones es \"evita abuso tonto\"."," Treinta por segundo por IP, quizás. No hay plan comercial que limite Cliente A a 1.000 llamadas\u002Fdía y Cliente B a 10.000.",[70,3734,3735,3738],{},[27,3736,3737],{},"No necesitas combinar back-ends."," Cada llamada del front-end va a un endpoint, ese endpoint llama a lo que necesita internamente. Sin agregación en el camino.",[70,3740,3741,3744],{},[27,3742,3743],{},"Documentación de la API es interna o inexistente."," No hay portal de desarrollador con tentar-aquí para terceros.",[70,3746,3747,3750],{},[27,3748,3749],{},"Versionado, si existe, se gestiona en código."," El back-end enruta internamente entre v1 y v2 cuando es necesario. No hay política formal en el gateway.",[12,3752,3753],{},"Si cinco de los seis items de arriba son verdad, instalar gateway dedicado es caro por el beneficio real. Reverse proxy embebido en el orquestador, o Caddy\u002Fnginx standalone, cubre todo.",[19,3755,3757],{"id":3756},"cuando-vale-la-pena-un-gateway-dedicado","¿Cuándo vale la pena un gateway dedicado?",[12,3759,3760],{},"La inversión de la lista anterior. Gateway compensa cuando aparecen algunos de estos:",[2735,3762,3763,3769,3775,3781,3795,3801,3807],{},[70,3764,3765,3768],{},[27,3766,3767],{},"API pública es parte del producto."," Cobras (o planeas cobrar) por uso de API. Terceros se registran, reciben clave, consumen.",[70,3770,3771,3774],{},[27,3772,3773],{},"Límite por clave\u002Fusuario\u002Fruta es regla de negocio."," Plan gratis tiene techo, plan pagado tiene techo mayor, plan enterprise se negocia. Ese límite necesita vivir en algún lugar — gateway es el lugar correcto.",[70,3776,3777,3780],{},[27,3778,3779],{},"Múltiples back-ends necesitan combinarse en una respuesta."," Patrón back-end-for-frontend, agregación de micro-servicios, fan-out y fan-in. Costes altos en la aplicación, costes modestos en el gateway.",[70,3782,3783,3786,3787,3790,3791,3794],{},[27,3784,3785],{},"Versionado formal de API."," Soportas v1 y v2 simultáneamente, con fecha de descontinuación anunciada. Cabecera ",[231,3788,3789],{},"Accept-Version"," o ruta ",[231,3792,3793],{},"\u002Fv2\u002F",". Cliente legacy no puede romperse.",[70,3796,3797,3800],{},[27,3798,3799],{},"Autenticación compleja."," Validación de JWT emitido por tercero, con claves públicas bajadas y cacheadas, con rotación automática. OAuth con varios proveedores. Autenticación por certificado de cliente (mTLS) para integraciones entre empresas.",[70,3802,3803,3806],{},[27,3804,3805],{},"Portal de desarrollador con tentar-aquí."," Documentación interactiva, gestión de clave self-service, panel de uso para el consumidor.",[70,3808,3809,3812],{},[27,3810,3811],{},"Métricas por clave de API."," Quién llama qué, cuándo, latencia por consumidor. Dashboards comerciales, informes de uso, SLA por cliente.",[12,3814,3815],{},"Tres o más de esos criterios verdaderos, gateway es defendible. Uno o dos, aún se puede resolver de otras formas (autenticación en la aplicación, límite por aplicación, métricas estructuradas en el log).",[19,3817,3819],{"id":3818},"router-integrado-de-heroctl-donde-queda-en-esa-regla","Router integrado de HeroCtl — dónde queda en esa regla",[12,3821,3822],{},"El router embebido en HeroCtl no intenta ser gateway. Cubre el lado de reverse proxy bien hecho: HTTPS terminado, Let's Encrypt automático con renovación, enrutamiento por host y ruta, balanceo entre las réplicas que el orquestador subió, health check coordinado con el agente en cada nodo, compresión, cabeceras de proxy, límite básico por IP, política de reintento en caso de fallo de back-end.",[12,3824,3825,3826,3828],{},"Lo que el router integrado ",[27,3827,100],{}," hace: validación de clave de API por consumidor, límite por clave\u002Fusuario, transformación de cuerpo, agregación de back-ends, validación de esquema OpenAPI, portal de desarrollador. Para los 80% de los casos donde el cliente final es navegador o app mobile de la propia empresa, el router embebido cubre el camino de entrada entero — no instalas nada más al frente.",[12,3830,3831],{},"Para los 20% que necesitan gateway dedicado, el camino es directo: instala Kong, Traefik standalone, Tyk o KrakenD como un job más en el cluster, detrás del router embebido. El router termina TLS en la borda, el gateway hace el trabajo de gateway, los back-ends quedan detrás. Sin ceremonia, sin dependencia circular.",[12,3833,3834],{},"El plano de control de HeroCtl ocupa entre 200 y 400 MB por servidor — o sea, un Kong instalado añade prácticamente el mismo peso del plano de control entero. Vale recordar el orden de magnitud antes de \"solo instalar\".",[19,3836,3838],{"id":3837},"tabla-comparativa-12-criterios","Tabla comparativa — 12 criterios",[119,3840,3841,3868],{},[122,3842,3843],{},[125,3844,3845,3847,3850,3853,3856,3859,3862,3865],{},[128,3846,2983],{},[128,3848,3849],{},"Reverse proxy simple (Caddy\u002Fnginx)",[128,3851,3852],{},"Router HeroCtl",[128,3854,3855],{},"Traefik standalone",[128,3857,3858],{},"KrakenD",[128,3860,3861],{},"Tyk OSS",[128,3863,3864],{},"Kong OSS",[128,3866,3867],{},"Envoy Gateway",[141,3869,3870,3896,3920,3941,3960,3979,3998,4018,4037,4058,4079,4100],{},[125,3871,3872,3875,3878,3881,3884,3887,3890,3893],{},[146,3873,3874],{},"RAM mínima",[146,3876,3877],{},"20–50 MB",[146,3879,3880],{},"embebido en el plano de control",[146,3882,3883],{},"50–100 MB",[146,3885,3886],{},"~50 MB",[146,3888,3889],{},"~100 MB",[146,3891,3892],{},"~200 MB",[146,3894,3895],{},"~100 MB + plano de control",[125,3897,3898,3901,3904,3906,3909,3912,3915,3917],{},[146,3899,3900],{},"Latencia añadida",[146,3902,3903],{},"\u003C 0,5 ms",[146,3905,3903],{},[146,3907,3908],{},"0,5–1 ms",[146,3910,3911],{},"~0,5 ms",[146,3913,3914],{},"1–2 ms",[146,3916,3914],{},[146,3918,3919],{},"\u003C 1 ms (puede crecer)",[125,3921,3922,3925,3928,3930,3932,3935,3937,3939],{},[146,3923,3924],{},"Certificados automáticos",[146,3926,3927],{},"Sí (Caddy nativo)",[146,3929,3065],{},[146,3931,3065],{},[146,3933,3934],{},"No directo",[146,3936,3065],{},[146,3938,3065],{},[146,3940,3065],{},[125,3942,3943,3946,3948,3950,3952,3954,3956,3958],{},[146,3944,3945],{},"Enrutamiento host\u002Fruta",[146,3947,3065],{},[146,3949,3065],{},[146,3951,3065],{},[146,3953,3065],{},[146,3955,3065],{},[146,3957,3065],{},[146,3959,3065],{},[125,3961,3962,3965,3967,3969,3971,3973,3975,3977],{},[146,3963,3964],{},"Balanceo + health",[146,3966,3065],{},[146,3968,3065],{},[146,3970,3065],{},[146,3972,3065],{},[146,3974,3065],{},[146,3976,3065],{},[146,3978,3065],{},[125,3980,3981,3984,3986,3988,3990,3992,3994,3996],{},[146,3982,3983],{},"Límite por IP",[146,3985,3065],{},[146,3987,3065],{},[146,3989,3065],{},[146,3991,3065],{},[146,3993,3065],{},[146,3995,3065],{},[146,3997,3065],{},[125,3999,4000,4003,4005,4007,4010,4012,4014,4016],{},[146,4001,4002],{},"Límite por clave\u002Fusuario",[146,4004,3059],{},[146,4006,3059],{},[146,4008,4009],{},"Sí (con middleware)",[146,4011,3065],{},[146,4013,3065],{},[146,4015,3065],{},[146,4017,3065],{},[125,4019,4020,4023,4025,4027,4029,4031,4033,4035],{},[146,4021,4022],{},"Validación de JWT",[146,4024,3059],{},[146,4026,3059],{},[146,4028,3140],{},[146,4030,3065],{},[146,4032,3065],{},[146,4034,3065],{},[146,4036,3065],{},[125,4038,4039,4042,4044,4046,4048,4051,4053,4056],{},[146,4040,4041],{},"Agregación de back-ends",[146,4043,3059],{},[146,4045,3059],{},[146,4047,3059],{},[146,4049,4050],{},"Sí (foco)",[146,4052,3140],{},[146,4054,4055],{},"Sí (con plug-in)",[146,4057,3065],{},[125,4059,4060,4063,4065,4067,4069,4072,4074,4077],{},[146,4061,4062],{},"Validación OpenAPI",[146,4064,3059],{},[146,4066,3059],{},[146,4068,3059],{},[146,4070,4071],{},"Sí (suscriptor)",[146,4073,3065],{},[146,4075,4076],{},"Sí (plug-in)",[146,4078,3065],{},[125,4080,4081,4084,4086,4088,4090,4092,4095,4098],{},[146,4082,4083],{},"Portal de desarrollador",[146,4085,3059],{},[146,4087,3059],{},[146,4089,3059],{},[146,4091,3059],{},[146,4093,4094],{},"Sí (incluido)",[146,4096,4097],{},"Sí (pagado en el OSS robusto)",[146,4099,3059],{},[125,4101,4102,4105,4108,4111,4114,4116,4119,4122],{},[146,4103,4104],{},"Configuración",[146,4106,4107],{},"Archivo",[146,4109,4110],{},"Panel + API",[146,4112,4113],{},"Etiquetas\u002Farchivo",[146,4115,4107],{},[146,4117,4118],{},"Archivo + panel",[146,4120,4121],{},"Archivo + panel + base",[146,4123,4124],{},"Custom Resources",[12,4126,4127,4128,4131],{},"La tabla tiene zonas claras. Las tres primeras columnas resuelven el camino de entrada con peso bajo. Las cuatro últimas resuelven camino de entrada ",[27,4129,4130],{},"más"," trabajo de gateway, con peso y complejidad crecientes.",[19,4133,4135],{"id":4134},"stack-tipica-por-etapa-de-la-empresa","Stack típica por etapa de la empresa",[12,4137,4138],{},"Esta es la regla que recomendamos. No es prescripción rígida — es lo que vemos funcionar en equipos de SaaS.",[12,4140,4141,4144],{},[27,4142,4143],{},"MVP (1 back-end, 1 desarrollador)."," Caddy standalone en un servidor, o router embebido si ya estás en orquestador. No instalas nada. No piensas en gateway. Foco en el producto.",[12,4146,4147,4150],{},[27,4148,4149],{},"Indie hacker (3 a 5 back-ends, equipo de 1 a 3)."," Router embebido en el orquestador, punto. El camino de entrada ya cubre lo que importa. Autenticación en la aplicación, límite básico por IP en el proxy. Tiempo gastado con gateway es tiempo no gastado en feature del producto.",[12,4152,4153,4156],{},[27,4154,4155],{},"Startup early (10 a 20 back-ends, primeros consumidores externos de la API)."," Hora de evaluar. Si la API externa es experimento que aún puede morir, deja la autenticación en la aplicación y límite por clave en una biblioteca compartida. Si la API es parte central de la promesa del producto, instala Traefik standalone con middlewares de autenticación y límite, o Tyk OSS por el portal incluido. Kong en esta fase suele ser pesado de más.",[12,4158,4159,4162],{},[27,4160,4161],{},"Startup mid (50+ back-ends, plataforma de API pública se vuelve producto)."," Kong OSS o Tyk pagado. Necesitas plug-ins, portal robusto, gestión de clave self-service, métricas comerciales. El peso de Kong ahora se justifica — estás cobrando por uso de API y el gateway es ingreso, no coste.",[12,4164,4165,4168],{},[27,4166,4167],{},"Empresa grande (cientos de servicios, integraciones con socios serios)."," Kong Enterprise o Envoy Gateway, dependiendo del contexto. Equipo dedicado cuidando del gateway. Política formal de versionado, descontinuación, SLA por cliente.",[12,4170,4171],{},"La migración natural — reverse proxy → Traefik\u002FTyk → Kong — funciona porque cada peldaño resuelve dolor real del peldaño anterior. Saltar peldaños es caro: instalar Kong en la fase de MVP es poner un camión para entregar una pizza.",[19,4173,4175],{"id":4174},"los-4-errores-caros-mas-comunes-con-gateway","Los 4 errores caros más comunes con gateway",[12,4177,4178],{},"Los tropiezos que vemos en producción:",[12,4180,4181,4184],{},[27,4182,4183],{},"Instalar Kong con PostgreSQL en el camino crítico sin necesidad."," El modo sin-base existe y es perfecto para la mayoría de los casos. Configuración declarativa vía archivo, sin dependencia externa, sin punto extra de fallo. Muchos equipos caen en la configuración por defecto con base y descubren eso solo cuando la base queda indisponible y el gateway no consigue más propagar cambios. Si necesitas gestión dinámica de claves (consumidores registrándose self-service), base compensa. Si no, modo sin-base.",[12,4186,4187,4190],{},[27,4188,4189],{},"No monitorizar el gateway con la misma severidad que los back-ends."," Gateway al frente se vuelve caja-negra de fácil olvido. Latencia crece 5 ms, tasa de error va de 0,01% a 0,5%, nadie lo nota hasta que el cliente reclama. Métricas de gateway (latencia por ruta, tasa de error 4xx\u002F5xx, uso de memoria, lag de propagación de configuración) merecen dashboard propio y alertas, no solo inclusión tímida en el panel general.",[12,4192,4193,4196],{},[27,4194,4195],{},"Plug-in customizado en Lua\u002FJS corriendo en producción."," Kong permite plug-in customizado en Lua. Tyk en JavaScript. Tentación enorme para resolver \"solo esa transformación\" en el gateway. Bug en ese plug-in derriba el gateway entero — bug que tú creaste, sin test de carga, en el camino crítico de todo. Si necesitas transformación custom, hazla en micro-servicio detrás del gateway. Plug-in customizado solo con revisión seria, test de carga, y plan de rollback automático.",[12,4198,4199,4202],{},[27,4200,4201],{},"Versión del gateway desactualizada."," Kong, Envoy y Tyk reciben CVEs (vulnerabilidades de seguridad) con regularidad. Gateway está expuesto a internet — superficie de ataque relevante. Versión de hace 18 meses es vulnerabilidad conocida acumulando. Hazlo parte del ciclo de mantenimiento: actualizar el gateway es tan importante como actualizar el sistema operativo.",[19,4204,4206],{"id":4205},"escenarios-reales-en-los-que-no-instalar-gateway","Escenarios reales en los que NO instalar gateway",[12,4208,4209],{},"Lista fuerte. Si estás en alguno de estos, evita el gateway dedicado aunque el tema aparezca en el consejo:",[2735,4211,4212,4218,4224,4230,4236],{},[70,4213,4214,4217],{},[27,4215,4216],{},"SaaS web con 5 endpoints, sin API externa pública."," Cliente final es el navegador. Autenticación por sesión. Reverse proxy resuelve el camino de entrada entero. Añadir gateway aquí es vanidad arquitectónica.",[70,4219,4220,4223],{},[27,4221,4222],{},"Equipo pequeño (1 a 3 desarrolladores)."," Curva de aprendizaje de Kong cuesta de dos a cuatro semanas de productividad total del equipo. En equipo de 3 personas, eso es trimestre de feature parado. A no ser que el gateway resuelva dolor concreto hoy, posponlo.",[70,4225,4226,4229],{},[27,4227,4228],{},"Workload donde latencia sub-10ms es requisito duro."," Trading de baja latencia, subasta en tiempo real, juego multijugador. Cada milisegundo cuenta. Gateway añade 1 a 3 ms — en workload sensible, es caro. Coloca la inteligencia en la aplicación.",[70,4231,4232,4235],{},[27,4233,4234],{},"Aplicación monolítica sin agregación."," El monolito atiende al front-end directo, sin composición entre servicios. No hay qué agregar. Gateway es solución buscando problema.",[70,4237,4238,4241],{},[27,4239,4240],{},"Cumplimiento que prefiere superficie de ataque mínima."," Cada componente expuesto a internet es un item más para auditoría, un parche más a aplicar, un log más a guardar. Si la auditoría valora minimalismo, justifica cada componente — gateway que no cubre dolor concreto es minus.",[19,4243,4245],{"id":4244},"preguntas-frecuentes","Preguntas frecuentes",[12,4247,4248,4251,4252,4255],{},[27,4249,4250],{},"¿Kong sin base es estable en 2026?","\nSí. El modo declarativo (",[231,4253,4254],{},"db_less = on",") es maduro, recomendado por el propio Kong para gran parte de los casos, y elimina PostgreSQL como dependencia. Pierdes gestión dinámica de clave vía API admin (necesitas hacer deploy de configuración nueva), pero ganas simplicidad operacional enorme. Para equipo pequeño, el cambio casi siempre vale.",[12,4257,4258,4261],{},[27,4259,4260],{},"¿Traefik hace todo lo que Kong hace?","\nNo. Traefik con middlewares cubre la mayoría de los casos comunes — autenticación básica, límite por clave simple, transformación de cabecera, reenvío de autenticación. No cubre catálogo de plug-ins de Kong, validación OpenAPI nativa, portal de desarrollador robusto, integraciones comerciales listas. Si tu dolor cabe en middleware de Traefik, queda en Traefik (más liviano, más simple). Si necesitas cosa del catálogo de Kong, Kong.",[12,4263,4264,4267],{},[27,4265,4266],{},"¿Puedo tener dos gateways en serie?","\nTécnicamente sí, en la práctica casi siempre es síntoma de organización confusa. Dos gateways = dos configuraciones para mantener, dos latencias sumadas, dos puntos de fallo. El caso defendible es: router de borda haciendo TLS y enrutamiento básico, gateway dedicado detrás haciendo trabajo específico (validación de clave, agregación). Eso es diferente de \"dos gateways completos en serie\" — es división de responsabilidad.",[12,4269,4270,4273,4274,101],{},[27,4271,4272],{},"¿API gateway sustituye malla de servicio?","\nNo. Gateway cuida del tráfico norte-sur (cliente externo → tu sistema). Malla cuida del tráfico este-oeste (servicio interno → servicio interno). Funciones parecidas (autenticación, límite, observabilidad) pero alcance diferente. Para startup media, gateway resuelve la parte que importa; malla de servicio completa solo se vuelve inversión defendible en escala mayor. Tratamos ese límite en ",[3337,4275,4277],{"href":4276},"\u002Fes\u002Fblog\u002Fservice-mesh-cuando-vale-la-pena-en-saas-pequeno","service mesh: cuándo vale la pena en SaaS pequeño y mediano",[12,4279,4280,4283],{},[27,4281,4282],{},"¿Cuánta latencia añade Kong en llamada típica?","\nEn hardware moderno, con configuración por defecto y plug-ins livianos (validación de clave + límite por clave): 1 a 2 milisegundos por petición. Plug-ins pesados (validación OpenAPI completa en payload grande, transformación JSON compleja, log síncrono a servicio externo) pueden sumar 3 a 10 ms. Mide antes y después — no confíes en número de blog post genérico.",[12,4285,4286,4289],{},[27,4287,4288],{},"Proveedor de OAuth auto-hospedado — ¿Keycloak o Hydra?","\nKeycloak es el estándar para quien quiere panel de administración robusto, federación con LDAP\u002FSAML, gestión de usuario completa. Pesa más (1 GB de RAM mínimo, JVM). Hydra es minimalista, se enfoca solo en OAuth\u002FOIDC, sin gestión de usuario (integras con tu sistema de usuarios existente). Para equipo pequeño que ya tiene sistema de usuario propio, Hydra es más adecuado. Para empresa que quiere un único lugar para identidad, Keycloak. Los dos hablan protocolos estándar, así que el gateway no diferencia entre ellos.",[12,4291,4292,4295],{},[27,4293,4294],{},"Validación de esquema — ¿OpenAPI o JSON Schema?","\nOpenAPI (anteriormente Swagger) es el estándar para describir API HTTP — engloba rutas, métodos, petición y respuesta. Incluye JSON Schema para describir payloads. Kong, Tyk y validadores standalone hablan OpenAPI directo. JSON Schema puro es más portable (no atado a HTTP) pero exige más pegamento. Usa OpenAPI cuando el gateway lo soporte; vale tener el esquema del contrato vivo, no desactualizado.",[12,4297,4298,4301,4302,4305,4306,4309],{},[27,4299,4300],{},"¿Puedo hacer límite en la aplicación en lugar del gateway?","\nPuedes. Bibliotecas como ",[231,4303,4304],{},"golang.org\u002Fx\u002Ftime\u002Frate"," o Redis con ",[231,4307,4308],{},"INCR"," resuelven límite por usuario a nivel de la aplicación. La cuestión es dónde el límite es más barato: en el gateway, antes de que el back-end sea tocado (ahorra recursos del back-end, aplica antes del trabajo empezar) o en la aplicación, con regla de negocio más cerca del código (más fácil de razonar, más fácil de testear). Para límite simple, aplicación basta. Para límite por plan comercial con múltiples niveles y auditoría, gateway es el lugar correcto.",[12,4311,4312,4315],{},[27,4313,4314],{},"¿Puedo usar dos gateways diferentes en rutas distintas?","\nPuedes. Algunas empresas corren Kong para rutas \"producto\" (API pública vendida) y Traefik para rutas \"interno\" (admin, ops, cron). La justificación es que cada gateway resuelve un dolor diferente, y tener uno solo forzaría compromiso. Vale cuando los perfiles de uso de hecho divergen. No vale solo por el placer de tener variedad — dos piezas para mantener.",[19,4317,4319],{"id":4318},"cierre-empieza-por-el-minimo-sube-cuando-el-dolor-sea-real","Cierre — empieza por el mínimo, sube cuando el dolor sea real",[12,4321,4322],{},"La trampa de la categoría \"API gateway\" es tratar la decisión como binaria — instalar o no — cuando es gradual. Reverse proxy bien hecho cubre 80% de las aplicaciones. Router integrado en el orquestador cubre las mismas 80% sin componente separado. Gateway dedicado es inversión defendible cuando aparecen tres o cuatro señales simultáneas: API externa pública, límite por clave, agregación, portal de desarrollador.",[12,4324,4325],{},"La regla honesta: instala el mínimo hasta que el dolor concreto fuerce el siguiente peldaño. Saltar peldaños cuesta caro en latencia, RAM, complejidad, área de fallo. Equipo pequeño que instala Kong \"porque va a necesitar\" pasa tres semanas configurando algo que no usa, y aún así tiene un componente más para monitorizar.",[12,4327,4328],{},"HeroCtl entrega el peldaño más bajo embebido — router integrado con TLS automático, balanceo, health check, límite por IP. Cuando el dolor de gateway aparezca de verdad, subes Kong, Traefik standalone, Tyk o KrakenD como un job más en el cluster. Sin migración dolorosa, sin ceremonia.",[12,4330,4331],{},"Para subir un cluster y probar:",[224,4333,4334],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,4335,4336],{"__ignoreMap":229},[234,4337,4338,4340,4342,4344,4346],{"class":236,"line":237},[234,4339,1220],{"class":247},[234,4341,2958],{"class":251},[234,4343,2961],{"class":255},[234,4345,2964],{"class":383},[234,4347,2967],{"class":247},[12,4349,4350,4353,4354,4357,4358,4361],{},[27,4351,4352],{},"Community"," es gratuito para siempre, sin techo de servidores, sin techo de jobs, sin feature gate. ",[27,4355,4356],{},"Business"," añade SSO\u002FSAML, RBAC granular, auditoría detallada y soporte con SLA. ",[27,4359,4360],{},"Enterprise"," suma escrow de código fuente, contrato de continuidad y soporte 24×7.",[12,4363,4364,4365,2403,4367,4371],{},"Posts próximos: ",[3337,4366,4277],{"href":4276},[3337,4368,4370],{"href":4369},"\u002Fes\u002Fblog\u002Fmulti-tenant-saas-aislamiento-real","multi-tenant SaaS: aislamiento real entre clientes",". Los tres temas juntos cubren la mayor parte de las decisiones de plataforma para startup en la franja de 1 a 500 servidores.",[12,4373,4374],{},"Orquestación de contenedores, sin ceremonia. Gateway solo cuando el dolor lo pida.",[3351,4376,4377],{},"html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":229,"searchDepth":244,"depth":244,"links":4379},[4380,4381,4382,4389,4390,4391,4392,4393,4394,4395,4396,4397],{"id":3409,"depth":244,"text":3410},{"id":3430,"depth":244,"text":3431},{"id":3588,"depth":244,"text":3589,"children":4383},[4384,4385,4386,4387,4388],{"id":3595,"depth":271,"text":3596},{"id":3620,"depth":271,"text":3621},{"id":3642,"depth":271,"text":3643},{"id":3664,"depth":271,"text":3665},{"id":3686,"depth":271,"text":3687},{"id":3708,"depth":244,"text":3709},{"id":3756,"depth":244,"text":3757},{"id":3818,"depth":244,"text":3819},{"id":3837,"depth":244,"text":3838},{"id":4134,"depth":244,"text":4135},{"id":4174,"depth":244,"text":4175},{"id":4205,"depth":244,"text":4206},{"id":4244,"depth":244,"text":4245},{"id":4318,"depth":244,"text":4319},"2026-06-03","El API gateway resuelve auth, rate limit, transformaciones y observabilidad — a cambio de un componente crítico más. Cuándo basta un reverse proxy simple vs cuándo vale el gateway dedicado.",{},"\u002Fes\u002Fblog\u002Fapi-gateway-auto-hospedado-cuando-instalar","13 min",{"title":3398,"description":4399},{"loc":4401},"es\u002Fblog\u002Fapi-gateway-auto-hospedado-cuando-instalar",[4407,4408,4409,3379,4410],"api-gateway","kong","traefik","arquitectura","DQw030gmc7XmXLeSlClU41twoCW00I44K4a7nhuqWGQ",{"id":4413,"title":4414,"author":7,"body":4415,"category":3379,"cover":3380,"date":5369,"description":5370,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":5371,"navigation":411,"path":4276,"readingTime":4402,"seo":5372,"sitemap":5373,"stem":5374,"tags":5375,"__hash__":5379},"blog_es\u002Fes\u002Fblog\u002Fservice-mesh-cuando-vale-la-pena-en-saas-pequeno.md","¿Service mesh es overkill en SaaS pequeño? Cuándo vale instalar Istio\u002FLinkerd",{"type":9,"value":4416,"toc":5351},[4417,4420,4424,4427,4430,4434,4437,4527,4530,4534,4537,4576,4579,4583,4586,4620,4623,4627,4630,4706,4709,4735,4738,4742,4745,4762,4765,4772,4776,4779,4782,4802,4805,4819,4822,4826,4829,5027,5034,5038,5041,5067,5070,5074,5077,5109,5113,5116,5142,5145,5149,5152,5172,5175,5179,5182,5202,5205,5209,5212,5249,5251,5257,5266,5272,5278,5284,5290,5296,5302,5308,5310,5313,5316,5334,5346,5349],[12,4418,4419],{},"La pregunta llega siempre con el mismo formato. Un tech lead de un SaaS con seis u ocho servicios corriendo lee tres posts en inglés sobre malla de servicio, ve a toda la industria americana usando Istio, y abre el terminal para instalar — junto con la duda: \"¿esto no es demasiado para el tamaño de mi empresa?\". Probablemente lo es. Pero la respuesta honesta exige separar cuatro problemas que la malla de servicio resuelve, mostrar el coste en RAM y CPU por servidor, y describir el punto exacto en que el beneficio pasa a superar el overhead.",[19,4421,4423],{"id":4422},"tldr-service-mesh-vale-la-pena-en-saas-pequenomediano","TL;DR — ¿Service mesh vale la pena en SaaS pequeño\u002Fmediano?",[12,4425,4426],{},"Malla de servicio (Istio, Linkerd, Cilium Service Mesh, Consul Connect) resuelve cuatro problemas reales entre servicios de una arquitectura de microservicios: cifrado automático (llamada entre pods sin TLS por default filtra tráfico en texto puro), retries y circuit breakers (resiliencia configurable), observabilidad granular (qué servicio llama a cuál, con qué latencia), y traffic shaping para canary releases. A cambio, añade un proxy paralelo en cada pod (normalmente Envoy) que consume entre 50 y 100 MB de RAM y añade 5 a 10 ms de latencia por llamada interna.",[12,4428,4429],{},"Para startup con menos de diez servicios activos y menos de cincuenta pods, malla de servicio es overkill — el overhead operacional supera el beneficio, y el equipo gasta semanas estudiando una capa que resuelve un problema que aún no tiene. Para empresa con cincuenta o más microservicios donde diagnosticar \"¿qué servicio está atrasando la llamada?\" lleva horas, malla paga en productividad. El término medio son clusters con cifrado entre servicios embebido en el propio plano de control — cubren cerca de 60% de lo que malla ofrece sin el sidecar paralelo, y atienden la mayoría de los casos hasta el rango de los treinta servicios.",[19,4431,4433],{"id":4432},"lo-que-service-mesh-resuelve-en-una-frase","Lo que service mesh resuelve, en una frase",[12,4435,4436],{},"Antes de discutir coste, es necesario ser claro sobre lo que está siendo comprado. Malla de servicio es una capa de red que se entromete en cada llamada entre servicios y añade seis comportamientos:",[2735,4438,4439,4452,4464,4476,4503,4512],{},[70,4440,4441,4444,4445,2630,4448,4451],{},[27,4442,4443],{},"Cifrado automático entre pods."," Sin malla, una llamada de ",[231,4446,4447],{},"pedidos",[231,4449,4450],{},"usuarios"," dentro del cluster transita en HTTP simple. Cualquier agente con acceso a la red del nodo ve el contenido. Con malla, cada llamada es cifrada con certificados emitidos automáticamente, sin alteración en el código de la aplicación.",[70,4453,4454,4457,4458,4460,4461,4463],{},[27,4455,4456],{},"Retries automáticos en llamadas internas."," Cuando ",[231,4459,4447],{}," llama a ",[231,4462,4450],{}," y el primer intento falla por una flap de red de 200 ms, la malla reenvía. Sin malla, la aplicación necesita implementar esa lógica en cada cliente HTTP que crea.",[70,4465,4466,4469,4470,4472,4473,4475],{},[27,4467,4468],{},"Circuit breakers configurables."," Si ",[231,4471,4450],{}," empieza a responder con latencia de cinco segundos, la malla abre el circuito y hace que ",[231,4474,4447],{}," falle rápido en lugar de apilar conexiones. Sin malla, el equipo necesita añadir una biblioteca en cada servicio.",[70,4477,4478,4481,4482,571,4485,4488,4489,4491,4492,4494,4495,2403,4497,4500,4501,101],{},[27,4479,4480],{},"Distributed tracing automático."," La malla propaga cabeceras de correlación (",[231,4483,4484],{},"x-request-id",[231,4486,4487],{},"traceparent",") por toda la cadena de llamadas. El equipo consigue ver, en un panel, que un request entró en el ",[231,4490,4407],{},", pasó por ",[231,4493,4447],{},", llamó a ",[231,4496,4450],{},[231,4498,4499],{},"stock",", y gastó la mayor parte del tiempo en ",[231,4502,4499],{},[70,4504,4505,4508,4509,4511],{},[27,4506,4507],{},"Traffic shaping fino."," Encaminar 5% del tráfico de ",[231,4510,4447],{}," a una versión nueva (canary), espejar 100% a una versión de test sin afectar al cliente (mirror), o alternar entre dos versiones enteras (blue-green) — todo configurado declarativamente, sin código.",[70,4513,4514,4517,4518,2403,4520,4523,4524,4526],{},[27,4515,4516],{},"Authorization policies entre servicios."," Declarar que solo ",[231,4519,4447],{},[231,4521,4522],{},"reportes"," pueden llamar a ",[231,4525,4450],{},", y cualquier otro servicio recibe 403. Es la base de la llamada \"red zero-trust\" entre pods.",[12,4528,4529],{},"Esos seis comportamientos son reales y el valor es mensurable. La pregunta es si tu cluster de hoy tiene volumen y complejidad suficientes para justificar pagar por ellos.",[19,4531,4533],{"id":4532},"lo-que-no-es-problema-de-service-mesh","Lo que NO es problema de service mesh",[12,4535,4536],{},"Antes de avanzar, vale la pena eliminar cuatro problemas que muchos equipos confunden con motivo para instalar malla — y que orquestador moderno ya resuelve solo:",[2735,4538,4539,4551,4557,4566],{},[70,4540,4541,4544,4545,4547,4548,4550],{},[27,4542,4543],{},"Enrutamiento de entrada (ingress HTTP)."," Recibir tráfico externo, terminar TLS, rutear ",[231,4546,3456],{}," a un servicio y ",[231,4549,3460],{}," a otro. Eso es trabajo de router integrado al orquestador, no de malla.",[70,4552,4553,4556],{},[27,4554,4555],{},"Balanceo de carga simple."," Distribuir requests entre tres réplicas de un mismo servicio con round-robin. Orquestador hace eso con DNS interno y health checks. Malla agrega solo cuando la política de balanceo necesita ser sofisticada (peso por región, sticky sessions complejas).",[70,4558,4559,4562,4563,4565],{},[27,4560,4561],{},"Service discovery."," Encontrar dónde ",[231,4564,4450],{}," está corriendo. DNS interno del cluster resuelve. Malla no trae nada nuevo aquí.",[70,4567,4568,4571,4572,4575],{},[27,4569,4570],{},"Terminación HTTP\u002FHTTPS en la borda."," Ingress controller resuelve. Malla cuida del tráfico ",[179,4573,4574],{},"entre"," servicios, no de la entrada.",[12,4577,4578],{},"Quien instala malla esperando que resuelva esos cuatro está pagando dos veces por el mismo trabajo.",[19,4580,4582],{"id":4581},"los-cuatro-jugadores-principales","Los cuatro jugadores principales",[12,4584,4585],{},"Cuatro productos dominan esa categoría en 2026. Las diferencias importan cuando el tradeoff es overhead vs features.",[2735,4587,4588,4598,4608,4614],{},[70,4589,4590,4593,4594,4597],{},[27,4591,4592],{},"Istio."," El más antiguo, más completo, más documentado — y más pesado. Usa Envoy como sidecar en cada pod. Patrón de facto en empresas grandes que adoptaron malla entre 2019 y 2022. La versión Ambient Mode (sin sidecar, con ",[231,4595,4596],{},"ztunnel"," por nodo) reduce overhead, pero aún está estabilizando en producción.",[70,4599,4600,4603,4604,4607],{},[27,4601,4602],{},"Linkerd."," Foco en simplicidad. Proxy propio escrito en Rust (",[231,4605,4606],{},"linkerd2-proxy","), bien más ligero que Envoy. Curva de aprendizaje corta — instalación cabe en un par de comandos. CNCF graduado, pero con comunidad menor que Istio.",[70,4609,4610,4613],{},[27,4611,4612],{},"Cilium Service Mesh."," Aprovecha eBPF en el kernel para implementar buena parte de la malla sin sidecar. Overhead por pod cerca de cero. A cambio, el setup del cluster necesita kernel reciente y CNI compatible, y algunas features avanzadas (como autorización L7 sofisticada) aún dependen de proxy auxiliar.",[70,4615,4616,4619],{},[27,4617,4618],{},"Consul Connect."," De Hashicorp. Integra con la caja fuerte de secretos de la propia casa, y funciona bien en ambientes mixtos (VMs + contenedores). Comunidad menor que Istio\u002FLinkerd.",[12,4621,4622],{},"Existen otros (Kuma, Open Service Mesh, AWS App Mesh), pero concentrar en el cuarteto arriba cubre 95% de las decisiones reales que un tech lead va a enfrentar.",[19,4624,4626],{"id":4625},"cuanto-cuesta-en-ram-y-cpu","¿Cuánto cuesta en RAM y CPU?",[12,4628,4629],{},"La pregunta que decide la discusión.",[119,4631,4632,4648],{},[122,4633,4634],{},[125,4635,4636,4639,4642,4645],{},[128,4637,4638],{},"Malla",[128,4640,4641],{},"RAM por pod",[128,4643,4644],{},"CPU por pod",[128,4646,4647],{},"Latencia adicional",[141,4649,4650,4664,4678,4692],{},[125,4651,4652,4655,4658,4661],{},[146,4653,4654],{},"Istio (Envoy sidecar)",[146,4656,4657],{},"+80–120 MB",[146,4659,4660],{},"+10–15%",[146,4662,4663],{},"5–10 ms",[125,4665,4666,4669,4672,4675],{},[146,4667,4668],{},"Linkerd (linkerd2-proxy Rust)",[146,4670,4671],{},"+20–40 MB",[146,4673,4674],{},"+3–6%",[146,4676,4677],{},"1–3 ms",[125,4679,4680,4683,4686,4689],{},[146,4681,4682],{},"Cilium Service Mesh (eBPF)",[146,4684,4685],{},"~0 MB por pod",[146,4687,4688],{},"~2% en el nodo",[146,4690,4691],{},"\u003C1 ms",[125,4693,4694,4697,4700,4703],{},[146,4695,4696],{},"Consul Connect (Envoy sidecar)",[146,4698,4699],{},"+70–110 MB",[146,4701,4702],{},"+8–12%",[146,4704,4705],{},"4–8 ms",[12,4707,4708],{},"En cluster con cien pods activos:",[2735,4710,4711,4717,4723,4729],{},[70,4712,4713,4716],{},[27,4714,4715],{},"Istio"," consume cerca de 10 GB de RAM solo en proxies paralelos, antes de cualquier aplicación.",[70,4718,4719,4722],{},[27,4720,4721],{},"Linkerd"," consume cerca de 3 GB.",[70,4724,4725,4728],{},[27,4726,4727],{},"Cilium"," consume casi nada por pod, pero exige un agente por nodo (cerca de 200–400 MB cada).",[70,4730,4731,4734],{},[27,4732,4733],{},"Consul Connect"," queda cerca de Istio.",[12,4736,4737],{},"Para cluster típico de startup — cuatro servidores con 4 GB de RAM cada, totalizando 16 GB — Istio solo ocupa un tercio de la memoria del cluster antes de que ninguna línea de código corra. Linkerd ocupa un quinto. Cilium ocupa casi nada por pod, pero exige planificación de CNI.",[19,4739,4741],{"id":4740},"mi-startup-necesita-esto","¿Mi startup necesita esto?",[12,4743,4744],{},"Respuesta directa: probablemente no. Los criterios honestos para \"necesita\":",[2735,4746,4747,4750,4753,4756,4759],{},[70,4748,4749],{},"Treinta o más microservicios activos en producción.",[70,4751,4752],{},"Tráfico entre servicios es más de 50% del volumen HTTP total del cluster.",[70,4754,4755],{},"Más de un incidente al mes relacionado con \"qué servicio cayó, atrasó o está reventando timeout\".",[70,4757,4758],{},"Compliance formal exige red zero-trust entre pods (PCI-DSS nivel 1, ciertos contratos con Banco Central, frameworks de salud).",[70,4760,4761],{},"Equipo tiene al menos una persona dedicada a la plataforma, con tiempo para estudiar y operar la malla.",[12,4763,4764],{},"Si no pegas en al menos tres de esos cinco criterios, malla es overkill. La complejidad agregada no retorna en valor — retorna en llamadas en la guardia intentando entender por qué el sidecar está reciclando.",[12,4766,4767,4768,4771],{},"Criterio más importante y menos discutido: ",[27,4769,4770],{},"¿cuánto del tráfico es interno?",". Aplicación que recibe request en la borda, hace una única consulta en la base y responde, gasta 95% del tiempo entre cliente externo y base — no entre servicios. Aplicación que recibe request en la borda, llama a diez servicios internos para montar la respuesta, gasta la mayor parte del tiempo en el tráfico interno. Para la primera, malla no añade nada perceptible. Para la segunda, malla puede cortar horas de debugging por mes.",[19,4773,4775],{"id":4774},"el-sustituto-cluster-native","El sustituto cluster-native",[12,4777,4778],{},"Aquí vive la parte que el discurso americano subestima. En 2026, varios orquestadores modernos — incluyendo HeroCtl y algunas distribuciones del coloso ortodoxo — vienen con cifrado entre servicios embebido en el plano de control. Sin sidecar, sin proxy paralelo, sin instalar producto adicional.",[12,4780,4781],{},"Lo que eso cubre:",[2735,4783,4784,4790,4796],{},[70,4785,4786,4789],{},[27,4787,4788],{},"Cifrado entre servicios."," Cada servicio recibe certificado emitido automáticamente por el cluster. Llamada interna es cifrada por defecto.",[70,4791,4792,4795],{},[27,4793,4794],{},"Identidad de servicio."," Cada servicio se autentica por el certificado, no por IP o DNS.",[70,4797,4798,4801],{},[27,4799,4800],{},"Authorization básica."," Listas de quién puede llamar a quién, declarativas en el archivo de configuración del servicio.",[12,4803,4804],{},"Lo que eso NO cubre:",[2735,4806,4807,4810,4813,4816],{},[70,4808,4809],{},"Traffic shaping fino (canary con 5% de tráfico, mirror).",[70,4811,4812],{},"Distributed tracing completamente automático.",[70,4814,4815],{},"Circuit breakers configurables por llamada.",[70,4817,4818],{},"Políticas de retry sofisticadas.",[12,4820,4821],{},"Para startup mediana que estaba pensando en instalar malla solo para tener \"cifrado entre servicios\", el cluster-native ya basta. Cubre el tópico de auditoría más común sin costar 10 GB de RAM.",[19,4823,4825],{"id":4824},"lado-a-lado-sin-adornos","Lado a lado, sin adornos",[12,4827,4828],{},"La tabla compara Istio, Linkerd, Cilium y la opción de no instalar malla (con cifrado cluster-native activo) en doce criterios. No hay columna sin matiz.",[119,4830,4831,4847],{},[122,4832,4833],{},[125,4834,4835,4837,4839,4841,4844],{},[128,4836,2983],{},[128,4838,4715],{},[128,4840,4721],{},[128,4842,4843],{},"Cilium SM",[128,4845,4846],{},"Sin malla + cluster-native",[141,4848,4849,4863,4876,4891,4908,4924,4940,4953,4967,4981,4994,5010],{},[125,4850,4851,4854,4856,4858,4861],{},[146,4852,4853],{},"RAM overhead por pod",[146,4855,4657],{},[146,4857,4671],{},[146,4859,4860],{},"~0",[146,4862,4860],{},[125,4864,4865,4868,4870,4872,4874],{},[146,4866,4867],{},"CPU overhead por pod",[146,4869,4660],{},[146,4871,4674],{},[146,4873,4688],{},[146,4875,4860],{},[125,4877,4878,4881,4883,4885,4888],{},[146,4879,4880],{},"Complejidad de setup",[146,4882,3167],{},[146,4884,3155],{},[146,4886,4887],{},"Media (kernel)",[146,4889,4890],{},"Mínima",[125,4892,4893,4896,4899,4902,4905],{},[146,4894,4895],{},"Documentación en español",[146,4897,4898],{},"Buena",[146,4900,4901],{},"Razonable",[146,4903,4904],{},"Poca",[146,4906,4907],{},"Embebida en el orquestador",[125,4909,4910,4913,4916,4918,4921],{},[146,4911,4912],{},"Comunidad local",[146,4914,4915],{},"Grande",[146,4917,3160],{},[146,4919,4920],{},"Pequeña",[146,4922,4923],{},"Crece con el orquestador",[125,4925,4926,4929,4932,4935,4938],{},[146,4927,4928],{},"Sidecar paralelo",[146,4930,4931],{},"Sí (Envoy)",[146,4933,4934],{},"Sí (Rust)",[146,4936,4937],{},"No (eBPF)",[146,4939,3059],{},[125,4941,4942,4945,4947,4949,4951],{},[146,4943,4944],{},"Cifrado entre servicios automático",[146,4946,3065],{},[146,4948,3065],{},[146,4950,3065],{},[146,4952,3065],{},[125,4954,4955,4958,4960,4962,4964],{},[146,4956,4957],{},"Distributed tracing automático",[146,4959,3065],{},[146,4961,3065],{},[146,4963,3140],{},[146,4965,4966],{},"No (necesita OpenTelemetry)",[125,4968,4969,4972,4974,4976,4978],{},[146,4970,4971],{},"Traffic shaping fino (canary 5%)",[146,4973,3065],{},[146,4975,3065],{},[146,4977,3140],{},[146,4979,4980],{},"Básico (rolling, blue-green)",[125,4982,4983,4986,4988,4990,4992],{},[146,4984,4985],{},"Circuit breakers configurables",[146,4987,3065],{},[146,4989,3065],{},[146,4991,3062],{},[146,4993,3059],{},[125,4995,4996,4998,5001,5004,5007],{},[146,4997,3152],{},[146,4999,5000],{},"6–10 semanas",[146,5002,5003],{},"2–4 semanas",[146,5005,5006],{},"4–6 semanas",[146,5008,5009],{},"Días",[125,5011,5012,5015,5018,5021,5024],{},[146,5013,5014],{},"Rango de aplicación ideal",[146,5016,5017],{},"50+ servicios",[146,5019,5020],{},"10–50 servicios",[146,5022,5023],{},"30+ servicios con kernel nuevo",[146,5025,5026],{},"1–30 servicios",[12,5028,5029,5030,5033],{},"La columna que importa es la última línea — ",[27,5031,5032],{},"rango de aplicación ideal",". Quien está debajo del rango, paga overhead sin retorno. Quien está por encima, siente que falta feature.",[19,5035,5037],{"id":5036},"cuando-service-mesh-paga-el-precio","Cuándo service mesh paga el precio",[12,5039,5040],{},"Cuatro escenarios en que la inversión se justifica:",[2735,5042,5043,5049,5055,5061],{},[70,5044,5045,5048],{},[27,5046,5047],{},"Treinta o más microservicios activos."," La complejidad operacional sin malla se vuelve peor que con malla — diagnosticar una cadena de seis llamadas internas en tres equipos distintos es caro sin tracing automático.",[70,5050,5051,5054],{},[27,5052,5053],{},"Compliance enterprise con requisitos de zero-trust."," Algunos frameworks de auditoría piden que el stack tenga \"red zero-trust nominalmente\". Malla resuelve la checkbox formalmente.",[70,5056,5057,5060],{},[27,5058,5059],{},"Federación multi-cluster."," Enrutamiento de servicio entre dos o tres clusters en regiones distintas, con failover automático. Malla facilita ese escenario; cluster-native resuelve mal.",[70,5062,5063,5066],{},[27,5064,5065],{},"Equipo de plataforma con cinco o más personas dedicadas."," Tienes capacidad para extraer valor de la malla — operar, evolucionar, dimensionar el plano de control de ella. Sin ese equipo, la malla se vuelve pasivo.",[12,5068,5069],{},"Si pegas en dos o más de esos, empieza a evaluar. Empieza por Linkerd — es el que da menos dolor por menos retorno relativo perdido.",[19,5071,5073],{"id":5072},"cuando-no-instalar-la-mayoria-de-los-casos","Cuándo NO instalar (la mayoría de los casos)",[12,5075,5076],{},"Cinco escenarios en que instalar malla hoy cuesta más de lo que retorna:",[2735,5078,5079,5085,5091,5097,5103],{},[70,5080,5081,5084],{},[27,5082,5083],{},"Monolito con cinco a diez microservicios auxiliares."," Cero ganancia, coste grande. El overhead en RAM cae directamente en cuenta de servidor.",[70,5086,5087,5090],{},[27,5088,5089],{},"Equipo pequeño, menos de tres personas en plataforma."," Operar malla exige guardia dedicada para ella. Equipo pequeño absorbe ese coste a costa de feature de producto.",[70,5092,5093,5096],{},[27,5094,5095],{},"Cluster con menos de treinta pods totales."," Gestionar treinta pods es trabajo humano, no exige tracing automático. El coste de aprender la malla no retorna.",[70,5098,5099,5102],{},[27,5100,5101],{},"Workload HTTP simple sin requisitos de canary."," Si nunca necesitaste liberar 5% del tráfico a una versión nueva porque rolling update siempre sirvió, malla es solución para problema que no existe.",[70,5104,5105,5108],{},[27,5106,5107],{},"Coste de cluster bajo presión."," Si cada gigabyte de RAM está siendo contado, gastar 10 GB en sidecars es decisión difícil de defender al inversor.",[19,5110,5112],{"id":5111},"decision-evolutiva-por-etapa","Decisión evolutiva, por etapa",[12,5114,5115],{},"La decisión correcta cambia con el tamaño del sistema. Cuatro etapas:",[2735,5117,5118,5124,5130,5136],{},[70,5119,5120,5123],{},[27,5121,5122],{},"Etapa 1 — 1 a 10 servicios."," Sin malla. Si necesitas cifrado entre servicios, haz TLS en el código (la mayoría de los lenguajes tiene cliente HTTPS listo). No vale la pena el aprendizaje. Foca en entregar producto.",[70,5125,5126,5129],{},[27,5127,5128],{},"Etapa 2 — 10 a 30 servicios."," Cluster con cifrado embebido en el plano de control (HeroCtl, algunos presets del coloso). Resuelve cifrado + identidad + descubrimiento de servicio sin sidecar. Cubre la mayor parte de lo que malla ofrece, sin el coste.",[70,5131,5132,5135],{},[27,5133,5134],{},"Etapa 3 — 30 a 50 servicios con equipo de plataforma."," Evalúa Linkerd primero. Curva corta, overhead bajo, resuelve tracing y circuit breakers. Istio solo si features avanzadas (authorization L7 sofisticada, federación multi-cluster real) son requisito inmediato.",[70,5137,5138,5141],{},[27,5139,5140],{},"Etapa 4 — 50+ servicios, compliance enterprise."," Istio o Cilium Service Mesh. Compliance va a pedir una de las dos; resto son detalles.",[12,5143,5144],{},"Salir de una etapa a la próxima es decisión deliberada, no gradual. Añade el componente cuando el equipo acepta el aprendizaje y el cluster acepta el overhead. No antes.",[19,5146,5148],{"id":5147},"la-trampa-del-vamos-a-instalar-ahora-para-estar-preparado","La trampa del \"vamos a instalar ahora para estar preparado\"",[12,5150,5151],{},"Argumento que aparece en toda discusión: \"si voy a crecer a cincuenta servicios el año que viene, mejor instalar ahora y aprender\". La trampa tiene tres caras:",[2735,5153,5154,5160,5166],{},[70,5155,5156,5159],{},[27,5157,5158],{},"Aprender malla cuesta de cuatro a ocho semanas por persona del equipo."," En equipo de cinco, son veinte a cuarenta semanas-persona. Multiplicado por R$ 200\u002Fhora, da entre R$ 160 mil y R$ 320 mil solo en aprendizaje. Ese dinero adquiere feature o compra plazo de runway.",[70,5161,5162,5165],{},[27,5163,5164],{},"Cada componente nuevo es un punto de fallo crítico más."," Plano de control de la malla (Istio Pilot, Linkerd controller, Cilium operator) puede fallar y llevarse conectividad interna junto. Más componentes en quórum, más superficie de incidente. Añade solo cuando la ganancia compensa ese riesgo.",[70,5167,5168,5171],{},[27,5169,5170],{},"Cuando lo necesites, instalar lleva una semana, no un mes."," Linkerd en particular es instalable en un par de comandos. Cilium en algunas horas si el cluster acepta kernel reciente. Aplazar la decisión no es deuda técnica — es deuda aplazada con intereses menores.",[12,5173,5174],{},"No funciona \"anticipar para estar preparado\". Lo que funciona es monitorear los criterios objetivos de la sección anterior e instalar cuando dos o más se vuelvan realidad.",[19,5176,5178],{"id":5177},"como-heroctl-encara-el-problema","Cómo HeroCtl encara el problema",[12,5180,5181],{},"Nuestra posición es deliberada: malla de servicio, en la mayoría de los casos, es decisión para etapa tres o cuatro. Para cubrir las etapas uno y dos, HeroCtl trae embebido en el plano de control:",[2735,5183,5184,5190,5196],{},[70,5185,5186,5189],{},[27,5187,5188],{},"Cifrado entre servicios automático."," Cada servicio enviado recibe identidad propia. Llamada interna entre dos servicios es cifrada por defecto, sin alteración en el código de la aplicación y sin sidecar paralelo.",[70,5191,5192,5195],{},[27,5193,5194],{},"Distributed tracing vía OpenTelemetry exporter integrado."," El cluster propaga cabeceras de correlación y exporta a cualquier collector que entienda OTLP. No es tan rico como malla completa (que inyecta tracing automáticamente en los sidecars), pero cubre 80% del uso real.",[70,5197,5198,5201],{},[27,5199,5200],{},"Traffic shaping básico embebido."," Rolling update, canary con porcentaje fijo de tráfico, blue-green. Suficiente para startup que hace diez deploys al día. No cubre mirror ni canary con peso por header — para eso, necesita instalar malla.",[12,5203,5204],{},"Para startup hasta el rango de los treinta servicios, eso cubre cerca de 80% de lo que una malla completa entrega — sin el sidecar, sin las cuatro semanas de aprendizaje, sin los 10 GB de RAM. Cuando el sistema crece más allá, instalar Linkerd encima de HeroCtl es camino documentado.",[19,5206,5208],{"id":5207},"los-cuatro-errores-mas-caros-instalando-service-mesh","Los cuatro errores más caros instalando service mesh",[12,5210,5211],{},"Para equipo que decidió por el paso, cuatro trampas que cuestan de dos semanas a tres meses de retrabajo:",[2735,5213,5214,5220,5237,5243],{},[70,5215,5216,5219],{},[27,5217,5218],{},"Instalar antes de necesitar."," Cobertura innecesaria se vuelve pasivo. Componente nuevo en el quórum, coste de RAM, tiempo de aprendizaje — sin retorno equivalente.",[70,5221,5222,5225,5226,5229,5230,5233,5234,5236],{},[27,5223,5224],{},"Configurar cifrado estricto en el día uno sin pensar en legacy."," Modo ",[231,5227,5228],{},"STRICT"," rompe cualquier servicio que aún no fue migrado. La migración correcta es gradual: modo ",[231,5231,5232],{},"PERMISSIVE"," al inicio (acepta tráfico cifrado y no-cifrado), solo se vuelve ",[231,5235,5228],{}," cuando todos los servicios están dentro de la malla.",[70,5238,5239,5242],{},[27,5240,5241],{},"No dimensionar el plano de control."," Istio Pilot y similares necesitan RAM y CPU suficientes para distribuir configuración a todos los sidecars. En cluster creciendo, volverse cuello de botella del plano de control es incidente clásico de quien no planificó.",[70,5244,5245,5248],{},[27,5246,5247],{},"Saltar Linkerd a Istio \"porque es más popular\"."," Linkerd resuelve 80% de los casos con 30% del overhead. La elección por Istio solo se justifica cuando una feature específica (authorization L7 sofisticada, integración con servicio de identidad externo, multi-cluster federation) sea requisito real, no preferencia de currículum.",[19,5250,4245],{"id":4244},[12,5252,5253,5256],{},[27,5254,5255],{},"¿Linkerd es lo bastante ligero para cluster pequeño?","\nMás ligero que Istio en un orden de magnitud, pero aún así es sidecar paralelo en cada pod. Para cluster con veinte pods y cuatro nodos de 4 GB, Linkerd come cerca de 600 MB de RAM total — significativo pero tolerable. Para cluster con diez pods, aún es exagero. Linkerd entra en escena en la etapa tres (10–50 servicios), no antes.",[12,5258,5259,5262,5263,5265],{},[27,5260,5261],{},"¿Istio Ambient Mode (sin sidecar) cambia esa decisión?","\nReduce el overhead por pod (va a un agente por nodo, ",[231,5264,4596],{},"), pero aún exige operar el plano de control de Istio entero. En producción estable desde 2024, pero la comunidad aún es pequeña — esperar más algunos trimestres para adopción en proyecto crítico es prudente.",[12,5267,5268,5271],{},[27,5269,5270],{},"¿Cilium eBPF realmente tiene cero overhead?","\nPor pod, sí — no tiene sidecar paralelo. Pero el agente Cilium en cada nodo consume de 200 a 400 MB y añade carga en el kernel. Para cluster con kernel Linux moderno y CNI compatible, es la opción más eficiente. Para cluster que aún corre kernel antiguo o usa CNI específico, el setup se vuelve proyecto.",[12,5273,5274,5277],{},[27,5275,5276],{},"¿Cómo hago cifrado entre servicios sin service mesh?","\nTres caminos. Primero, TLS en el código de la aplicación — cada servicio expone HTTPS, cada cliente confía en CA interna. Funciona, pero exige distribuir certificados manualmente (o vía caja fuerte de secretos). Segundo, plano de control del orquestador emitir certificados automáticamente — HeroCtl y algunas distribuciones del coloso hacen eso, es el camino más limpio. Tercero, VPN o red overlay cifrada (WireGuard) entre nodos — protege el tráfico dentro del cluster, pero no la identidad servicio-a-servicio.",[12,5279,5280,5283],{},[27,5281,5282],{},"¿Distributed tracing necesita malla?","\nNo. OpenTelemetry SDK en cada servicio, exportando a un collector central (Tempo, Jaeger, o servicio gestionado), cubre 90% del uso. Malla automatiza la inyección sin cambiar código, lo que es cómodo — pero no es requisito. Para startup, empezar con OpenTelemetry en el código es más barato.",[12,5285,5286,5289],{},[27,5287,5288],{},"¿Service mesh en cluster gestionado es más fácil?","\nMás fácil de instalar, sí — buena parte de los proveedores ofrece add-on de Istio o Linkerd con un clic. Más fácil de operar, no — aún necesitas entender el plano de control, dimensionar, debugar cuando una sidecar reciclar. No ganes tiempo de instalación a costa de despreparo operacional.",[12,5291,5292,5295],{},[27,5293,5294],{},"¿Cuál malla es más usada en startup?","\nPor experiencia de comunidad, Istio domina en las empresas que adoptaron entre 2020 y 2022 (efecto moda CNCF). Linkerd crece desde 2024 entre quienes migraron o empezaron nuevo, especialmente fintechs de tamaño mediano. Cilium aparece en casos específicos (clusters muy grandes, optimización de coste). Consul Connect rarísimo.",[12,5297,5298,5301],{},[27,5299,5300],{},"¿Vale la pena para monolito + 3 microservicios?","\nNo. Monolito + tres microservicios no tiene complejidad interna que malla ayude a domar. TLS en el código resuelve cifrado. Logs centralizados resuelven visibilidad. Rolling update del orquestador resuelve deploy seguro. Instalar malla en ese escenario es traer un problema para resolver otro problema que no existe.",[12,5303,5304,5307],{},[27,5305,5306],{},"¿HeroCtl sustituye completamente una service mesh?","\nPara etapas uno y dos (hasta treinta servicios), sustituye en cerca de 80% del uso real. Para etapas tres y cuatro (por encima de treinta servicios, o compliance específico), HeroCtl convive con Linkerd o Istio corriendo como jobs encima. El cifrado entre servicios del plano de control de HeroCtl coexiste con la malla — la malla cuida del tráfico entre tus pods, HeroCtl cuida de la identidad de los servicios y de la comunicación con el plano de control.",[19,5309,3310],{"id":3309},[12,5311,5312],{},"La regla práctica que recomendamos al tech lead: instala malla cuando dos o más de los criterios objetivos se vuelvan realidad — treinta servicios activos, más de un incidente al mes relacionado con llamadas internas, compliance formal pidiendo zero-trust, equipo de plataforma de cinco personas, federación multi-cluster real. Antes de eso, cluster con cifrado embebido en el plano de control resuelve la mayor parte de lo que ibas a comprar con malla, sin los 10 GB de RAM y sin las ocho semanas de aprendizaje.",[12,5314,5315],{},"Para empezar a explorar esa vía — orquestador con cifrado entre servicios ya incluido, sin sidecar paralelo, plano de control ocupando entre 200 y 400 MB por servidor y elección de coordinador en cerca de siete segundos cuando algo cae — instala en un servidor Linux cualquiera y abre el panel:",[224,5317,5319],{"className":226,"code":5318,"language":228,"meta":229,"style":229},"curl -sSL get.heroctl.com\u002Finstall.sh | sh\n",[231,5320,5321],{"__ignoreMap":229},[234,5322,5323,5325,5327,5330,5332],{"class":236,"line":237},[234,5324,1220],{"class":247},[234,5326,2958],{"class":251},[234,5328,5329],{"class":255}," get.heroctl.com\u002Finstall.sh",[234,5331,2964],{"class":383},[234,5333,2967],{"class":247},[12,5335,5336,5337,5340,5341,5345],{},"Para continuar en esa línea, dos posts directos. En ",[3337,5338,5339],{"href":4369},"Multi-tenant SaaS — ¿aislamiento real o solo namespace?"," tratamos del problema vecino — separar clientes dentro del mismo cluster sin romper el presupuesto. En ",[3337,5342,5344],{"href":5343},"\u002Fes\u002Fblog\u002Fk3s-vs-heroctl-cuando-cada-uno-tiene-sentido","K3s vs HeroCtl — cuándo cada uno tiene sentido"," comparamos la alternativa más común cuando el equipo ya decidió que el coloso ortodoxo es exagero.",[12,5347,5348],{},"La elección por malla de servicio es, en el fondo, una elección de cuándo absorber complejidad. La pregunta correcta no es \"¿necesito Istio?\" — es \"¿cuál es el menor sistema que aún resuelve mi problema actual?\". Para gran parte de las startups, la respuesta es más simple de lo que la industria americana sugiere.",[3351,5350,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":5352},[5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368],{"id":4422,"depth":244,"text":4423},{"id":4432,"depth":244,"text":4433},{"id":4532,"depth":244,"text":4533},{"id":4581,"depth":244,"text":4582},{"id":4625,"depth":244,"text":4626},{"id":4740,"depth":244,"text":4741},{"id":4774,"depth":244,"text":4775},{"id":4824,"depth":244,"text":4825},{"id":5036,"depth":244,"text":5037},{"id":5072,"depth":244,"text":5073},{"id":5111,"depth":244,"text":5112},{"id":5147,"depth":244,"text":5148},{"id":5177,"depth":244,"text":5178},{"id":5207,"depth":244,"text":5208},{"id":4244,"depth":244,"text":4245},{"id":3309,"depth":244,"text":3310},"2026-05-29","Service mesh resuelve problemas reales (mTLS, observabilidad entre servicios, traffic shaping). Pero añade 30-50% overhead de RAM\u002FCPU y complejidad. Cuándo vale la pena y cuándo es overkill.",{},{"title":4414,"description":5370},{"loc":4276},"es\u002Fblog\u002Fservice-mesh-cuando-vale-la-pena-en-saas-pequeno",[5376,5377,5378,3394,4410],"service-mesh","istio","linkerd","WjLsoEL_PvEf75FpHRjW2Wfu2YOhmhW3jd7R5Rf_YDU",{"id":5381,"title":5382,"author":7,"body":5383,"category":6382,"cover":3380,"date":6383,"description":6384,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":6385,"navigation":411,"path":6386,"readingTime":6387,"seo":6388,"sitemap":6389,"stem":6390,"tags":6391,"__hash__":6397},"blog_es\u002Fes\u002Fblog\u002Fsalir-de-aws-sin-reescribir-el-stack.md","Cómo salir de AWS sin reescribir todo el stack: guía práctica 2026",{"type":9,"value":5384,"toc":6344},[5385,5388,5392,5395,5398,5404,5407,5411,5414,5417,5420,5424,5427,5501,5504,5508,5511,5714,5717,5721,5724,5727,5731,5738,5741,5744,5750,5754,5757,5760,5764,5767,5774,5777,5781,5784,5787,5791,5794,5797,5801,5804,5808,5811,5814,5818,5821,5824,5827,5831,5834,5844,5847,5851,5854,5857,5861,5864,5870,5876,5879,5883,5886,5892,5898,5908,5914,5920,5926,5932,5938,5942,5945,5977,5981,5984,5989,6026,6031,6062,6065,6068,6072,6075,6078,6095,6098,6101,6105,6108,6114,6120,6126,6132,6136,6139,6153,6156,6160,6163,6166,6191,6194,6206,6209,6211,6215,6219,6222,6226,6229,6233,6236,6240,6246,6250,6269,6273,6276,6280,6283,6287,6290,6294,6297,6299,6303,6306,6309,6325,6328,6339,6342],[12,5386,5387],{},"La mayoría de los equipos que piensa en salir de AWS lo posterga indefinidamente porque cree estar ante un proyecto de \"reescribir todo el stack\". No lo es. Es un proyecto de mapeo, no de reescritura. Y el mapeo cabe en una hoja de cálculo de doce líneas.",[19,5389,5391],{"id":5390},"tldr-lo-que-vas-a-leer-en-tres-minutos","TL;DR — lo que vas a leer en tres minutos",[12,5393,5394],{},"Stack típico de SaaS usa cerca de doce servicios AWS, y cada uno de ellos tiene alternativa portable que cuesta entre tres y siete veces menos. EC2 se vuelve VPS en cualquier proveedor (Hetzner, DigitalOcean, Magalu Cloud). RDS se vuelve Postgres en VPS dedicado, Neon o Supabase. ElastiCache se vuelve Valkey auto-hospedado. S3 se vuelve CloudFlare R2 o Backblaze B2 — ambos con API S3-compatible, así que el código ni cambia. SQS se vuelve cola basada en Redis o RabbitMQ. Lambda se vuelve endpoint en el app server tradicional o CloudFlare Workers. ALB se vuelve el router integrado del orquestador. CloudFront se vuelve CloudFlare gratis. IAM se vuelve inyección de secretos en el orquestador.",[12,5396,5397],{},"Cronograma realista para startup con cinco a diez aplicaciones: seis a ocho semanas, ochenta a ciento sesenta horas de desarrollo. Ahorro típico: tres a siete veces en la cuenta de infra, con retorno en menos de un mes de salario sénior.",[12,5399,5400,5403],{},[27,5401,5402],{},"No migres si"," tu cumplimiento exige AWS nominalmente, si el equipo es único y se enfoca en producto, o si el stack usa lock-in profundo (DynamoDB con features específicas, Aurora Serverless v2, IAM cross-account complejo).",[12,5405,5406],{},"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",[19,5408,5410],{"id":5409},"por-que-tantos-equipos-posponen-la-salida-de-aws","¿Por qué tantos equipos posponen la salida de AWS?",[12,5412,5413],{},"La respuesta honesta es confusión entre dos proyectos diferentes. \"Salir de AWS\" se volvió sinónimo mental de \"reescribir la aplicación\". No es la misma cosa.",[12,5415,5416],{},"Reescribir la aplicación es cambiar tecnología central — base relacional por NoSQL, framework síncrono por reactivo, monolito por microservicios. Eso sí toma trimestres. Salir de AWS es cambiar la infra que sostiene la aplicación que ya tienes. El código de dominio queda idéntico. Cambian endpoints de base, credenciales, algunos SDKs y la forma de declarar deploy.",[12,5418,5419],{},"La confusión dura porque el equipo mira la consola de AWS y ve doscientos servicios. Nadie usa doscientos. La mayor parte usa doce. Mapea esos doce, encuentra alternativa para cada uno, y lo que queda es trabajo de ejecución — no de investigación.",[19,5421,5423],{"id":5422},"los-doce-servicios-aws-que-tu-stack-probablemente-usa","Los doce servicios AWS que tu stack probablemente usa",[12,5425,5426],{},"La hoja de cálculo de inicio es esa. Todo lo que está fuera de ella en tu cuenta probablemente es satélite — alarma del CloudWatch que nadie mira, bucket S3 olvidado, función Lambda muerta. Enfócate en los doce:",[67,5428,5429,5435,5441,5447,5453,5459,5465,5471,5477,5483,5489,5495],{},[70,5430,5431,5434],{},[27,5432,5433],{},"EC2"," — máquinas virtuales que corren app server y workers",[70,5436,5437,5440],{},[27,5438,5439],{},"RDS"," — base relacional gestionada (Postgres o MySQL)",[70,5442,5443,5446],{},[27,5444,5445],{},"ElastiCache"," — Redis para caché y sesión",[70,5448,5449,5452],{},[27,5450,5451],{},"S3"," — almacenamiento de objetos (uploads, backups, assets)",[70,5454,5455,5458],{},[27,5456,5457],{},"ALB \u002F NLB"," — balanceador de carga al frente de las EC2",[70,5460,5461,5464],{},[27,5462,5463],{},"CloudFront"," — CDN para assets estáticos",[70,5466,5467,5470],{},[27,5468,5469],{},"Route 53"," — DNS autoritativo",[70,5472,5473,5476],{},[27,5474,5475],{},"SES"," — email transaccional",[70,5478,5479,5482],{},[27,5480,5481],{},"SQS \u002F SNS"," — cola y pub-sub",[70,5484,5485,5488],{},[27,5486,5487],{},"IAM"," — credenciales y roles para que servicios conversen",[70,5490,5491,5494],{},[27,5492,5493],{},"CloudWatch"," — métricas y logs",[70,5496,5497,5500],{},[27,5498,5499],{},"Lambda"," — funciones serverless",[12,5502,5503],{},"Si tu cuenta tiene los doce, felicitaciones: eres el stack mediano. Si tiene ocho o nueve, mejor — menos cosas para migrar. Si tiene cinco servicios muy específicos (Aurora Global, DynamoDB con Streams, EventBridge complejo), estás en un camino diferente — lee la sección de lock-ins antes de continuar.",[19,5505,5507],{"id":5506},"mapeo-servicio-por-servicio-alternativa-coste-y-complejidad","Mapeo servicio por servicio — alternativa, coste y complejidad",[12,5509,5510],{},"La tabla abajo es el atajo. Cada línea tiene detalle expandido después.",[119,5512,5513,5532],{},[122,5514,5515],{},[125,5516,5517,5520,5523,5526,5529],{},[128,5518,5519],{},"Servicio AWS",[128,5521,5522],{},"Alternativa portable",[128,5524,5525],{},"Coste antes (US$\u002Fmes)",[128,5527,5528],{},"Coste después (US$\u002Fmes)",[128,5530,5531],{},"Complejidad migración",[141,5533,5534,5550,5566,5582,5597,5612,5626,5641,5655,5671,5684,5698],{},[125,5535,5536,5539,5542,5545,5548],{},[146,5537,5538],{},"EC2 t3.medium",[146,5540,5541],{},"VPS Hetzner CPX21",[146,5543,5544],{},"30",[146,5546,5547],{},"9",[146,5549,3155],{},[125,5551,5552,5555,5558,5561,5564],{},[146,5553,5554],{},"RDS db.t4g.large",[146,5556,5557],{},"Postgres auto-hospedado o Neon",[146,5559,5560],{},"140",[146,5562,5563],{},"10–50",[146,5565,3160],{},[125,5567,5568,5571,5574,5577,5580],{},[146,5569,5570],{},"ElastiCache cache.t4g.micro",[146,5572,5573],{},"Valkey auto-hospedado",[146,5575,5576],{},"15",[146,5578,5579],{},"6",[146,5581,3160],{},[125,5583,5584,5587,5590,5593,5595],{},[146,5585,5586],{},"S3 (1TB + egress)",[146,5588,5589],{},"CloudFlare R2",[146,5591,5592],{},"120",[146,5594,5576],{},[146,5596,3155],{},[125,5598,5599,5602,5605,5608,5610],{},[146,5600,5601],{},"ALB",[146,5603,5604],{},"Router integrado del orquestador",[146,5606,5607],{},"22",[146,5609,893],{},[146,5611,3160],{},[125,5613,5614,5616,5619,5622,5624],{},[146,5615,5463],{},[146,5617,5618],{},"CloudFlare gratis",[146,5620,5621],{},"80",[146,5623,893],{},[146,5625,3155],{},[125,5627,5628,5630,5633,5636,5638],{},[146,5629,5469],{},[146,5631,5632],{},"CloudFlare DNS",[146,5634,5635],{},"5",[146,5637,893],{},[146,5639,5640],{},"Trivial",[125,5642,5643,5645,5648,5650,5653],{},[146,5644,5475],{},[146,5646,5647],{},"Resend o Postmark",[146,5649,1589],{},[146,5651,5652],{},"15–20",[146,5654,5640],{},[125,5656,5657,5659,5662,5665,5668],{},[146,5658,5481],{},[146,5660,5661],{},"Redis Streams o RabbitMQ",[146,5663,5664],{},"16",[146,5666,5667],{},"0 (misma VPS)",[146,5669,5670],{},"Media–alta",[125,5672,5673,5675,5678,5680,5682],{},[146,5674,5487],{},[146,5676,5677],{},"Secretos del orquestador",[146,5679,893],{},[146,5681,893],{},[146,5683,3160],{},[125,5685,5686,5688,5691,5694,5696],{},[146,5687,5493],{},[146,5689,5690],{},"Prometheus + Loki",[146,5692,5693],{},"50",[146,5695,5667],{},[146,5697,3160],{},[125,5699,5700,5702,5705,5708,5711],{},[146,5701,5499],{},[146,5703,5704],{},"App server o CloudFlare Workers",[146,5706,5707],{},"40",[146,5709,5710],{},"0–12",[146,5712,5713],{},"Variable",[12,5715,5716],{},"Costes de antes asumen stack de SaaS pequeño-medio con cinco a diez aplicaciones activas.",[368,5718,5720],{"id":5719},"ec2-se-vuelve-vps-en-cualquier-proveedor","EC2 se vuelve VPS en cualquier proveedor",[12,5722,5723],{},"La migración más obvia. EC2 t3.medium cuesta cerca de treinta dólares mensuales. Hetzner CPX21 con la misma clase de CPU y más RAM cuesta siete euros y noventa y nueve. DigitalOcean queda en el medio. Magalu Cloud es competitivo para quien prioriza factura en moneda local y dato en territorio nacional.",[12,5725,5726],{},"El camino técnico es provisionar la VPS, correr tu Ansible existente (o un script de bootstrap simple), copiar el snapshot del EC2 o subir la imagen desde cero. Para cada servidor, cuenta de dos a cuatro horas. No es la parte demorada de la migración.",[368,5728,5730],{"id":5729},"rds-se-vuelve-postgres-auto-hospedado-o-neonsupabase","RDS se vuelve Postgres auto-hospedado o Neon\u002FSupabase",[12,5732,5733,5734,5737],{},"Aquí hay tres caminos honestos. El primero es Postgres corriendo en una VPS dedicada, con backup automatizado vía ",[231,5735,5736],{},"pg_dump"," en cron y replicación física a un secundario en otra región. Cuesta el precio de la VPS — diez a veinte dólares mensuales — para sustituir un RDS de ciento cuarenta.",[12,5739,5740],{},"El segundo es Neon. Postgres serverless con branching, ramp-up automático, plan gratuito generoso, planes pagados a partir de cinco dólares. Útil para quien quiere abandonar AWS sin asumir operación directa de base.",[12,5742,5743],{},"El tercero es Supabase, que entrega Postgres con APIs adicionales (auth, realtime, storage) y tier gratuito permanente. Tiene sentido para startups que toleran acoplamiento a Supabase a cambio de simplicidad.",[12,5745,5746,5747,5749],{},"La migración en sí es ",[231,5748,5736],{}," seguido de restore en el destino, con ventana de mantenimiento corta — o replicación lógica con cutover casi sin downtime si tu Postgres es versión 13 o superior. Cuatro a ocho horas dependiendo del tamaño de la base.",[368,5751,5753],{"id":5752},"elasticache-se-vuelve-valkey-auto-hospedado","ElastiCache se vuelve Valkey auto-hospedado",[12,5755,5756],{},"Redis se volvió Valkey después del cambio de licencia en 2024 — fork mantenido por la Linux Foundation. Corre en cualquier VPS con dos clics. Seis dólares mensuales sustituyen el ElastiCache de quince.",[12,5758,5759],{},"La migración tiene dos etapas. Primera, levantar el cluster Valkey con Sentinel para failover automático. Segunda, poblar la caché — script que lee de AWS y graba en el destino, o simplemente dejar que la aplicación lo llene orgánicamente después del cutover (caché cold start de pocos minutos). Tres a seis horas de trabajo.",[368,5761,5763],{"id":5762},"s3-se-vuelve-cloudflare-r2-o-backblaze-b2","S3 se vuelve CloudFlare R2 (o Backblaze B2)",[12,5765,5766],{},"Esa es la ganancia más inmediata. CloudFlare R2 cobra cero por el egreso — la rebanada más cara del S3 cuando sirves assets a usuarios. Quince centavos de dólar por GB almacenado, contra veintitrés centavos del S3 estándar. Backblaze B2 es una alternativa casi idéntica, con integración aún más barata para workloads de backup pesado.",[12,5768,5769,5770,5773],{},"La migración técnica es trivial: ",[231,5771,5772],{},"rclone copy s3:mi-bucket r2:mi-bucket"," en paralelo. Un terabyte transfiere alrededor de doce horas dependiendo de la banda. El código de la aplicación cambia exactamente una línea — el endpoint del cliente S3. Toda biblioteca AWS SDK acepta configuración de endpoint custom; R2 y B2 implementan el protocolo S3 idéntico.",[12,5775,5776],{},"Volumen típico de SaaS medio (cincuenta GB de uploads de usuario): US$15 mensuales en R2 contra US$120 en S3 con egreso activo. El ahorro paga una semana de trabajo de migración en el primer mes.",[368,5778,5780],{"id":5779},"alb-se-vuelve-router-integrado-del-orquestador","ALB se vuelve router integrado del orquestador",[12,5782,5783],{},"Si estás usando ALB, es porque tienes varias EC2 detrás de él. La alternativa es el router embebido en el orquestador elegido — HeroCtl, Caddy, o el router embebido en otros stacks auto-hospedados. El orquestador descubre los contenedores corriendo, abre puerto, terminan TLS vía Let's Encrypt automático, distribuye tráfico.",[12,5785,5786],{},"La migración cambia la definición de target group AWS por una definición de ingress en el manifiesto del orquestador. Cuatro a ocho horas para entender las reglas correctas. Veintidós dólares mensuales ahorrados por balanceador, y el orquestador acepta cuantos hosts quieras sin cobro adicional.",[368,5788,5790],{"id":5789},"cloudfront-se-vuelve-cloudflare-gratis","CloudFront se vuelve CloudFlare gratis",[12,5792,5793],{},"Ese merece una mención destacada. CloudFront cobra por GB transferido — quien sirve vídeo o descargas pesadas sangra. CloudFlare ofrece CDN global gratuita en el plan free, con caché configurable, mitigación básica de DDoS y WAF rudimentario. Para la mayor parte de los casos de SaaS, es más que suficiente.",[12,5795,5796],{},"La migración es cambiar los nameservers del dominio a CloudFlare y configurar reglas de caché. Dos a cuatro horas. El ahorro puede ser masivo — ochenta dólares mensuales para quien tiene volumen medio de tráfico, miles para quien tiene volumen alto.",[368,5798,5800],{"id":5799},"route-53-se-vuelve-cloudflare-dns","Route 53 se vuelve CloudFlare DNS",[12,5802,5803],{},"DNS en CloudFlare es gratis y más rápido que Route 53 en la mayoría de las mediciones públicas. Migración es exportar la zone file, importar en CloudFlare, validar registros, cambiar nameservers en el registrar. Treinta minutos. Cinco dólares mensuales que vuelven a la caja.",[368,5805,5807],{"id":5806},"ses-se-vuelve-resend-postmark-o-mailgun","SES se vuelve Resend, Postmark o Mailgun",[12,5809,5810],{},"AWS es barato para envío en volumen, pero la entregabilidad del SES exige calentamiento de IP y configuración de reputación que toma tiempo. Resend cobra veinte dólares por cincuenta mil emails mensuales y tiene entregabilidad superior fuera de la caja. Postmark cobra quince por diez mil. Mailgun cubre el caso de quien manda mucho volumen no-transaccional.",[12,5812,5813],{},"La migración es cambiar credenciales SMTP en el app — una hora de trabajo.",[368,5815,5817],{"id":5816},"sqs-y-sns-se-vuelven-redis-streams-o-rabbitmq","SQS y SNS se vuelven Redis Streams o RabbitMQ",[12,5819,5820],{},"La migración más delicada. SQS es un servicio que hace una cosa y la hace bien; sustituir exige elegir tecnología de cola y refactorizar productor y consumidor.",[12,5822,5823],{},"El camino más corto es Redis Streams, principalmente si ya estás corriendo Valkey para caché. Bibliotecas como Sidekiq (Ruby), BullMQ (Node), RQ (Python) y Asynq (Go) consumen Redis nativamente. RabbitMQ es más robusto para escenarios de enrutamiento complejo. NATS es alternativa moderna para pub-sub.",[12,5825,5826],{},"Para cada cola, cuenta uno a tres días dependiendo de la complejidad. Colas simples de jobs background son triviales. Colas con fan-out, dead letter queues y visibility timeout customizado exigen más cuidado. Dieciséis dólares mensuales ahorrados, y la cola corre en la misma VPS que la caché — cero adicional en la infra.",[368,5828,5830],{"id":5829},"iam-se-vuelve-secretos-del-orquestador","IAM se vuelve secretos del orquestador",[12,5832,5833],{},"Aquí está la migración no-obvia que pilla a muchos equipos experimentados en AWS desprevenidos. En AWS, la aplicación accede a S3 y RDS sin credenciales explícitas en el código — la EC2 hereda un IAM role y el SDK busca tokens automáticamente. Fuera de AWS, eso desaparece.",[12,5835,5836,5837,5839,5840,5843],{},"La solución es inyección de secretos por el orquestador. HeroCtl, k3s y similares aceptan secretos como recursos de primera clase — declaras ",[231,5838,453],{}," o ",[231,5841,5842],{},"S3_ACCESS_KEY"," en el manifiesto del job y el orquestador inyecta como variable de entorno en el contenedor. Para escenarios más sofisticados, HashiCorp Vault auto-hospedado hace rotación automática.",[12,5845,5846],{},"La migración es refactorizar cada role IAM en un conjunto de credenciales explícitas, creadas en el proveedor de destino (CloudFlare API token, Postgres user específico, etc), y declaradas como secretos. Cuatro a ocho horas para un stack medio.",[368,5848,5850],{"id":5849},"cloudwatch-se-vuelve-prometheus-loki","CloudWatch se vuelve Prometheus + Loki",[12,5852,5853],{},"Métricas se vuelven Prometheus + Grafana. Logs se vuelven Loki + Grafana. Todo corre en contenedores en el mismo cluster. Cincuenta dólares mensuales de CloudWatch se vuelven cero adicional.",[12,5855,5856],{},"La configuración inicial toma cerca de cuatro horas para volverse productiva: Prometheus con service discovery apuntando a los agentes del orquestador, Loki recibiendo vía Promtail o directamente del runtime de contenedor, Grafana con dashboards básicos. Hay posts dedicados a esa migración en el blog.",[368,5858,5860],{"id":5859},"lambda-la-parte-mas-dificil","Lambda — la parte más difícil",[12,5862,5863],{},"Lambda es el servicio con la mayor varianza de complejidad en la migración. Depende totalmente de cómo la estés usando.",[12,5865,5866,5869],{},[27,5867,5868],{},"Lambda HTTP simple"," (API Gateway → Lambda → respuesta) es trivial. Se vuelve endpoint en tu app server. El código de la función cambia poco — handler del framework en lugar del handler del Lambda. Una a dos horas por función.",[12,5871,5872,5875],{},[27,5873,5874],{},"Lambda event-driven"," (S3 dispara Lambda, SQS dispara Lambda, EventBridge agenda Lambda) es la parte cara. Para eventos de S3, R2 ofrece eventos vía CloudFlare Workers — reescribes la Lambda como Worker y mantienes el patrón. Para SQS, se vuelve consumer en el app server. Para EventBridge agendado, se vuelve cron en el orquestador.",[12,5877,5878],{},"Escenario peor: Lambda compleja con EventBridge, Step Functions y dead letter queues encadenados. Aquí es redesign. Reserva una semana o dos y dibuja un modelo de eventos más simple — generalmente el sistema queda mejor.",[19,5880,5882],{"id":5881},"cronograma-realista-de-seis-a-ocho-semanas","Cronograma realista de seis a ocho semanas",[12,5884,5885],{},"El orden importa. Empezar por la base es tentación y trampa — base es la última en migrar, no la primera.",[12,5887,5888,5891],{},[27,5889,5890],{},"Semana 1 — Inventario y decisión."," Lista los doce servicios, anota coste actual, identifica integraciones entre ellos. Elige alternativa para cada uno. Documento de una página con la tabla de mapeo. Sin código aún.",[12,5893,5894,5897],{},[27,5895,5896],{},"Semana 2 — Provisión del destino en paralelo."," Levanta las VPS, instala el orquestador (HeroCtl o similar), configura DNS de prueba apuntando a un subdominio. Sube Postgres, Valkey, CloudFlare R2. Todo vacío. Smoke test: un \"hello world\" corriendo.",[12,5899,5900,5903,5904,5907],{},[27,5901,5902],{},"Semana 3 — Migración de storage."," S3 a R2 con ",[231,5905,5906],{},"rclone",". Suele ser lenta (volumen) pero bajísimo riesgo. Aplicación aún lee de S3, pero validas que R2 esté sincronizado. Al final de la semana, dual-write — aplicación escribe en los dos.",[12,5909,5910,5913],{},[27,5911,5912],{},"Semana 4 — Migración de la base."," Réplica lógica de Postgres del RDS al destino. Cutover en una ventana de mantenimiento corta — suele ser minutos, no horas, con replicación lógica funcionando. Aplicación apunta a la base nueva. RDS queda como hot standby por una semana.",[12,5915,5916,5919],{},[27,5917,5918],{},"Semana 5 — Migración de aplicaciones web."," Apps que corren en EC2 se vuelven jobs en el orquestador. Router integrado hace el papel del ALB. DNS apunta al orquestador (o a CloudFlare al frente). Cutover gradual usando weighted DNS.",[12,5921,5922,5925],{},[27,5923,5924],{},"Semana 6 — Colas y jobs asíncronos."," SQS sale, Redis Streams o RabbitMQ entra. Workers corren en el orquestador. Período de dual-consume para garantizar que ningún mensaje cae.",[12,5927,5928,5931],{},[27,5929,5930],{},"Semana 7 — Lambdas y workloads event-driven."," La semana más variable. Lambdas HTTP migran rápidamente. Lambdas event-driven exigen el redesign discutido arriba. Si tienes más de diez Lambdas complejas, considera extender a dos semanas.",[12,5933,5934,5937],{},[27,5935,5936],{},"Semana 8 — Cutover final, monitoreo intensivo, decommission."," CloudFlare al frente sustituye CloudFront. Route 53 se vuelve CloudFlare DNS. CloudWatch va a Prometheus + Loki. Última cosa: apaga las EC2 antiguas y cierra la cuenta AWS — o deja un saldo mínimo si aún mantienes algún servicio residual.",[19,5939,5941],{"id":5940},"los-cinco-lock-ins-que-mas-duelen-en-la-migracion","Los cinco lock-ins que más duelen en la migración",[12,5943,5944],{},"La honestidad es importante: no todo migra fácil. Cinco cosas exigen trabajo extra y a veces cambian la viabilidad del proyecto:",[67,5946,5947,5953,5959,5965,5971],{},[70,5948,5949,5952],{},[27,5950,5951],{},"DynamoDB con features específicas."," GSI, Streams, scan limits, TTL. No hay equivalente directo. El camino realista es rediseñar a Postgres con JSONB, o a un NoSQL auto-hospedado (FoundationDB, ScyllaDB) — re-arquitectura, no migración.",[70,5954,5955,5958],{},[27,5956,5957],{},"Aurora-only features."," Aurora Serverless v2 con auto-scaling de connections, Aurora Global Database, Aurora I\u002FO optimized. Postgres auto-hospedado hace casi todo, pero no tiene el auto-scaling instantáneo. Para workloads spiky, considera Neon (que ofrece patrón similar).",[70,5960,5961,5964],{},[27,5962,5963],{},"IAM cross-service complejo."," Equipos que usan IAM roles cross-account, Service Control Policies y organización jerárquica de cuentas tienen control de acceso embebido en la arquitectura. Migrar exige reimplementar la jerarquía en otro lugar — Vault, CloudFlare Access, o inyección de secretos del orquestador. Cuenta días, no horas.",[70,5966,5967,5970],{},[27,5968,5969],{},"Lambda + EventBridge complejo."," Pipelines de eventos con varios hops, retries, dead letter queues. No migra como está. Rediseña en torno de colas (RabbitMQ, NATS) y workers persistentes. Generalmente el sistema queda más simple — pero toma tiempo.",[70,5972,5973,5976],{},[27,5974,5975],{},"S3 events disparando Lambda."," Patrón muy común, y R2 con CloudFlare Workers cubre la mayoría de los casos. Para workloads que necesitan garantía exactamente-una-vez o ordering fuerte, cambia a patrón de cola — productor escribe evento en la cola cuando archivo es confirmado, worker consume.",[19,5978,5980],{"id":5979},"la-cuenta-de-ahorro-sin-optimismo","La cuenta de ahorro, sin optimismo",[12,5982,5983],{},"Escenario típico de SaaS con cinco aplicaciones:",[12,5985,5986],{},[27,5987,5988],{},"Antes en AWS:",[2735,5990,5991,5994,5997,6000,6003,6006,6009,6012,6015,6018,6021],{},[70,5992,5993],{},"Cinco EC2 t3.medium: US$150",[70,5995,5996],{},"RDS db.t4g.large Multi-AZ: US$280",[70,5998,5999],{},"ElastiCache cache.t4g.micro: US$15",[70,6001,6002],{},"S3 con 100GB y egreso medio: US$60",[70,6004,6005],{},"ALB: US$22",[70,6007,6008],{},"CloudFront con volumen medio: US$80",[70,6010,6011],{},"Route 53 + SES: US$15",[70,6013,6014],{},"CloudWatch logs\u002Fmétricas: US$50",[70,6016,6017],{},"Lambda con volumen medio: US$40",[70,6019,6020],{},"NAT Gateway: US$40",[70,6022,6023],{},[27,6024,6025],{},"Total: US$752\u002Fmes = US$9.024\u002Faño",[12,6027,6028],{},[27,6029,6030],{},"Después auto-hospedado:",[2735,6032,6033,6036,6039,6042,6045,6048,6051,6054,6057],{},[70,6034,6035],{},"Cuatro VPS Hetzner CPX21 con orquestador: US$36",[70,6037,6038],{},"Postgres auto-hospedado (incluido en las VPS): US$0",[70,6040,6041],{},"Valkey (incluido): US$0",[70,6043,6044],{},"CloudFlare R2 50GB con egreso ilimitado: US$15",[70,6046,6047],{},"CloudFlare CDN + DNS: US$0",[70,6049,6050],{},"Resend para email: US$20",[70,6052,6053],{},"Prometheus + Loki (incluido): US$0",[70,6055,6056],{},"Workers de cola (incluidos): US$0",[70,6058,6059],{},[27,6060,6061],{},"Total: US$71\u002Fmes = US$852\u002Faño",[12,6063,6064],{},"Ahorro: US$681\u002Fmes, US$8.172\u002Faño. Aproximadamente un mes de salario de ingeniero sénior.",[12,6066,6067],{},"La migración consume ochenta a ciento sesenta horas. En tiempo de dev sénior interno, son entre tres y seis mil dólares. Retorno en cinco a diez meses, con ahorro perpetuo después.",[19,6069,6071],{"id":6070},"la-migracion-mas-no-obvia-secretos-y-credenciales","La migración más no-obvia: secretos y credenciales",[12,6073,6074],{},"Vale repetir, porque es lo que más sorprende a equipos experimentados en AWS. En AWS accedes a S3 sin credentials en el código — IAM role del EC2 resuelve. Accedes a RDS vía IAM authentication. Accedes a parameter store vía IAM. El equipo pierde la noción de que esa \"magia\" existe.",[12,6076,6077],{},"Fuera de AWS, toda credencial es explícita. Aplicación necesita:",[2735,6079,6080,6083,6086,6089,6092],{},[70,6081,6082],{},"Access key y secret para R2 (creada en el panel CloudFlare)",[70,6084,6085],{},"Connection string con user y contraseña para el Postgres",[70,6087,6088],{},"URL del Valkey con contraseña",[70,6090,6091],{},"API key para Resend",[70,6093,6094],{},"Token para CloudFlare API si automatizas DNS",[12,6096,6097],{},"La solución del orquestador es declarar todo eso como secretos inyectados en el contenedor como variables de entorno. El secreto es cifrado en reposo en el orquestador y nunca aparece en los logs. Para rotación automática y auditoría sofisticada, Vault auto-hospedado entra en juego — pero la mayoría de los equipos no lo necesita.",[12,6099,6100],{},"Plan: haz una hoja de cálculo con todas las credenciales que cada app necesita, crea cada una en el proveedor de destino, declara como secreto en el orquestador, inyecta en el contenedor. Cuatro a ocho horas para un stack medio.",[19,6102,6104],{"id":6103},"cuando-no-migrar-perfiles-honestos","Cuándo NO migrar (perfiles honestos)",[12,6106,6107],{},"Cuatro situaciones en que salir de AWS es decisión equivocada:",[12,6109,6110,6113],{},[27,6111,6112],{},"Cumplimiento que lista AWS nominalmente."," FedRAMP, ITAR, ciertos contratos de gobierno americano y algunas certificaciones financieras exigen que la infra corra sobre componentes pre-aprobados — y la mayoría de las listas incluyen AWS, GCP, Azure, y pocos proveedores adicionales. Si tu cliente es una agencia federal americana, AWS resuelve una rebanada del cumplimiento que costaría meses replicar en otro lugar.",[12,6115,6116,6119],{},[27,6117,6118],{},"Equipo único enfocado en producto."," Si eres el único dev y estás construyendo el producto, ocho semanas redirigidas a la migración matan roadmap. Hazlo cuando tengas el segundo dev, o cuando los costes AWS pasen a representar rebanada significativa del MRR. Antes de eso, AWS es caro pero comprable.",[12,6121,6122,6125],{},[27,6123,6124],{},"Costes AWS por debajo del 2% del MRR."," Cuenta de doscientos dólares mensuales para startup que factura veinte mil. El ahorro es real pero el esfuerzo no vale el foco. Migra cuando la factura pase del cinco al diez por ciento del MRR — ahí la ganancia cubre la oportunidad perdida.",[12,6127,6128,6131],{},[27,6129,6130],{},"Lock-in profundo en DynamoDB o Aurora Serverless v2."," Ya tratado arriba. Si la mitad de tu arquitectura es DynamoDB con Streams, no migras — re-arquitectas. Ese es proyecto diferente, con alcance diferente, decisión diferente.",[19,6133,6135],{"id":6134},"estrategia-hibrida-alternativa-para-quien-no-quiere-migrar-todo","Estrategia híbrida — alternativa para quien no quiere migrar todo",[12,6137,6138],{},"Equipos con cincuenta o más aplicaciones en AWS raramente migran en bloque. La estrategia híbrida funciona mejor:",[2735,6140,6141,6144,6147,6150],{},[70,6142,6143],{},"Mantiene en AWS lo que es caro de mover (Aurora con features específicas, Lambda crítica, DynamoDB)",[70,6145,6146],{},"Mueve lo que es barato de mover y caro de mantener (S3 → R2, CloudFront → CloudFlare, EC2 no-críticas → VPS)",[70,6148,6149],{},"Establece VPN o conexión privada entre los dos extremos",[70,6151,6152],{},"Ahorro parcial pero cero riesgo de migración radical",[12,6154,6155],{},"Resultado típico: corte del cuarenta al sesenta por ciento de la factura AWS, sin tocar las piezas críticas. Para empresa que paga diez mil mensuales, eso es cuatro a seis mil de vuelta — y el resto migra orgánicamente en los doce meses siguientes, conforme equipos reescriben componentes por otras razones.",[19,6157,6159],{"id":6158},"heroctl-como-destino-lo-que-cambia-en-la-practica","HeroCtl como destino — lo que cambia en la práctica",[12,6161,6162],{},"HeroCtl es orquestador de contenedores que corre en cualquier servidor Linux con Docker. Cuatro VPS corriendo HeroCtl entregan experiencia operacional cercana a la que tendrías con ECS gestionado — sin cobro gestionado, sin lock-in.",[12,6164,6165],{},"Lo que sustituye:",[2735,6167,6168,6173,6179,6185],{},[70,6169,6170,6172],{},[27,6171,5601],{}," se vuelve el router integrado de HeroCtl, con TLS Let's Encrypt automático",[70,6174,6175,6178],{},[27,6176,6177],{},"CloudWatch parcial"," se vuelve métricas embebidas y logs centralizados nativos",[70,6180,6181,6184],{},[27,6182,6183],{},"RDS automated backups"," se vuelve backup gestionado en el Business Edition",[70,6186,6187,6190],{},[27,6188,6189],{},"IAM roles en apps"," se vuelve inyección de secretos en el manifiesto de job",[12,6192,6193],{},"Lo que sigue igual: Docker corriendo tu app exactamente como corre en ECS. Variables de entorno, healthchecks, rolling deploys, multi-replicas. La aplicación no percibe la diferencia.",[12,6195,6196,6197,6199,6200,6202,6203,6205],{},"Hay tres planes. ",[27,6198,4352],{}," es gratuito permanente, sin límite de servidores o jobs — corre toda la stack descrita arriba incluyendo alta disponibilidad real, router, certificados, métricas y logs. ",[27,6201,4356],{}," añade SSO, RBAC granular, auditoría detallada, backup gestionado y soporte con SLA — útil para quien ya tiene requisitos formales de plataforma. ",[27,6204,4360],{}," añade escrow de código fuente, soporte 24×7 y desarrollo dedicado. Los precios de Business y Enterprise están publicados en la página de planes, sin \"habla con ventas\" obligatorio.",[12,6207,6208],{},"El cluster público de demostración corre en cuatro servidores y la elección de coordinador ocurre en cerca de siete segundos cuando el nodo actual cae — número medido, no estimado.",[12,6210,5406],{},[19,6212,6214],{"id":6213},"preguntas-que-recibimos-sobre-salida-de-aws","Preguntas que recibimos sobre salida de AWS",[368,6216,6218],{"id":6217},"cuanto-tiempo-realmente-toma-migrar-un-stack-medio","¿Cuánto tiempo realmente toma migrar un stack medio?",[12,6220,6221],{},"Para startup con cinco a diez aplicaciones, sin lock-ins profundos: seis a ocho semanas con un dev sénior dedicando medio tiempo, o tres a cuatro semanas con dedicación total. Stacks mayores o con Lambdas event-driven complejas: tres a cuatro meses. Stacks con DynamoDB o Aurora Serverless v2 críticos: vuélvelo proyecto de re-arquitectura, plazo de seis meses o más.",[368,6223,6225],{"id":6224},"dynamodb-tiene-alternativa-buena","¿DynamoDB tiene alternativa buena?",[12,6227,6228],{},"No hay sustituto idéntico. Las opciones honestas son: Postgres con JSONB para la mayoría de los casos (resuelve ochenta por ciento de los usos de DynamoDB con performance excelente), ScyllaDB o Cassandra auto-hospedado para workloads que realmente necesitan NoSQL distribuido, FoundationDB para quien necesita transacciones distribuidas. Ninguno de esos es \"cambia la connection string y listo\" — exigen cambio en el modelo de datos.",[368,6230,6232],{"id":6231},"puedo-mantener-aws-para-la-base-y-mover-compute","¿Puedo mantener AWS para la base y mover compute?",[12,6234,6235],{},"Sí, y es la estrategia híbrida más común. Aurora o RDS sigue en AWS, EC2 se vuelven VPS Hetzner o DigitalOcean, S3 se vuelve R2. Abres VPN entre los dos extremos y el app sigue accediendo RDS vía endpoint privado. Ahorro típicamente del cincuenta al setenta por ciento de la factura AWS.",[368,6237,6239],{"id":6238},"s3-r2-cuanto-cuesta-transferir-1tb","S3 → R2: ¿cuánto cuesta transferir 1TB?",[12,6241,6242,6243,6245],{},"R2 cobra cero de ingreso. AWS cobra la salida de S3 — aproximadamente nueve centavos de dólar por GB en los primeros 10 TB. Un terabyte cuesta cerca de noventa dólares para salir de AWS. Tiempo de transferencia: doce a veinticuatro horas con ",[231,6244,5906],{}," paralelizado, dependiendo de la banda. Tras la migración, US$15 mensuales almacenando 50GB con egreso ilimitado, contra US$120 por lo mismo en S3 con tráfico activo.",[368,6247,6249],{"id":6248},"lambda-como-migrar-event-driven","Lambda — ¿cómo migrar event-driven?",[12,6251,6252,6253,6256,6257,6260,6261,6264,6265,6268],{},"Depende del disparador. ",[27,6254,6255],{},"S3 disparando Lambda"," se vuelve R2 con CloudFlare Workers (mismo patrón, sin cambio radical). ",[27,6258,6259],{},"SQS disparando Lambda"," se vuelve worker persistente en el app server, consumiendo de la cola — generalmente código más simple que la Lambda original. ",[27,6262,6263],{},"EventBridge agendado"," se vuelve cron en el orquestador. ",[27,6266,6267],{},"EventBridge con reglas complejas y Step Functions encadenados"," exige redesign — dibuja el flujo en torno a una cola central con workers consumidores, queda más auditable.",[368,6270,6272],{"id":6271},"rds-multi-az-postgres-auto-hospedado-es-confiable","RDS Multi-AZ → Postgres auto-hospedado, ¿es confiable?",[12,6274,6275],{},"Postgres con replicación física streaming y failover vía Patroni alcanza confiabilidad cercana a la del RDS Multi-AZ — siempre que el equipo sepa operar. Si nadie en el equipo domina Postgres en producción, el camino más seguro es Neon o Supabase, que entregan Postgres gestionado con tier gratuito. Para equipos con SRE o DBA, auto-hospedado es viable y ahorra substancial. Para equipos sin esa competencia, el ahorro no compensa el riesgo — paga por el gestionado.",[368,6277,6279],{"id":6278},"email-ses-quien-es-mas-barato","Email SES — ¿quién es más barato?",[12,6281,6282],{},"Depende del volumen. Hasta 10 mil emails mensuales, Postmark a US$15 entrega mucho más (entregabilidad superior, dashboard mejor, soporte responsivo). Entre 50 mil y 100 mil mensuales, Resend a US$20 es el mejor coste-beneficio. Por encima de 500 mil mensuales, Mailgun o Amazon SES compiten en precio — y SES quizás tiene sentido mantener incluso después de migrar el resto. Email es de los pocos servicios AWS que puede ser racional mantener.",[368,6284,6286],{"id":6285},"dns-todo-cloudflare-o-mezclar","DNS — ¿todo CloudFlare o mezclar?",[12,6288,6289],{},"CloudFlare resuelve DNS, CDN, DDoS, WAF y workers en el plan gratis. Para la mayoría de los stacks, concentrar todo ahí simplifica operación y corta coste. La excepción es cumplimiento que exige separación geográfica de proveedor — algunos frameworks de gobernanza piden que DNS y CDN sean de proveedores distintos. En ese caso, CloudFlare DNS + Bunny CDN (o Fastly) cumple la separación.",[368,6291,6293],{"id":6292},"cumplimiento-lgpd-cambia-algo","¿Cumplimiento LGPD cambia algo?",[12,6295,6296],{},"LGPD no exige hospedaje en territorio brasileño. Exige que sepas dónde están los datos y que tengas contrato adecuado con el operador. Hetzner (Alemania), DigitalOcean (varias regiones), CloudFlare R2 (multi-región) y Magalu Cloud (Brasil) son todos compatibles con LGPD desde que el contrato esté en orden. Para quien prefiere dato en territorio nacional por preferencia de cliente, Magalu Cloud es la alternativa directa.",[12,6298,5406],{},[19,6300,6302],{"id":6301},"proximo-paso-concreto","Próximo paso concreto",[12,6304,6305],{},"Si llegaste hasta aquí, el próximo paso es la hoja de cálculo. Lista los doce servicios, marca cuáles tu stack usa, anota coste actual de cada uno, elige alternativa. En una tarde sabes si la migración vale el esfuerzo.",[12,6307,6308],{},"Cuando estés listo para provisionar el destino:",[224,6310,6311],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,6312,6313],{"__ignoreMap":229},[234,6314,6315,6317,6319,6321,6323],{"class":236,"line":237},[234,6316,1220],{"class":247},[234,6318,2958],{"class":251},[234,6320,5329],{"class":255},[234,6322,2964],{"class":383},[234,6324,2967],{"class":247},[12,6326,6327],{},"Corre en cualquier servidor Linux con Docker. Los primeros tres se vuelven quórum para el plano de control replicado. Envías jobs vía CLI, API o panel web embebido. El cluster decide dónde correr, hace health check, gestiona rolling deploys, emite certificados Let's Encrypt automáticamente.",[12,6329,6330,6331,2403,6335,101],{},"Para contexto adicional sobre costes y arquitectura, lee también ",[3337,6332,6334],{"href":6333},"\u002Fes\u002Fblog\u002Faws-ecs-vs-kubernetes-vs-auto-hospedado","AWS ECS vs Kubernetes vs auto-hospedado",[3337,6336,6338],{"href":6337},"\u002Fes\u002Fblog\u002Fcuanto-cuesta-alojar-un-saas-2026","Cuánto cuesta alojar un SaaS en 2026",[12,6340,6341],{},"La migración es más aburrida que difícil. Lo difícil es decidir empezar.",[3351,6343,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":6345},[6346,6347,6348,6349,6363,6364,6365,6366,6367,6368,6369,6370,6381],{"id":5390,"depth":244,"text":5391},{"id":5409,"depth":244,"text":5410},{"id":5422,"depth":244,"text":5423},{"id":5506,"depth":244,"text":5507,"children":6350},[6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362],{"id":5719,"depth":271,"text":5720},{"id":5729,"depth":271,"text":5730},{"id":5752,"depth":271,"text":5753},{"id":5762,"depth":271,"text":5763},{"id":5779,"depth":271,"text":5780},{"id":5789,"depth":271,"text":5790},{"id":5799,"depth":271,"text":5800},{"id":5806,"depth":271,"text":5807},{"id":5816,"depth":271,"text":5817},{"id":5829,"depth":271,"text":5830},{"id":5849,"depth":271,"text":5850},{"id":5859,"depth":271,"text":5860},{"id":5881,"depth":244,"text":5882},{"id":5940,"depth":244,"text":5941},{"id":5979,"depth":244,"text":5980},{"id":6070,"depth":244,"text":6071},{"id":6103,"depth":244,"text":6104},{"id":6134,"depth":244,"text":6135},{"id":6158,"depth":244,"text":6159},{"id":6213,"depth":244,"text":6214,"children":6371},[6372,6373,6374,6375,6376,6377,6378,6379,6380],{"id":6217,"depth":271,"text":6218},{"id":6224,"depth":271,"text":6225},{"id":6231,"depth":271,"text":6232},{"id":6238,"depth":271,"text":6239},{"id":6248,"depth":271,"text":6249},{"id":6271,"depth":271,"text":6272},{"id":6278,"depth":271,"text":6279},{"id":6285,"depth":271,"text":6286},{"id":6292,"depth":271,"text":6293},{"id":6301,"depth":244,"text":6302},"case-study","2026-05-26","Migrar de AWS a cloud más barato (Hetzner\u002FDO) o auto-hospedado parece proyecto de 1 año. En la práctica, se puede hacer en 6-8 semanas si mapeas los 12 servicios AWS-only que tu stack usa de verdad.",{},"\u002Fes\u002Fblog\u002Fsalir-de-aws-sin-reescribir-el-stack","16 min",{"title":5382,"description":6384},{"loc":6386},"es\u002Fblog\u002Fsalir-de-aws-sin-reescribir-el-stack",[6392,6393,6394,6395,6396],"aws","migracion","costo","salida","guia","7t3Io1_05IyDD4uz6Hub49VPeOsK60ryeoLqblj3EKc",{"id":6399,"title":6400,"author":7,"body":6401,"category":3379,"cover":3380,"date":7502,"description":7503,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":7504,"navigation":411,"path":7505,"readingTime":4402,"seo":7506,"sitemap":7507,"stem":7508,"tags":7509,"__hash__":7513},"blog_es\u002Fes\u002Fblog\u002Fredis-en-produccion-gestionado-vs-auto-hospedado.md","Redis (y Valkey) en producción: gestionado vs auto-hospedado en 2026",{"type":9,"value":6402,"toc":7474},[6403,6417,6419,6438,6442,6445,6448,6454,6461,6465,6468,6474,6480,6486,6489,6495,6500,6505,6508,6514,6519,6524,6527,6533,6538,6548,6552,6555,6599,6603,6606,6610,6613,6645,6648,6652,6655,6669,6676,6680,6694,6697,6701,6734,6737,6741,6744,6758,6765,6769,6772,6853,6856,6860,6863,6869,6875,6882,6885,6889,6892,6924,6927,6931,6938,6941,6944,7240,7244,7247,7273,7277,7280,7306,7310,7313,7334,7343,7346,7349,7353,7378,7392,7398,7407,7413,7419,7425,7431,7433,7436,7442,7445,7461,7472],[12,6404,6405,6406,6409,6410,2403,6413,6416],{},"La pregunta \"¿Redis gestionado o auto-hospedado?\" se volvió otra pregunta a finales de marzo de 2024. Fue cuando la empresa detrás de Redis cambió la licencia de Apache 2.0 \u002F BSD a una combinación de RSAL con SSPL — un par de licencias \"source available\" diseñadas para impedir que proveedores de nube ofrecieran Redis como servicio sin licenciamiento comercial. La reacción fue rápida: la Linux Foundation lanzó ",[27,6407,6408],{},"Valkey"," como fork directo de la última versión BSD, con AWS, Google y Oracle financiando el desarrollo. En paralelo, proyectos que ya existían — ",[27,6411,6412],{},"KeyDB",[27,6414,6415],{},"Dragonfly"," — pasaron a aparecer con más frecuencia en benchmarks de empresas que estaban reevaluando el stack.",[19,6418,22],{"id":21},[12,6420,6421,6422,6425,6426,6428,6429,6431,6432,6434,6435,6437],{},"En 2026, \"Redis en producción\" se volvió una categoría con cuatro implementaciones disputando el mismo protocolo: ",[27,6423,6424],{},"Redis OSS"," (BSD pre-2024 o RSAL post), ",[27,6427,6408],{}," (BSD, drop-in por el fork), ",[27,6430,6412],{}," (multi-thread, fork antiguo) y ",[27,6433,6415],{}," (BSL, reescritura desde cero en C++). Auto-hospedar cualquiera de los cuatro cuesta entre R$30 y R$130 al mes en VPS Hetzner. El camino gestionado cuesta desde R$75 (ElastiCache micro) hasta R$1.000\u002Fmes (instancia de 13 GB), más Upstash con cobro serverless variando US$0–100\u002Fmes. Para startup con MRR por debajo de R$200k, ",[27,6436,5573],{}," en un cluster propio ahorra entre R$300 y R$1.500 al mes comparado al gestionado, elimina exposición a la licencia RSAL y mantiene compatibilidad total con clientes Redis. Cambiar el stack después de adoptar la versión comercial es dolor real — empezar con la versión amigable a OSS es la apuesta con menor coste de salida. Este post compara los cuatro productos, los tres caminos gestionados (ElastiCache, Upstash, Redis Cloud) y la configuración mínima para correr Valkey en producción sin perder noches de sueño.",[19,6439,6441],{"id":6440},"la-historia-corta-del-cambio-de-licencia","La historia corta del cambio de licencia",[12,6443,6444],{},"Antes de marzo de 2024, \"Redis\" era el cache OSS dominante: BSD, ecosistema gigante, presente en cualquier stack que hubiera cabido la palabra \"Rails\" o \"Node\" en el currículum. El proveedor comercial — Redis Inc, antigua Redis Labs — vivía bien del producto gestionado y de los módulos de pago (Search, JSON, TimeSeries).",[12,6446,6447],{},"Llegó el anuncio: la versión 7.4 en adelante saldría bajo RSAL + SSPL, no más BSD. En términos prácticos, el cambio apuntó directamente a AWS, Google y Azure. La lectura interna de quien produce software open source fue otra: \"si pasó con Redis, puede pasar con cualquier proyecto VC-funded\". Fue el tercer caso reciente — después de Elastic en 2021 y MongoDB en 2018 — en que un proyecto que parecía consolidado cambió las reglas.",[12,6449,6450,6451,6453],{},"La Linux Foundation fue rápida. Cinco días después del anuncio, ",[27,6452,6408],{}," fue formado como fork de la última versión BSD (7.2.4), con governanza independiente y backers de peso: AWS, Google Cloud, Oracle, Ericsson, Snap. En poco más de un año, AWS ya había migrado el motor por defecto de ElastiCache a Valkey. Google Memorystore siguió. En 2026, Valkey dejó de ser \"fork experimental\" para volverse referencia creciente — con versiones 7.x y 8.x ya incorporando optimizaciones propias que ni siquiera fueron ofrecidas a Redis OSS.",[12,6455,6456,6457,6460],{},"La lección operacional para quien está eligiendo cache hoy: ",[27,6458,6459],{},"el mainstream se movió",". Ya no hay la inercia de \"nadie fue despedido por elegir Redis\" — la pregunta en la entrevista de arquitectura se volvió \"¿por qué Redis y no Valkey?\". Y la respuesta honesta, en la mayoría de los casos, es \"costumbre\".",[19,6462,6464],{"id":6463},"cuales-son-los-cuatro-productos-disputando-ese-mercado","¿Cuáles son los cuatro productos disputando ese mercado?",[368,6466,6424],{"id":6467},"redis-oss",[12,6469,6470,6473],{},[27,6471,6472],{},"El original."," Versiones anteriores a 7.4 aún están bajo BSD y siguen usables indefinidamente — nadie revoca licencia retroactivamente. Versiones 7.4 en adelante salen bajo RSAL\u002FSSPL.",[12,6475,6476,6479],{},[27,6477,6478],{},"Pros",": comunidad aún enorme, batter-tested en producción desde hace más de una década, ecosistema más rico (módulos, integraciones, libros, talks). Casi toda client library testeó primero contra Redis OSS.",[12,6481,6482,6485],{},[27,6483,6484],{},"Cons",": la RSAL impide ofrecer-as-a-service sin licenciamiento comercial. Para quien opera Redis para uso interno, eso es irrelevante — la restricción es sobre reventa. El riesgo real es estratégico: si el proveedor cambió la licencia una vez, puede cambiar de nuevo. Adoptar Redis OSS en 2026 significa apostar que la próxima feature crítica va a bajar a rama abierta, y no quedarse en el producto comercial.",[368,6487,6408],{"id":6488},"valkey",[12,6490,6491,6494],{},[27,6492,6493],{},"El fork de la Linux Foundation."," Tomó el código de la 7.2.4 BSD y siguió desarrollando. Drop-in replacement a nivel de protocolo: ningún cliente necesita cambiar una línea de código para cambiar Redis por Valkey.",[12,6496,6497,6499],{},[27,6498,6478],{},": BSD permanente garantizado por governanza neutra (no es una empresa, es fundación). Backers grandes alinean incentivos para mantener el proyecto saludable. Paridad técnica con Redis 7.x y velocidad de desarrollo creciente.",[12,6501,6502,6504],{},[27,6503,6484],{},": la marca aún se está construyendo — algunos plugins de terceros y SDKs muy específicos aún solo listan \"Redis\" en el README. En 2026 eso es cada vez más cosmético, pero puede aparecer en integraciones antiguas que necesitan pequeña adaptación.",[368,6506,6412],{"id":6507},"keydb",[12,6509,6510,6513],{},[27,6511,6512],{},"El fork multi-thread."," Existe desde 2019, fue adquirido por Snap en 2022, hoy vive como proyecto Snap-Telemetry. La diferencia arquitectural es fundamental: Redis OSS y Valkey son single-thread por diseño (un thread principal procesa todos los comandos). KeyDB corre multi-thread por defecto.",[12,6515,6516,6518],{},[27,6517,6478],{},": en CPUs con 4+ cores, KeyDB entrega 2 a 3 veces más throughput que Redis single-thread en el mismo hardware. API es compatible, así que el cliente no cambia. Para workloads CPU-bound con volumen alto, es la elección obvia.",[12,6520,6521,6523],{},[27,6522,6484],{},": comunidad menor, ritmo de adopción de nuevas features Redis suele quedar trimestres atrás. Algunas features nuevas de Redis (Functions, ciertas extensiones) tardan en aparecer en KeyDB.",[368,6525,6415],{"id":6526},"dragonfly",[12,6528,6529,6532],{},[27,6530,6531],{},"La reescritura."," No es fork — es implementación nueva en C++ moderno, con hash table diseñada para cache (no la estructura genérica de Redis), usando io_uring en Linux para I\u002FO asíncrono. Compatibilidad a nivel del protocolo, no a nivel del código.",[12,6534,6535,6537],{},[27,6536,6478],{},": claims de 25× throughput en benchmarks específicos (pipelines pesados en hardware moderno). Memory efficiency real — 2 a 3 veces más datos en la misma RAM que Redis. Sin GIL implícito de single-thread; escala vertical en una máquina con 32+ cores.",[12,6539,6540,6542,6543,6547],{},[27,6541,6484],{},": licencia BSL (Business Source License) — queda cerrada por 4 años antes de volverse Apache 2.0. Es exactamente el mismo patrón de licencia que pegó a otros proyectos de la industria de orquestación por sorpresa, y que tratamos en nuestro post sobre ",[3337,6544,6546],{"href":6545},"\u002Fes\u002Fblog\u002Fpor-que-creamos-heroctl","por qué creamos HeroCtl",". Algunos commands aún incompatibles con Redis en casos de borde (scripts Lua complejos, ciertas operaciones de cluster).",[19,6549,6551],{"id":6550},"cual-elegir-para-nuevo-proyecto-en-2026","¿Cuál elegir para nuevo proyecto en 2026?",[12,6553,6554],{},"El árbol de decisión corto:",[2735,6556,6557,6566,6574,6582,6591],{},[70,6558,6559,6562,6563,6565],{},[27,6560,6561],{},"Default sensato",": ",[27,6564,6408],{},". BSD permanente, paridad Redis, cliente no necesita cambiar, futuro garantizado por backers grandes. No hay razón técnica para preferir Redis OSS para proyecto nuevo en 2026.",[70,6567,6568,6562,6571,6573],{},[27,6569,6570],{},"Performance crítica",[27,6572,6415],{},", si la aplicación sostiene por encima de 100 mil operaciones por segundo y el equipo acepta el riesgo de licencia BSL.",[70,6575,6576,6562,6579,6581],{},[27,6577,6578],{},"Multi-thread sin reescritura",[27,6580,6412],{},", si el cuello de botella es CPU en hardware grande y el equipo prefiere no migrar a Dragonfly.",[70,6583,6584,6562,6587,6590],{},[27,6585,6586],{},"Simplicidad extrema (1 VPS, bajo volumen)",[27,6588,6589],{},"Redis OSS 7.2.4 BSD"," aún funciona perfectamente. Cristalizó como versión estable; va a correr en cualquier Debian\u002FAlpine los próximos cinco años sin quejarse.",[70,6592,6593,6562,6596,6598],{},[27,6594,6595],{},"Migrando de Redis Labs gestionado",[27,6597,6408],{}," es drop-in. Cero código cambiando. La migración es solo operacional — replicación, swap de DNS, rollback si necesario.",[19,6600,6602],{"id":6601},"gestionado-vs-auto-hospedado-la-cuenta-sin-adornos","Gestionado vs auto-hospedado: la cuenta sin adornos",[12,6604,6605],{},"Los números abajo son precio de tabla en mayo de 2026, cambio R$5\u002FUSD.",[368,6607,6609],{"id":6608},"aws-elasticache","AWS ElastiCache",[12,6611,6612],{},"Crece en escalones por instancia:",[2735,6614,6615,6624,6630,6639],{},[70,6616,6617,6620,6621],{},[231,6618,6619],{},"cache.t4g.micro"," (1 GB): cerca de US$15\u002Fmes = ",[27,6622,6623],{},"R$75\u002Fmes",[70,6625,6626,6629],{},[231,6627,6628],{},"cache.t4g.small"," (2 GB): US$30\u002Fmes = R$150\u002Fmes",[70,6631,6632,6635,6636],{},[231,6633,6634],{},"cache.r6g.large"," (13 GB): cerca de US$200\u002Fmes = ",[27,6637,6638],{},"R$1.000\u002Fmes",[70,6640,6641,6644],{},[231,6642,6643],{},"cache.r6g.xlarge"," (26 GB): cerca de US$400\u002Fmes = R$2.000\u002Fmes",[12,6646,6647],{},"Multi-AZ duplica el precio (réplica en otra zona). Backup automático está incluido. Multi-AZ failover real es el argumento principal — pagas para no tener que pensar en eso.",[368,6649,6651],{"id":6650},"upstash","Upstash",[12,6653,6654],{},"Cobro serverless por comando:",[2735,6656,6657,6660,6663,6666],{},[70,6658,6659],{},"Free tier: 256 MB, 500k commands\u002Fdía",[70,6661,6662],{},"Pay-as-you-go: US$0,2 por 100k commands",[70,6664,6665],{},"Para startup con volumen medio (10M commands\u002Fdía): cerca de US$60\u002Fmes = R$300\u002Fmes",[70,6667,6668],{},"Para app con pico bajo: puede quedar entre US$0 y US$10\u002Fmes",[12,6670,6671,6672,6675],{},"La ventaja operacional es única: ",[27,6673,6674],{},"cero capacidad pre-asignada",". Si la app duerme, la cuenta duerme. Para Vercel\u002FCloudflare Workers, es el complemento natural. Para carga sostenida y predecible, queda más caro que ElastiCache.",[368,6677,6679],{"id":6678},"redis-cloud-oferta-directa-de-redis-inc","Redis Cloud (oferta directa de Redis Inc)",[2735,6681,6682,6685,6691],{},[70,6683,6684],{},"Plan Essentials 30MB: free",[70,6686,6687,6688],{},"Plan Pro 5GB single-region: cerca de US$50\u002Fmes = ",[27,6689,6690],{},"R$250\u002Fmes",[70,6692,6693],{},"Plan Pro 10GB multi-AZ: cerca de US$120\u002Fmes = R$600\u002Fmes",[12,6695,6696],{},"Incluye módulos comerciales (Search, JSON, TimeSeries) que no existen en Valkey ni en Redis OSS. Si usas esos módulos, no hay alternativa directa — es Redis Cloud o compras licencia comercial y auto-hospedas.",[368,6698,6700],{"id":6699},"auto-hospedado-en-hetzner","Auto-hospedado en Hetzner",[2735,6702,6703,6713,6719,6728],{},[70,6704,6705,6708,6709,6712],{},[27,6706,6707],{},"CPX21"," (3 vCPU, 4 GB RAM, 80 GB SSD): €7,99 = ",[27,6710,6711],{},"R$44\u002Fmes",". Cabe Valkey de 2 GB con holgura.",[70,6714,6715,6718],{},[27,6716,6717],{},"CPX31"," (4 vCPU, 8 GB RAM, 160 GB SSD): €13,99 = R$78\u002Fmes.",[70,6720,6721,6724,6725,101],{},[27,6722,6723],{},"Cluster de 3 CPX21 para Valkey + Sentinel HA",": 3 × €7,99 = €24\u002Fmes = ",[27,6726,6727],{},"R$130\u002Fmes",[70,6729,6730,6733],{},[27,6731,6732],{},"Cluster de 3 CPX31 para datos serios",": €42\u002Fmes = R$230\u002Fmes.",[12,6735,6736],{},"Para DigitalOcean, Linode, Vultr, multiplica por aproximadamente 1,5×. Para AWS EC2, multiplica por 2×. Pero en cualquier caso queda más barato que el gestionado equivalente.",[368,6738,6740],{"id":6739},"diferencia-practica","Diferencia práctica",[12,6742,6743],{},"Para workload de cache de 8 GB con replicación:",[2735,6745,6746,6749,6752,6755],{},[70,6747,6748],{},"ElastiCache Multi-AZ: ~R$1.000\u002Fmes",[70,6750,6751],{},"Redis Cloud Pro Multi-AZ: ~R$600\u002Fmes",[70,6753,6754],{},"Valkey self-hosted en 3× Hetzner CPX31: R$230\u002Fmes",[70,6756,6757],{},"Valkey single-node en 1× Hetzner CPX31 + backup S3: R$80\u002Fmes",[12,6759,6760,6761,6764],{},"Quien elige el camino gestionado paga ",[27,6762,6763],{},"3 a 10 veces más"," por el mismo throughput. La diferencia es lo que compras con eso: SLA contractual, multi-AZ failover automático, ausencia de pager a las 3 de la mañana. Para equipo pequeño, eso puede valer el precio. Para equipo que ya opera servidores Linux en producción, generalmente no vale la pena.",[19,6766,6768],{"id":6767},"stack-minimo-de-valkey-production-grade","Stack mínimo de Valkey production-grade",[12,6770,6771],{},"Configuración que aguanta producción real sin teatro:",[2735,6773,6774,6780,6789,6804,6810,6816,6822,6828],{},[70,6775,6776,6779],{},[27,6777,6778],{},"Container o systemd service en VPS dedicado."," No comparte máquina con la aplicación — cache y app compiten por RAM, y cuando da error da error para los dos al mismo tiempo.",[70,6781,6782,6788],{},[27,6783,6784,6787],{},[231,6785,6786],{},"maxmemory"," configurado"," entre 50 y 70% de la RAM disponible. Sobrar memoria para el sistema y para los buffers de red es más importante que tener los últimos megabytes para cache.",[70,6790,6791,6562,6796,6799,6800,6803],{},[27,6792,6793],{},[231,6794,6795],{},"maxmemory-policy",[231,6797,6798],{},"allkeys-lru"," si modo cache puro (tirar claves antiguas cuando llene). ",[231,6801,6802],{},"noeviction"," si modo storage (queue, sesiones) — ahí prefiere error de write a perder datos silenciosamente.",[70,6805,6806,6809],{},[27,6807,6808],{},"AOF persistence"," si la carga es cola de jobs (Sidekiq, BullMQ, Resque). Sin AOF, un restart pierde cualquier job que estaba enfilado pero no procesado. RDB es insuficiente en ese escenario porque snapshot es periódico.",[70,6811,6812,6815],{},[27,6813,6814],{},"RDB suficiente"," si la carga es cache puro (Rails cache, Django cache). Si reiniciar perdiendo cache solo significa \"request lento por algunos segundos mientras recalienta\", AOF es overhead innecesario.",[70,6817,6818,6821],{},[27,6819,6820],{},"Replicación async para standby"," en un segundo nodo. Failover manual con swap de DNS interno es aceptable para mucho caso. Failover automático cuesta Sentinel o Cluster.",[70,6823,6824,6827],{},[27,6825,6826],{},"Backup AOF + RDB para S3"," o compatible, diariamente. Restic o rclone resuelven bien.",[70,6829,6830,6833,6834,6837,6838,571,6841,571,6844,571,6847,571,6850,101],{},[27,6831,6832],{},"Monitoring"," con ",[231,6835,6836],{},"redis_exporter"," exportando para Prometheus + alertas en Grafana o similar. Métricas críticas: ",[231,6839,6840],{},"connected_clients",[231,6842,6843],{},"used_memory",[231,6845,6846],{},"evicted_keys",[231,6848,6849],{},"keyspace_hits\u002Fmisses",[231,6851,6852],{},"latency_percentiles",[12,6854,6855],{},"Ese setup corre cómodo en CPX21 (R$44\u002Fmes) sirviendo 50k+ ops\u002Fs sostenidas para app medio.",[19,6857,6859],{"id":6858},"sentinel-o-cluster","¿Sentinel o Cluster?",[12,6861,6862],{},"Pregunta que confunde a mucho equipo viniendo de Redis por primera vez.",[12,6864,6865,6868],{},[27,6866,6867],{},"Sentinel",": 1 master + N réplicas + 3+ procesos sentinel monitoreando. Failover automático cuando el master cae — un sentinel detecta, los sentinels votan, una réplica se vuelve master, clientes reciben nuevo endpoint vía discovery. Todo en un único shard — todo el dataset cabe en un nodo.",[12,6870,6871,6874],{},[27,6872,6873],{},"Cluster",": dataset particionado en 16384 slots distribuidos en 3+ masters. Cada master tiene sus propias réplicas. Multi-shard, escala horizontal de capacidad — puedes tener 100 GB total con ningún nodo individual sosteniendo más de 20 GB.",[12,6876,6877,6878,6881],{},"La regla práctica: ",[27,6879,6880],{},"Sentinel basta hasta dataset de ~100 GB",". Por encima, Cluster es necesario. Para mayoría de las startups, Sentinel es la elección correcta por simplicidad — Cluster añade complejidad real (clave necesita hashtag para operaciones multi-key, scripts Lua quedan restringidos a un slot, algunos clientes tienen bugs en modo cluster).",[12,6883,6884],{},"No uses Cluster por status. Usa Sentinel hasta que la métrica fuerce.",[19,6886,6888],{"id":6887},"patrones-de-sidekiq-bullmq-y-compania","Patrones de Sidekiq, BullMQ y compañía",[12,6890,6891],{},"Uso real, no diagrama de marketing:",[2735,6893,6894,6900,6906,6912,6918],{},[70,6895,6896,6899],{},[27,6897,6898],{},"Sidekiq Ruby",": Redis necesita AOF. Sin AOF, cualquier crash pierde los jobs enfilados que aún no fueron retirados. Sidekiq Pro añade \"reliable fetch\" que mejora — pero el backstop sigue siendo AOF.",[70,6901,6902,6905],{},[27,6903,6904],{},"BullMQ Node",": similar. AOF essential para durability. BullMQ usa estructuras de datos que dependen de atomicidad transaccional de Redis — restart sin AOF puede dejar cola en estado inconsistente.",[70,6907,6908,6911],{},[27,6909,6910],{},"Resque Ruby",": el padre de todos. AOF necesario por las mismas razones.",[70,6913,6914,6917],{},[27,6915,6916],{},"Cache puro (Rails.cache, Django cache, Laravel cache)",": puede correr sin AOF, RDB suficiente. Perder cache en un restart es aceptable.",[70,6919,6920,6923],{},[27,6921,6922],{},"Pub\u002Fsub puro",": ni siquiera necesita persistencia. Pub\u002Fsub es fire-and-forget por diseño.",[12,6925,6926],{},"Mezclar uso de cache y queue en el mismo Redis funciona — basta configurar AOF (la carga \"peor caso\" determina). Pero para workload serio, separar en dos instancias (una para cache sin AOF, otra para queue con AOF) es más limpio. Operacionalmente baratísimo si ya hay orquestador corriendo.",[19,6928,6930],{"id":6929},"elasticache-sao-paulo-es-confiable","¿ElastiCache São Paulo es confiable?",[12,6932,6933,6934,6937],{},"Sí — 99.99% uptime SLA contractual, multi-AZ en la región São Paulo (",[231,6935,6936],{},"sa-east-1","), backup automático, failover testeado. Latencia de la app desde São Paulo a ElastiCache São Paulo queda en 1-3ms, indistinguible de Redis local para mayoría de los workloads.",[12,6939,6940],{},"El punto débil no es confiabilidad técnica, es coste y lock-in. AWS Brazil cobra cerca de 30% más caro que regiones norteamericanas por el mismo recurso. Y migrar de ElastiCache a otro proveedor después implica dump\u002Frestore + cutover coordinado — no es apocalipsis, pero es trabajo de fin de semana.",[19,6942,6943],{"id":3837},"Tabla comparativa: 12 criterios",[119,6945,6946,6967],{},[122,6947,6948],{},[125,6949,6950,6952,6954,6956,6958,6960,6962,6964],{},[128,6951,2983],{},[128,6953,6424],{},[128,6955,6408],{},[128,6957,6412],{},[128,6959,6415],{},[128,6961,5445],{},[128,6963,6651],{},[128,6965,6966],{},"Self-hosted Valkey",[141,6968,6969,6994,7018,7040,7065,7086,7108,7129,7152,7176,7197,7218],{},[125,6970,6971,6974,6977,6980,6982,6985,6988,6991],{},[146,6972,6973],{},"Licencia",[146,6975,6976],{},"RSAL\u002FSSPL (7.4+)",[146,6978,6979],{},"BSD",[146,6981,6979],{},[146,6983,6984],{},"BSL → Apache 4 años",[146,6986,6987],{},"Comercial AWS",[146,6989,6990],{},"Comercial Upstash",[146,6992,6993],{},"BSD permanente",[125,6995,6996,6999,7002,7004,7007,7009,7012,7015],{},[146,6997,6998],{},"Threading",[146,7000,7001],{},"Single",[146,7003,7001],{},[146,7005,7006],{},"Multi",[146,7008,7006],{},[146,7010,7011],{},"Single (engine 7)",[146,7013,7014],{},"Serverless",[146,7016,7017],{},"Configurable",[125,7019,7020,7023,7026,7028,7030,7033,7035,7038],{},[146,7021,7022],{},"Compat. cliente Redis",[146,7024,7025],{},"100%",[146,7027,7025],{},[146,7029,7025],{},[146,7031,7032],{},"95%+",[146,7034,7025],{},[146,7036,7037],{},"100% (subset comandos)",[146,7039,7025],{},[125,7041,7042,7045,7048,7050,7053,7056,7059,7062],{},[146,7043,7044],{},"Throughput baseline",[146,7046,7047],{},"100k ops\u002Fs",[146,7049,7047],{},[146,7051,7052],{},"250k ops\u002Fs",[146,7054,7055],{},"1M+ ops\u002Fs",[146,7057,7058],{},"depende inst.",[146,7060,7061],{},"depende plan",[146,7063,7064],{},"100-250k ops\u002Fs",[125,7066,7067,7070,7072,7074,7076,7078,7081,7084],{},[146,7068,7069],{},"Persistencia AOF",[146,7071,3065],{},[146,7073,3065],{},[146,7075,3065],{},[146,7077,3065],{},[146,7079,7080],{},"Sí (snapshot)",[146,7082,7083],{},"Gestionada",[146,7085,3065],{},[125,7087,7088,7091,7093,7095,7097,7099,7102,7105],{},[146,7089,7090],{},"Replicación",[146,7092,3065],{},[146,7094,3065],{},[146,7096,3065],{},[146,7098,3065],{},[146,7100,7101],{},"Multi-AZ",[146,7103,7104],{},"Multi-region",[146,7106,7107],{},"Sí (config manual)",[125,7109,7110,7113,7116,7118,7120,7122,7125,7127],{},[146,7111,7112],{},"Failover automático",[146,7114,7115],{},"Sentinel\u002FCluster",[146,7117,7115],{},[146,7119,7115],{},[146,7121,6873],{},[146,7123,7124],{},"Built-in",[146,7126,7124],{},[146,7128,7115],{},[125,7130,7131,7134,7137,7139,7141,7143,7146,7149],{},[146,7132,7133],{},"Coste 8GB\u002Fmes (R$)",[146,7135,7136],{},"80 (VPS)",[146,7138,7136],{},[146,7140,7136],{},[146,7142,7136],{},[146,7144,7145],{},"1000 (Multi-AZ)",[146,7147,7148],{},"300-500",[146,7150,7151],{},"80-230",[125,7153,7154,7157,7160,7163,7165,7168,7171,7174],{},[146,7155,7156],{},"Lock-in",[146,7158,7159],{},"Medio (licencia)",[146,7161,7162],{},"Bajo",[146,7164,7162],{},[146,7166,7167],{},"Medio (BSL)",[146,7169,7170],{},"Alto (AWS)",[146,7172,7173],{},"Alto (Upstash API)",[146,7175,7162],{},[125,7177,7178,7181,7184,7186,7188,7190,7193,7195],{},[146,7179,7180],{},"Módulos premium",[146,7182,7183],{},"Pagos",[146,7185,3056],{},[146,7187,3056],{},[146,7189,3056],{},[146,7191,7192],{},"Add-on $$",[146,7194,3062],{},[146,7196,3056],{},[125,7198,7199,7202,7205,7207,7209,7211,7214,7216],{},[146,7200,7201],{},"Operacional",[146,7203,7204],{},"Tú",[146,7206,7204],{},[146,7208,7204],{},[146,7210,7204],{},[146,7212,7213],{},"AWS",[146,7215,6651],{},[146,7217,7204],{},[125,7219,7220,7223,7226,7229,7231,7233,7236,7238],{},[146,7221,7222],{},"Soporte SLA",[146,7224,7225],{},"Pago",[146,7227,7228],{},"Comunidad",[146,7230,7228],{},[146,7232,7225],{},[146,7234,7235],{},"Incluido",[146,7237,7235],{},[146,7239,7204],{},[19,7241,7243],{"id":7242},"cuando-aun-gestionado-tiene-sentido","Cuándo aún gestionado tiene sentido",[12,7245,7246],{},"La honestidad es mecanismo de defensa de cualquier recomendación técnica. Hay cuatro perfiles en que pagar por gestionado es la elección correcta:",[2735,7248,7249,7255,7261,7267],{},[70,7250,7251,7254],{},[27,7252,7253],{},"Equipo sin capacidad operacional para Redis cluster."," Si nadie en la empresa sabe debugar un master que ya no responde, o interpretar latencia de fork RDB, o cuidar de backup AOF — pagar AWS para hacer eso es racional. No es excusa, es división de trabajo.",[70,7256,7257,7260],{},[27,7258,7259],{},"Compliance que exige proveedor SOC2\u002FISO certificado."," Auditoría que pide \"proveedor certificado X\" no acepta \"corremos Valkey en un VPS Hetzner\". El camino es ElastiCache, Redis Cloud o similar con certificaciones en el contrato.",[70,7262,7263,7266],{},[27,7264,7265],{},"Volumen que necesita escalar instantáneo."," Aplicación que va de 100 req\u002Fs a 100k req\u002Fs en 5 minutos por una campaña viral — el camino serverless de Upstash es donde brilla. Auto-hospedado necesita capacidad reservada antes; serverless crece al instante.",[70,7268,7269,7272],{},[27,7270,7271],{},"Aplicación totalmente serverless."," Si la app corre en Vercel o Cloudflare Workers y Redis también necesita ser serverless por modelo de cobro, Upstash es prácticamente la única opción sana. Conectar funciones edge a un Redis en VPS implica cold start malo.",[19,7274,7276],{"id":7275},"cuando-auto-hospedar-es-obvio","Cuándo auto-hospedar es obvio",[12,7278,7279],{},"Y cuatro perfiles en que pagar gestionado es desperdicio:",[2735,7281,7282,7288,7294,7300],{},[70,7283,7284,7287],{},[27,7285,7286],{},"Startup con R$10k–R$200k MRR optimizando coste."," La diferencia entre R$80\u002Fmes y R$1.000\u002Fmes de cache es 1% del coste total de un SaaS pequeño; también son 11 horas de salario persona-hora de dev. Vale la pena hacer la cuenta.",[70,7289,7290,7293],{},[27,7291,7292],{},"Workload predecible."," Si el volumen de cache crece 10% al mes, no hay ventaja en escalar serverless. Capacidad reservada en VPS es más barata y más predecible.",[70,7295,7296,7299],{},[27,7297,7298],{},"Equipo tiene 1+ persona cómoda con Linux\u002FDocker."," Si ya tiene a alguien que opera Postgres, nginx, Docker — Redis\u002FValkey es más fácil que cualquiera de ellos. Curva de aprendizaje son días, no semanas.",[70,7301,7302,7305],{},[27,7303,7304],{},"Ya existe cluster propio."," Si la empresa corre orquestador (HeroCtl, Coolify, plataforma similar) con nodos sobrando, Valkey se vuelve solo otro job. Coste marginal cerca de cero — ya pagas por los nodos.",[19,7307,7309],{"id":7308},"heroctl-como-infraestructura-para-valkey","HeroCtl como infraestructura para Valkey",[12,7311,7312],{},"Para quien opera HeroCtl, correr Valkey en producción es ejercicio de configuración corta. Un archivo de ~30 líneas describe job con:",[2735,7314,7315,7318,7321,7324,7327],{},[70,7316,7317],{},"Container Valkey 8.x oficial",[70,7319,7320],{},"Volumen nombrado replicado entre nodos (datos sobreviven a kill -9 de servidor)",[70,7322,7323],{},"Recursos reservados (RAM y CPU) con límites duros",[70,7325,7326],{},"Health check en el ping Valkey",[70,7328,7329,7330,7333],{},"Enrutamiento interno entre servicios (la app habla con ",[231,7331,7332],{},"valkey.servicio.local"," sin exponer puerto a internet)",[12,7335,7336,7337,7339,7340,7342],{},"Backup automatizado AOF + RDB para S3-compatible está disponible en el plan ",[27,7338,4356],{}," — sin montar restic externo, sin cron manual en el host. Métricas Valkey salen por el ",[231,7341,6836],{}," corriendo como sidecar y aparecen en el Prometheus interno (ya incluido como job del propio cluster, sin stack externo).",[12,7344,7345],{},"Failover Sentinel está integrado al plano de control del orquestador: si el nodo del master Valkey cae, el cluster detecta en torno de 7 segundos y la réplica es promovida. La configuración de la app se actualiza vía descubrimiento de servicio — ningún redeploy manual.",[12,7347,7348],{},"Para startup con 4 servidores corriendo el orquestador, ese setup sustituye ElastiCache Multi-AZ entero a coste marginal cero (los servidores ya están allí). La diferencia mensual real es el salario-equivalente de una persona, dependiendo del tamaño de la operación.",[19,7350,7352],{"id":7351},"preguntas-que-recibimos","Preguntas que recibimos",[12,7354,7355,7358,7359,571,7362,571,7365,571,7368,571,7371,571,7374,7377],{},[27,7356,7357],{},"¿Valkey es compatible con client libraries Redis?","\nSí, en 100% de los casos prácticos. El protocolo es idéntico — ",[231,7360,7361],{},"redis-cli",[231,7363,7364],{},"node-redis",[231,7366,7367],{},"ioredis",[231,7369,7370],{},"redis-rb",[231,7372,7373],{},"redis-py",[231,7375,7376],{},"go-redis",", todos funcionan sin cambiar una línea. Lo que se cambia es solo el endpoint. En 2026, varias bibliotecas ya anuncian soporte explícito a Valkey en el README, pero eso es cosmético — el protocolo es el mismo.",[12,7379,7380,7383,7384,7387,7388,7391],{},[27,7381,7382],{},"¿Puedo migrar de Redis Labs gestionado a Valkey self-hosted sin downtime?","\nSí, con replicación. Configuras Valkey como réplica del Redis Labs (",[231,7385,7386],{},"REPLICAOF host port","), esperas sincronizar (algunos minutos a horas dependiendo del dataset), promueves Valkey a master (",[231,7389,7390],{},"REPLICAOF NO ONE","), haces cutover de DNS interno, decomisionas Redis Labs después de período de observación. Ventana de error real es de segundos durante el swap.",[12,7393,7394,7397],{},[27,7395,7396],{},"¿Dragonfly vale el riesgo de BSL?","\nDepende del horizonte de la empresa. BSL convierte a Apache 2.0 después de 4 años por el modelo estándar — entonces código de hoy será abierto hasta 2030. El riesgo es que la empresa detrás (DragonflyDB Inc) siga el camino de Redis Inc y haga la conversión menos amigable. Para workloads que exigen performance que Valkey no entrega (por encima de 500k ops\u002Fs sostenido), Dragonfly puede ser la elección correcta a pesar del riesgo. Para el resto, Valkey es más conservador.",[12,7399,7400,7403,7404,7406],{},[27,7401,7402],{},"¿Cuánto de RAM consume un Redis con 1 GB de datos útiles?","\nCuenta práctica: dataset de 1 GB ocupa entre 1,3 y 2 GB reales de RAM (overhead de estructura, fragmentación, buffers de cliente, replication backlog). Configurar ",[231,7405,6786],{}," en 60% de la RAM disponible es regla segura — instancia de 4 GB cabe ~2,5 GB de datos útiles con holgura.",[12,7408,7409,7412],{},[27,7410,7411],{},"¿Sidekiq necesita AOF de verdad? Los docs de Sidekiq dicen que se puede correr sin.","\nLos docs dicen que técnicamente corre. En producción, sin AOF, cualquier restart inesperado pierde jobs enfilados que estaban en el buffer. Para cola de \"envío de e-mail bienvenida\", lo descubres cuando el cliente reclama. Para cola de \"cobro recurrente\", lo descubres cuando contable reclama. AOF es barato (incremento de 5-10% de I\u002FO), el coste de no tenerlo es grande.",[12,7414,7415,7418],{},[27,7416,7417],{},"¿Cluster vs Sentinel para app procesando 50k jobs\u002Fdía?","\nSentinel. 50k jobs\u002Fdía son 0,6 ops\u002Fs media — caben en 100 MB de RAM Redis. Cluster es overkill por orden de magnitud. Sentinel resuelve failover automático con 1 master + 1 réplica + 3 sentinels (3 procesos sentinel en VPSs separados, pueden cohabitar con otras cosas).",[12,7420,7421,7424],{},[27,7422,7423],{},"¿ElastiCache São Paulo tiene latencia buena para app corriendo en São Paulo?","\nSí, 1-3ms p99 dentro de la misma AZ. El problema no es latencia — es coste y lock-in. Latencia solo se vuelve tema si la app está en otro proveedor (Hetzner FSN, DigitalOcean NYC) intentando hablar con ElastiCache São Paulo — ahí sube a 130-200ms y el argumento desaparece.",[12,7426,7427,7430],{},[27,7428,7429],{},"¿Cómo hacer backup de Valkey self-hosted que sobreviva a desastre?","\nTres capas. Primera: AOF persistente en disco local (sobrevive a restart). Segunda: snapshot RDB diario copiado para storage S3-compatible (Wasabi, Backblaze B2, Cloudflare R2 — todos más baratos que S3 de AWS para ese caso). Tercera: snapshot semanal copiado para otro proveedor de storage (segunda región, segundo proveedor). Restic o rclone hacen el trabajo. Coste total de almacenamiento para backup de Valkey de 4 GB: cerca de US$1\u002Fmes.",[19,7432,3310],{"id":3309},[12,7434,7435],{},"En 2026, \"Redis en producción\" se volvió pregunta con más matiz de lo que tenía en 2023. La licencia del producto original cambió, el fork Linux Foundation maduró, alternativas multi-thread están de pie, la oferta serverless tiene caso de uso real. Elegir entre las cuatro implementaciones y los tres caminos gestionados es ejercicio honesto — no hay respuesta única.",[12,7437,7438,7439,7441],{},"Nuestra recomendación default para startup en 2026: ",[27,7440,5573],{}," en un cluster propio, modo Sentinel, AOF activado si hay queue, monitoring con Prometheus. Coste en el rango de R$80–R$230\u002Fmes, contra R$600–R$2.000\u002Fmes de las alternativas gestionadas equivalentes. Compatibilidad total con cualquier biblioteca Redis. Sin exposición a la licencia RSAL. Migración reversible si se vuelve un problema.",[12,7443,7444],{},"Para poner ese stack de pie:",[224,7446,7447],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,7448,7449],{"__ignoreMap":229},[234,7450,7451,7453,7455,7457,7459],{"class":236,"line":237},[234,7452,1220],{"class":247},[234,7454,2958],{"class":251},[234,7456,2961],{"class":255},[234,7458,2964],{"class":383},[234,7460,2967],{"class":247},[12,7462,7463,7464,7468,7469,7471],{},"Y leer en paralelo: ",[3337,7465,7467],{"href":7466},"\u002Fes\u002Fblog\u002Fpostgres-en-produccion-gestionado-vs-auto-hospedado","Postgres en producción: gestionado vs auto-hospedado"," (mismo análisis para la base de datos) y ",[3337,7470,6338],{"href":6337}," (la cuenta consolidada de todo el stack).",[3351,7473,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":7475},[7476,7477,7478,7484,7485,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501],{"id":21,"depth":244,"text":22},{"id":6440,"depth":244,"text":6441},{"id":6463,"depth":244,"text":6464,"children":7479},[7480,7481,7482,7483],{"id":6467,"depth":271,"text":6424},{"id":6488,"depth":271,"text":6408},{"id":6507,"depth":271,"text":6412},{"id":6526,"depth":271,"text":6415},{"id":6550,"depth":244,"text":6551},{"id":6601,"depth":244,"text":6602,"children":7486},[7487,7488,7489,7490,7491],{"id":6608,"depth":271,"text":6609},{"id":6650,"depth":271,"text":6651},{"id":6678,"depth":271,"text":6679},{"id":6699,"depth":271,"text":6700},{"id":6739,"depth":271,"text":6740},{"id":6767,"depth":244,"text":6768},{"id":6858,"depth":244,"text":6859},{"id":6887,"depth":244,"text":6888},{"id":6929,"depth":244,"text":6930},{"id":3837,"depth":244,"text":6943},{"id":7242,"depth":244,"text":7243},{"id":7275,"depth":244,"text":7276},{"id":7308,"depth":244,"text":7309},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-05-20","Redis cambió de licencia en 2024, Valkey nació como fork OSS, Dragonfly bate benchmarks. En 2026, elegir cache ya no es elegir Redis — es elegir entre 4 productos. Análisis honesto con costes.",{},"\u002Fes\u002Fblog\u002Fredis-en-produccion-gestionado-vs-auto-hospedado",{"title":6400,"description":7503},{"loc":7505},"es\u002Fblog\u002Fredis-en-produccion-gestionado-vs-auto-hospedado",[7510,6488,7511,7512,3394],"redis","cache","self-hosted","N3mLPFFjt2L-yR8G9IKJ-p0pd4dVOinPYOpCKt1ukTI",{"id":7515,"title":7516,"author":7,"body":7517,"category":8761,"cover":3380,"date":8762,"description":8763,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":8764,"navigation":411,"path":8765,"readingTime":8766,"seo":8767,"sitemap":8768,"stem":8769,"tags":8770,"__hash__":8776},"blog_es\u002Fes\u002Fblog\u002Fgithub-actions-vs-gitlab-ci-vs-drone.md","GitHub Actions vs GitLab CI vs Drone: qué CI\u002FCD elegir para startup",{"type":9,"value":7518,"toc":8724},[7519,7526,7529,7533,7548,7554,7560,7566,7569,7572,7576,7579,7582,7606,7609,7613,7620,7624,7656,7660,7663,7708,7711,7714,7717,7721,7724,7727,7747,7750,7754,7757,7761,7797,7801,7804,7809,7858,7861,7867,7881,7884,7888,7891,7895,7938,7942,7968,7972,7975,7982,7986,7989,8109,8116,8119,8123,8126,8187,8190,8192,8196,8375,8378,8382,8385,8389,8395,8399,8405,8408,8412,8418,8421,8425,8431,8435,8441,8445,8448,8451,8477,8487,8490,8494,8498,8501,8517,8521,8524,8535,8538,8542,8545,8548,8552,8555,8573,8576,8578,8583,8586,8591,8594,8599,8602,8607,8610,8615,8618,8623,8626,8631,8638,8643,8646,8651,8654,8656,8660,8663,8695,8698,8703,8706,8717],[12,7520,7521,7522,7525],{},"La elección de CI\u002FCD en 2026 ya no es sobre \"qué herramienta tiene más features\". Las tres serias — GitHub Actions, GitLab CI, Drone (y su fork Woodpecker) — hacen lo básico bien. La elección real es sobre ",[27,7523,7524],{},"dónde tu dolor va a aparecer primero",": en la factura a fin de mes, en la complejidad del workflow cuando el monorepo crezca, o a la hora de subir un runner que nadie entiende cuando el dev senior se va de vacaciones.",[12,7527,7528],{},"Este post es una comparación honesta para tech leads decidiendo CI\u002FCD en 2026. Sin ranking artificial, sin columna en la que una herramienta sea \"campeona\" en todo. Tradeoffs explícitos, números en euros, y una recomendación por perfil al final.",[19,7530,7532],{"id":7531},"tldr-200-palabras","TL;DR (200 palabras)",[12,7534,7535,7536,571,7539,571,7542,2403,7545,101],{},"La decisión de CI\u002FCD en 2026 sigue cuatro fuerzas: ",[27,7537,7538],{},"dónde está hospedado el código",[27,7540,7541],{},"coste de minutos",[27,7543,7544],{},"complejidad de workflow",[27,7546,7547],{},"disposición a operar self-hosted",[12,7549,7550,7553],{},[27,7551,7552],{},"GitHub Actions"," ganó mindshare absoluto para proyectos en GitHub. Es gratis hasta 2000 minutos\u002Fmes en repos públicos; después cuesta US$0,008\u002Fmin en runner Linux — entre US$5 y US$30\u002Fmes para startup típica (5 € a 30 €). Marketplace tiene 10 mil acciones listas. El talón es el pricing de minutos cuando el volumen crece.",[12,7555,7556,7559],{},[27,7557,7558],{},"GitLab CI"," es más completo: grafo de dependencias entre jobs nativo, parent-child pipelines, monorepo handling mejor, registry de imágenes incluido, scanning de seguridad embebido. Self-hosted (Community Edition) es gratuito pero exige 4 a 8 GB de RAM y operación activa. SaaS Premium es US$29\u002Fusuario\u002Fmes — caro para equipo grande.",[12,7561,7562,7565],{},[27,7563,7564],{},"Drone\u002FWoodpecker"," auto-hospedado es la opción para reducir coste a cero variable. Un servidor de 5 € a 15 €\u002Fmes corre CI para cinco a diez proyectos. Cuesta en ops: tú operas los runners.",[12,7567,7568],{},"Para startup ES pequeña en GitHub, empieza en el plan gratuito de Actions. Cuando pase de US$30\u002Fmes, considera Woodpecker self-hosted. Para empresa que valora CI + issue tracker + registry en un producto solo, GitLab self-hosted.",[12,7570,7571],{},"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",[19,7573,7575],{"id":7574},"por-que-esa-decision-importa-mas-de-lo-que-parece","¿Por qué esa decisión importa más de lo que parece?",[12,7577,7578],{},"CI\u002FCD es la infraestructura más usada de cualquier equipo de producto: cada commit toca el sistema, cada PR depende de él, cada deploy pasa por él. Una elección equivocada no te rompe en el primer mes — te rompe en el tercer año, cuando migrar cuesta cuatro semanas de dos personas y pagas eso mientras el roadmap queda parado.",[12,7580,7581],{},"Los tres síntomas que indican que la elección fue equivocada:",[67,7583,7584,7590,7600],{},[70,7585,7586,7589],{},[27,7587,7588],{},"La factura crece más rápido que el equipo."," Si el coste de CI se duplica cada seis meses sin que el volumen de deploys lo justifique, el pricing model no es el tuyo.",[70,7591,7592,7595,7596,7599],{},[27,7593,7594],{},"Los workflows se vuelven copy-paste."," Si cada nuevo proyecto empieza con ",[231,7597,7598],{},"cp -r .github\u002Fworkflows\u002F",", la herramienta no tiene composición decente.",[70,7601,7602,7605],{},[27,7603,7604],{},"Fallos en CI tardan más de una hora en debuguearse."," Si reproducir el error local exige correr una imagen Docker que nadie sabe montar, el build no es portable.",[12,7607,7608],{},"Los tres competidores principales resuelven esos síntomas de formas diferentes. Vamos por partes.",[19,7610,7612],{"id":7611},"github-actions-el-estandar-de-facto-vale-el-precio","GitHub Actions: el estándar de facto — ¿vale el precio?",[12,7614,7615,7616,7619],{},"Si tu código está en GitHub, Actions tiene una ventaja estructural que no se puede ignorar: cero fricción de integración. Creas ",[231,7617,7618],{},".github\u002Fworkflows\u002Fci.yml",", haces push, y está corriendo. Sin registro separado, sin token cruzado, sin webhook que configurar.",[368,7621,7623],{"id":7622},"lo-que-actions-hace-bien","Lo que Actions hace bien",[2735,7625,7626,7632,7638,7644,7650],{},[70,7627,7628,7631],{},[27,7629,7630],{},"Marketplace gigante."," Más de diez mil acciones listas para tareas comunes: setup de Node, Python, Go; deploy a AWS, GCP, Azure; firma de imágenes; scanning de seguridad. La mayoría es mantenida por el propio proveedor de la tecnología (HashiCorp publica la suya, AWS publica la suya, etc).",[70,7633,7634,7637],{},[27,7635,7636],{},"Matrix builds."," Correr la misma suite contra cinco versiones de Node o tres sistemas operativos es una clave en tres líneas.",[70,7639,7640,7643],{},[27,7641,7642],{},"Reusable workflows."," Desde 2021 puedes extraer workflows compartidos entre repos de la misma organización — soluciona el problema de \"copy-paste entre proyectos\" para equipos medianos.",[70,7645,7646,7649],{},[27,7647,7648],{},"Deployment protection rules."," Approvals manuales, ventanas de horario, restricción por branch — todo configurable sin plugin.",[70,7651,7652,7655],{},[27,7653,7654],{},"Self-hosted runners."," Puedes correr el agente en tu propia infra y usar la UI de Actions solo como orquestador. Resuelve el problema de minutos para equipos con volumen alto.",[368,7657,7659],{"id":7658},"lo-que-actions-cobra-caro","Lo que Actions cobra caro",[12,7661,7662],{},"El modelo de cobro es por minuto, y los números importan:",[119,7664,7665,7674],{},[122,7666,7667],{},[125,7668,7669,7672],{},[128,7670,7671],{},"Tipo de runner",[128,7673,136],{},[141,7675,7676,7684,7692,7700],{},[125,7677,7678,7681],{},[146,7679,7680],{},"Linux 2 vCPU (estándar)",[146,7682,7683],{},"US$0,008\u002Fmin (0,007 €)",[125,7685,7686,7689],{},[146,7687,7688],{},"Windows 2 vCPU",[146,7690,7691],{},"US$0,016\u002Fmin (0,014 €)",[125,7693,7694,7697],{},[146,7695,7696],{},"macOS (necesario para builds iOS)",[146,7698,7699],{},"US$0,08\u002Fmin (0,07 €)",[125,7701,7702,7705],{},[146,7703,7704],{},"Larger Linux (4 vCPU+)",[146,7706,7707],{},"US$0,016\u002Fmin y arriba",[12,7709,7710],{},"Para una startup en GitHub con cinco devs y workflow razonable (build + test + lint en cada PR), el consumo típico es 800 a 2500 minutos\u002Fmes en Linux. Eso da US$6 a US$20\u002Fmes — o sea, entre 5 € y 18 €. Cabe en la línea de \"herramientas de dev\" sin dolor.",[12,7712,7713],{},"Cuando duele: workflows pesados (E2E con Playwright, builds Rust, tests que suben Postgres + Redis en cada job) fácilmente pasan de 10 mil minutos\u002Fmes. A US$0,008\u002Fmin eso se vuelve US$80\u002Fmes — 70 €. Multiplica por 12 y estás pagando 850 €\u002Faño en CI.",[12,7715,7716],{},"Builds macOS son el peor caso: US$0,40\u002Fmin es diez veces más que Linux. Equipos que mantienen apps iOS gastan tres a cuatro veces más en CI que en infra de producción.",[368,7718,7720],{"id":7719},"self-hosted-runners-de-actions-resuelven","¿Self-hosted runners de Actions resuelven?",[12,7722,7723],{},"Parcialmente. Corres el binario del runner en una máquina tuya, lo registras en el repo o en la organización, y los jobs van ahí en lugar del pool gestionado. Coste de minuto va a cero — pagas solo la máquina.",[12,7725,7726],{},"Pero tres trampas:",[67,7728,7729,7735,7741],{},[70,7730,7731,7734],{},[27,7732,7733],{},"Mantenimiento del runner."," La versión actualiza con frecuencia; runners desactualizados empiezan a fallar silenciosamente. Sin automatización, se vuelve tarea de operación manual.",[70,7736,7737,7740],{},[27,7738,7739],{},"Scaling manual."," Si el equipo tiene cinco devs abriendo 20 PRs simultáneos, un runner serializa todo. Necesitas N runners — y provisionar\u002Fdesprovisionar conforme demanda exige tooling adicional.",[70,7742,7743,7746],{},[27,7744,7745],{},"Seguridad en repos públicos."," Self-hosted runners en repo público son una puerta abierta para que cualquier fork malicioso corra código arbitrario en tu máquina. Siempre restrito a repos privados u organización confiable.",[12,7748,7749],{},"La solución madura es Actions Runner Controller (ARC): un operador que sube runners on-demand en un cluster Kubernetes o similar. Resuelve scaling, pero añade una capa entera de infraestructura — no es trivial.",[19,7751,7753],{"id":7752},"gitlab-ci-el-competidor-pesado-aun-tiene-sentido","GitLab CI: el competidor \"pesado\" ¿aún tiene sentido?",[12,7755,7756],{},"GitLab CI es más antiguo que Actions, más completo en features, y menos popular fuera de los equipos que ya están en la plataforma GitLab. La pregunta correcta no es \"¿GitLab CI es mejor que Actions?\", es \"¿vale la pena migrar a GitLab para usar GitLab CI?\"",[368,7758,7760],{"id":7759},"lo-que-gitlab-ci-hace-mejor","Lo que GitLab CI hace mejor",[2735,7762,7763,7773,7779,7785,7791],{},[70,7764,7765,7768,7769,7772],{},[27,7766,7767],{},"Grafo de dependencias (DAG)."," Nativo, sin tooling externo. Declaras ",[231,7770,7771],{},"needs: [job_a, job_b]"," y los jobs corren en paralelo respetando dependencias. Para workflows con 30+ jobs (monorepo grande, varios lenguajes, deploy multi-entorno), eso es la diferencia entre 8 minutos y 25 minutos por pipeline.",[70,7774,7775,7778],{},[27,7776,7777],{},"Parent-child pipelines."," Pipeline grande puede disparar pipelines hijos con lógica condicional — útil para monorepo donde solo servicios alterados necesitan buildar.",[70,7780,7781,7784],{},[27,7782,7783],{},"Registry de imágenes incluido."," Cada proyecto viene con un registry de container privado nativo. Sin configurar secretos para Amazon ECR, Docker Hub o similar.",[70,7786,7787,7790],{},[27,7788,7789],{},"Pages, security scanning, code quality, dependency scanning"," — todo embebido en la plataforma. En Actions cada uno es una acción separada del marketplace.",[70,7792,7793,7796],{},[27,7794,7795],{},"Merge request integration profundo."," Pipelines aparecen dentro del MR con diff de cobertura, comparación de bundle size, comparación de tiempo de build. En Actions los checks aparecen como links — en GitLab son datos estructurados.",[368,7798,7800],{"id":7799},"donde-gitlab-ci-cobra-caro","Donde GitLab CI cobra caro",[12,7802,7803],{},"Dos dimensiones.",[12,7805,7806],{},[27,7807,7808],{},"Pricing SaaS:",[119,7810,7811,7823],{},[122,7812,7813],{},[125,7814,7815,7818,7820],{},[128,7816,7817],{},"Plan",[128,7819,136],{},[128,7821,7822],{},"Límite mensual de minutos",[141,7824,7825,7836,7847],{},[125,7826,7827,7830,7833],{},[146,7828,7829],{},"Free",[146,7831,7832],{},"US$0\u002Fusuario",[146,7834,7835],{},"400 minutos",[125,7837,7838,7841,7844],{},[146,7839,7840],{},"Premium",[146,7842,7843],{},"US$29\u002Fusuario\u002Fmes (26 €)",[146,7845,7846],{},"10.000 minutos",[125,7848,7849,7852,7855],{},[146,7850,7851],{},"Ultimate",[146,7853,7854],{},"US$99\u002Fusuario\u002Fmes (88 €)",[146,7856,7857],{},"50.000 minutos",[12,7859,7860],{},"Para equipo de cinco devs en Premium, son US$145\u002Fmes — 130 €. Ese es solo el ticket de entrada; minutos extra cuestan aparte. Para equipo de 20, US$580\u002Fmes = 520 € solo en suscripción.",[12,7862,7863,7866],{},[27,7864,7865],{},"Self-hosted Community Edition"," es gratuito y elimina ese coste de licencia — pero:",[2735,7868,7869,7872,7875,7878],{},[70,7870,7871],{},"Mínimo realista: 4 vCPU, 8 GB RAM (16 GB si vas a usar registry + pages + scanning).",[70,7873,7874],{},"VPS adecuado: 20 € a 45 €\u002Fmes.",[70,7876,7877],{},"Ops: 2 a 4 horas\u002Fmes en actualización, backup, monitoreo.",[70,7879,7880],{},"Actualizaciones mensuales. GitLab tiene cadencia rígida; quedarse tres versiones atrás abre brechas de seguridad documentadas.",[12,7882,7883],{},"En producción real, self-hosted GitLab da menos trabajo que Kubernetes pero más que Actions SaaS. Es un servidor real que tú operas.",[19,7885,7887],{"id":7886},"drone-ci-y-woodpecker-la-alternativa-minimalista","Drone CI y Woodpecker: la alternativa minimalista",[12,7889,7890],{},"Drone CI nació en 2014 como el \"CI nativo de container\": cada step del pipeline es un container, sin magia. En 2020 la empresa detrás (Drone Inc.) fue adquirida por Harness, y el producto ganó una versión Cloud comercial. El fork comunitario Woodpecker continúa 100% open-source, con API compatible con Drone.",[368,7892,7894],{"id":7893},"lo-que-dronewoodpecker-hacen-bien","Lo que Drone\u002FWoodpecker hacen bien",[2735,7896,7897,7906,7920,7926,7932],{},[70,7898,7899,7902,7903,7905],{},[27,7900,7901],{},"YAML simple."," Cada step declara una imagen y un comando. Sin DSL, sin actions reutilizables con semántica propia. Lo que ejecutas localmente con ",[231,7904,2406],{}," es lo que ejecuta en CI.",[70,7907,7908,7911,7912,7915,7916,7919],{},[27,7909,7910],{},"Container-native."," No hay \"executor\" Java, no hay agente Python ejecutando steps. Cada step es un container aislado. Reproducir el error localmente es literal: copia el ",[231,7913,7914],{},"image:"," y los ",[231,7917,7918],{},"commands:"," del YAML y lo corres en el terminal.",[70,7921,7922,7925],{},[27,7923,7924],{},"Self-hosted desde el día uno."," No hay \"Drone Cloud gratis\" pulling features hacia la versión paga. El servidor + los runners son el producto entero.",[70,7927,7928,7931],{},[27,7929,7930],{},"Plugins vía container."," Cada plugin (deploy SSH, Slack, Docker push, AWS) es una imagen publicada. Versionado igual a cualquier otra dependencia.",[70,7933,7934,7937],{},[27,7935,7936],{},"Soporta múltiples hosts de código."," GitHub, GitLab, Bitbucket, Gitea, Forgejo — todo en el mismo servidor de Drone.",[368,7939,7941],{"id":7940},"donde-dronewoodpecker-cobran","Donde Drone\u002FWoodpecker cobran",[2735,7943,7944,7950,7956,7962],{},[70,7945,7946,7949],{},[27,7947,7948],{},"Comunidad menor."," Cuando golpeas en un bug oscuro, Stack Overflow tiene cinco respuestas, no cincuenta. Github issues son tu fuente principal.",[70,7951,7952,7955],{},[27,7953,7954],{},"Operación no trivial en escala."," Un servidor + un runner es fácil. Cinco runners autoescalando detrás de una cola es tooling que tú montas — auto-scaling no es built-in.",[70,7957,7958,7961],{},[27,7959,7960],{},"Drone Cloud es pago."," Si quieres SaaS, vas a Harness; el tier gratis es limitado. Por eso la recomendación es siempre self-hosted.",[70,7963,7964,7967],{},[27,7965,7966],{},"Documentación modesta."," Cubre el camino feliz; casos de borde los descubres leyendo código.",[368,7969,7971],{"id":7970},"por-que-woodpecker-en-lugar-de-drone-en-2026","Por qué Woodpecker en lugar de Drone en 2026",[12,7973,7974],{},"Drone vanilla aún funciona, pero Harness ha priorizado la versión cloud comercial. Woodpecker es el fork comunitario del Drone original — 100% open-source, sin versión paga jalando features, releases mensuales activas, comunidad comprometida. API y YAML compatibles con Drone, así que la migración es trivial: cambias la URL del servidor.",[12,7976,7977,7978,7981],{},"Para cualquier equipo pequeño auto-hospedando en 2026, ",[27,7979,7980],{},"Woodpecker es la elección mejor que Drone vanilla",". Misma arquitectura, sin el overhead de una empresa controlando el roadmap.",[19,7983,7985],{"id":7984},"cual-es-mas-barata-en-2026","¿Cuál es más barata en 2026?",[12,7987,7988],{},"Coste total mensual real, considerando equipo de cinco devs con volumen medio (300 builds\u002Fmes, builds de 8 minutos medios en Linux):",[119,7990,7991,8007],{},[122,7992,7993],{},[125,7994,7995,7998,8001,8004],{},[128,7996,7997],{},"Opción",[128,7999,8000],{},"Coste fijo",[128,8002,8003],{},"Coste variable",[128,8005,8006],{},"Total estimado\u002Fmes",[141,8008,8009,8024,8037,8051,8065,8079,8093],{},[125,8010,8011,8014,8017,8020],{},[146,8012,8013],{},"Woodpecker self-hosted (VPS 15 €)",[146,8015,8016],{},"15 €",[146,8018,8019],{},"0 €",[146,8021,8022],{},[27,8023,8016],{},[125,8025,8026,8029,8031,8033],{},[146,8027,8028],{},"Actions repos públicos (open-source)",[146,8030,8019],{},[146,8032,8019],{},[146,8034,8035],{},[27,8036,8019],{},[125,8038,8039,8042,8044,8047],{},[146,8040,8041],{},"Actions repos privados (free tier 2000 min)",[146,8043,8019],{},[146,8045,8046],{},"0 € a 10 €",[146,8048,8049],{},[27,8050,8046],{},[125,8052,8053,8056,8058,8061],{},[146,8054,8055],{},"Actions Linux pago (volumen medio)",[146,8057,8019],{},[146,8059,8060],{},"10 € a 30 €",[146,8062,8063],{},[27,8064,8060],{},[125,8066,8067,8070,8073,8075],{},[146,8068,8069],{},"GitLab CI self-hosted (VPS 35 €)",[146,8071,8072],{},"35 €",[146,8074,8019],{},[146,8076,8077],{},[27,8078,8072],{},[125,8080,8081,8084,8086,8089],{},[146,8082,8083],{},"Actions con builds macOS pesados",[146,8085,8019],{},[146,8087,8088],{},"60 € a 280 €",[146,8090,8091],{},[27,8092,8088],{},[125,8094,8095,8098,8101,8104],{},[146,8096,8097],{},"GitLab CI SaaS Premium (5 devs)",[146,8099,8100],{},"130 €",[146,8102,8103],{},"0 € a 35 €",[146,8105,8106],{},[27,8107,8108],{},"130 € a 165 €",[12,8110,8111,8112,8115],{},"Ganador absoluto en coste: ",[27,8113,8114],{},"Woodpecker self-hosted"," para equipo dispuesto a operar una VPS. Cuesta lo mismo que un almuerzo al mes y corre CI para diez proyectos sin sentir.",[12,8117,8118],{},"Si ops no está disponible, Actions plan gratuito es la siguiente opción. Cabe en un equipo pequeño con workflows ligeros; cuando pasa de US$30\u002Fmes variable, vale la pena al menos evaluar runners self-hosted.",[19,8120,8122],{"id":8121},"cual-tiene-mejor-experiencia-de-desarrollador","¿Cuál tiene mejor experiencia de desarrollador?",[12,8124,8125],{},"DX en CI\u002FCD se mide en tres dimensiones: tiempo del \"yml en blanco\" hasta el \"primer build pasando\", capacidad de debug cuando sale mal, y capacidad de evolucionar el workflow cuando crece.",[119,8127,8128,8138],{},[122,8129,8130],{},[125,8131,8132,8135],{},[128,8133,8134],{},"Dimensión",[128,8136,8137],{},"Ganador",[141,8139,8140,8148,8156,8164,8172,8180],{},[125,8141,8142,8145],{},[146,8143,8144],{},"Templates listas \u002F accesibilidad",[146,8146,8147],{},"GitHub Actions (marketplace + onboarding)",[125,8149,8150,8153],{},[146,8151,8152],{},"Workflows complejos \u002F DAG \u002F monorepo",[146,8154,8155],{},"GitLab CI (parent-child + needs nativo)",[125,8157,8158,8161],{},[146,8159,8160],{},"Reproducción local \u002F simplicidad conceptual",[146,8162,8163],{},"Drone\u002FWoodpecker (cada step = container)",[125,8165,8166,8169],{},[146,8167,8168],{},"Debug de fallo intermitente",[146,8170,8171],{},"Drone\u002FWoodpecker (re-correr step aislado es trivial)",[125,8173,8174,8177],{},[146,8175,8176],{},"Composición entre proyectos",[146,8178,8179],{},"GitHub Actions (reusable workflows + composite actions)",[125,8181,8182,8185],{},[146,8183,8184],{},"Time-to-first-pipeline (cero a hello world)",[146,8186,7552],{},[12,8188,8189],{},"No hay ganador absoluto. Para equipo que valora empezar rápido, Actions. Para equipo que tiene workflow complejo desde el día uno (monorepo, varios lenguajes), GitLab CI. Para equipo que quiere entender exactamente lo que está sucediendo, Drone\u002FWoodpecker.",[12,8191,7571],{},[19,8193,8195],{"id":8194},"tabla-comparativa-12-criterios-honestos","Tabla comparativa: 12 criterios honestos",[119,8197,8198,8210],{},[122,8199,8200],{},[125,8201,8202,8204,8206,8208],{},[128,8203,2983],{},[128,8205,7552],{},[128,8207,7558],{},[128,8209,7564],{},[141,8211,8212,8225,8239,8253,8267,8281,8295,8309,8323,8335,8347,8361],{},[125,8213,8214,8217,8220,8223],{},[146,8215,8216],{},"Coste mensual startup ES (5 devs, volumen medio)",[146,8218,8219],{},"0 € a 30 €",[146,8221,8222],{},"15 € a 165 €",[146,8224,8016],{},[125,8226,8227,8230,8233,8236],{},[146,8228,8229],{},"Free tier real (2026)",[146,8231,8232],{},"2000 min\u002Fmes privados, ilimitado público",[146,8234,8235],{},"400 min\u002Fmes SaaS",[146,8237,8238],{},"Ilimitado self-hosted",[125,8240,8241,8244,8247,8250],{},[146,8242,8243],{},"Self-hosted disponible",[146,8245,8246],{},"Sí (runners), SaaS UI",[146,8248,8249],{},"Sí (CE completa)",[146,8251,8252],{},"Sí (es la única forma sensata)",[125,8254,8255,8258,8261,8264],{},[146,8256,8257],{},"Complejidad de workflow grande",[146,8259,8260],{},"Buena (reusable workflows)",[146,8262,8263],{},"Excelente (DAG + parent-child)",[146,8265,8266],{},"Modesta (lineal + matrix)",[125,8268,8269,8272,8275,8278],{},[146,8270,8271],{},"Soporte a monorepo",[146,8273,8274],{},"Medio (paths filter)",[146,8276,8277],{},"Excelente (rules + parent-child)",[146,8279,8280],{},"Medio (when filter)",[125,8282,8283,8286,8289,8292],{},[146,8284,8285],{},"Registry de containers integrado",[146,8287,8288],{},"No (necesita GHCR aparte)",[146,8290,8291],{},"Sí, nativo",[146,8293,8294],{},"No (usa registry externo)",[125,8296,8297,8300,8303,8306],{},[146,8298,8299],{},"Gestión de secretos",[146,8301,8302],{},"Repo + org + environment",[146,8304,8305],{},"Project + group + instance",[146,8307,8308],{},"Server + repo",[125,8310,8311,8314,8317,8320],{},[146,8312,8313],{},"Jobs paralelos out-of-box",[146,8315,8316],{},"Sí (matrix)",[146,8318,8319],{},"Sí (parallel + DAG)",[146,8321,8322],{},"Sí (depends_on)",[125,8324,8325,8328,8331,8333],{},[146,8326,8327],{},"Comunidad ES \u002F material en español",[146,8329,8330],{},"Mediana",[146,8332,8330],{},[146,8334,4920],{},[125,8336,8337,8339,8342,8344],{},[146,8338,4895],{},[146,8340,8341],{},"Parcial (oficial en inglés)",[146,8343,3140],{},[146,8345,8346],{},"Prácticamente cero",[125,8348,8349,8352,8355,8358],{},[146,8350,8351],{},"Integración con GitHub\u002FGitLab\u002FGitea",[146,8353,8354],{},"Solo GitHub",[146,8356,8357],{},"Solo GitLab (mirror externo es workaround)",[146,8359,8360],{},"Los tres + Bitbucket",[125,8362,8363,8366,8369,8372],{},[146,8364,8365],{},"Franja ideal de uso",[146,8367,8368],{},"1 a 50 devs en GitHub",[146,8370,8371],{},"5 a 500 devs en una sola plataforma",[146,8373,8374],{},"1 a 30 devs con ops disponible",[12,8376,8377],{},"Ningún competidor tiene columna sin reservas. La herramienta correcta depende del perfil del equipo.",[19,8379,8381],{"id":8380},"decision-por-perfil-de-equipo","Decisión por perfil de equipo",[12,8383,8384],{},"Cuatro recomendaciones concretas, sin \"depende\".",[368,8386,8388],{"id":8387},"indie-hacker-o-repo-publico-en-github","Indie hacker o repo público en GitHub",[12,8390,8391,8394],{},[27,8392,8393],{},"Usa GitHub Actions plan gratuito."," Repos públicos tienen minutos ilimitados. No tienes motivo para buscar alternativa. Si dentro de un año el proyecto crece, reevalúas.",[368,8396,8398],{"id":8397},"startup-early-en-github-repos-privados-10-mil-a-50-mil-mrr","Startup early en GitHub, repos privados, 10 mil a 50 mil € MRR",[12,8400,8401,8404],{},[27,8402,8403],{},"Continúa en Actions plan gratuito."," El free tier de 2000 minutos cabe en un equipo de dos a tres devs con workflows razonables. Cuando empiece a pasar de eso, primero reduce desperdicio (paths filter para no correr todo en todo PR, cache de dependencias decente) antes de migrar.",[12,8406,8407],{},"Si pasa consistentemente de US$30\u002Fmes variable, considera migrar a runners self-hosted o Woodpecker en paralelo.",[368,8409,8411],{"id":8410},"startup-con-50-mil-a-200-mil-mrr-en-github-volumen-ci-alto","Startup con 50 mil a 200 mil € MRR en GitHub, volumen CI alto",[12,8413,8414,8417],{},[27,8415,8416],{},"Híbrido."," Usa Actions para workflows ligeros (lint, tests unitarios) y self-hosted runners (vía ARC) o Woodpecker para workflows pesados (E2E, builds largos, deploys). Pagas por minuto donde compensa y cero donde duele.",[12,8419,8420],{},"Para equipos con builds macOS regulares, considera una máquina Mac mini dedicada como self-hosted runner. Inversión de 1.000 € paga en tres meses si gastas US$200\u002Fmes en macOS Actions hoy.",[368,8422,8424],{"id":8423},"empresa-es-en-gitlab-self-hosted","Empresa ES en GitLab self-hosted",[12,8426,8427,8430],{},[27,8428,8429],{},"Usa GitLab CI nativo."," Ya estás pagando el coste de operar GitLab; CI viene junto sin coste adicional. Migrar a otra herramienta significaría operar dos sistemas en paralelo — no vale.",[368,8432,8434],{"id":8433},"equipo-pequeno-controlando-coste-agresivamente","Equipo pequeño controlando coste agresivamente",[12,8436,8437,8440],{},[27,8438,8439],{},"Woodpecker self-hosted en VPS 15 €."," Corre CI para diez proyectos sin sudar. Cuesta en ops 1 a 2 horas\u002Fmes. Si el equipo tiene alguien con afinidad por herramientas Unix, es la opción más económica y más previsible en cuenta — sabes exactamente el coste cada mes.",[19,8442,8444],{"id":8443},"donde-heroctl-entra-como-infraestructura-para-runners","Donde HeroCtl entra como infraestructura para runners",[12,8446,8447],{},"Self-hosted CI\u002FCD es exactamente el tipo de carga de trabajo que HeroCtl orquesta bien: servicios largos (servidor de CI, base que mantiene historial de builds), servicios que escalan horizontalmente (runners que suben y bajan con la cola), servicios con necesidad de persistencia (cache de artefactos).",[12,8449,8450],{},"En lugar de operar Docker Compose en un servidor único — single point of failure — describes el setup como una configuración de jobs:",[2735,8452,8453,8459,8465,8471],{},[70,8454,8455,8458],{},[27,8456,8457],{},"Servidor de Drone\u002FWoodpecker como job largo",", con réplica única y volumen persistente para la base de historial.",[70,8460,8461,8464],{},[27,8462,8463],{},"N runners como job replicable",", escalando horizontalmente. El orquestador distribuye los runners entre nodos; si un servidor muere, los runners migran a los otros.",[70,8466,8467,8470],{},[27,8468,8469],{},"Backup integrado"," para el estado del CI (base del servidor + cache de artefactos), sin montar tooling externo.",[70,8472,8473,8476],{},[27,8474,8475],{},"Métricas y logs integrados"," — ves uso de CPU, memoria, tiempo de build sin subir un stack de observabilidad separado.",[12,8478,8479,8480,2630,8483,8486],{},"La diferencia práctica: en lugar de operar un stack de CI en paralelo a tu cluster de producción, se vuelve parte del mismo cluster, con las mismas garantías de alta disponibilidad. Si un servidor se cae, los runners migran. Si quieres duplicar capacidad para una sprint pesada, es cambiar ",[231,8481,8482],{},"replicas: 4",[231,8484,8485],{},"replicas: 8"," en el archivo de configuración.",[12,8488,8489],{},"Para quien está en la frontera \"empiezo simple pero voy a crecer\", eso resuelve la transición sin necesitar cambiar de herramienta a mitad de camino.",[19,8491,8493],{"id":8492},"los-4-errores-caros-en-cicd-self-hosted-y-como-evitarlos","Los 4 errores caros en CI\u002FCD self-hosted (y cómo evitarlos)",[368,8495,8497],{"id":8496},"error-1-cache-stale-silencioso","Error 1: cache stale silencioso",[12,8499,8500],{},"El síntoma: build pasa local, falla en CI por una dependencia que existe en la máquina del dev pero no en la imagen fresca. Peor caso: pasa en CI también porque cache anterior contiene la dependencia, pero falla en producción cuando la imagen es construida sin cache.",[12,8502,8503,8504,571,8507,571,8510,571,8513,8516],{},"La corrección: cache decente asume que puede ser invalidado en cualquier momento. Siempre que cambies archivos de manifiesto de dependencias (",[231,8505,8506],{},"package.json",[231,8508,8509],{},"go.mod",[231,8511,8512],{},"requirements.txt",[231,8514,8515],{},"Cargo.toml","), inclúyelos en la clave de cache. Periódicamente (semanal), forzar build sin cache para detectar drift.",[368,8518,8520],{"id":8519},"error-2-secret-commiteado-por-accidente","Error 2: secret commiteado por accidente",[12,8522,8523],{},"El síntoma: alguien pegó un token en la configuración de CI \"solo para probar\", commiteó, olvidó. El repo es público; en 12 horas el token está en uso por quien no debía.",[12,8525,8526,8527,8530,8531,8534],{},"La corrección: dos mecanismos en capas. ",[27,8528,8529],{},"Pre-commit hook"," que escanea patrones de claves comunes (AWS, Stripe, GitHub PAT). ",[27,8532,8533],{},"Rotación automática"," de tokens críticos (90 días máximo). Si un token se filtra, la ventana de exposición es finita.",[12,8536,8537],{},"En GitLab CI, usa variables con flag \"masked\" y \"protected\". En Actions, usa environment-scoped secrets con approval rules. En Drone\u002FWoodpecker, secretos son escopados por repo y nunca aparecen en logs por defecto.",[368,8539,8541],{"id":8540},"error-3-runner-corriendo-en-el-mismo-servidor-de-produccion","Error 3: runner corriendo en el mismo servidor de producción",[12,8543,8544],{},"El síntoma: build pesado consume CPU\u002FRAM, producción se vuelve lenta, latencia sube, alarma dispara, on-call despierta. Caso real común en equipos pequeños que intentan ahorrar máquina.",[12,8546,8547],{},"La corrección: runners en servidor separado de producción, siempre. Si el presupuesto aprieta, runner en VPS de 5 €\u002Fmes aún es más barato que un incidente de producción en horario comercial.",[368,8549,8551],{"id":8550},"error-4-workflow-que-no-corre-fuera-de-ci","Error 4: workflow que no corre fuera de CI",[12,8553,8554],{},"El síntoma: el build de CI es un script de 200 líneas inline en el YAML, con 15 variables de entorno que el sistema inyecta. Cuando algo sale mal, nadie logra reproducir local sin hacer ingeniería inversa del YAML.",[12,8556,8557,8558,571,8561,8564,8565,8568,8569,8572],{},"La corrección: el CI debe llamar comandos que existen como ",[231,8559,8560],{},"Makefile",[231,8562,8563],{},"script\u002Fbuild",", o ",[231,8566,8567],{},"package.json scripts",". El YAML del CI orquesta; la lógica vive en scripts versionados que corren en cualquier terminal. Si no logras correr ",[231,8570,8571],{},"make ci"," localmente y ver el mismo resultado, tu CI no es portable.",[12,8574,8575],{},"Drone\u002FWoodpecker fuerza esa disciplina por diseño (cada step es un container). Actions y GitLab CI permiten el anti-patrón; cabe al equipo evitar.",[19,8577,4245],{"id":4244},[12,8579,8580],{},[27,8581,8582],{},"¿GitHub Actions es más rápido que Drone?",[12,8584,8585],{},"En build crudo, depende del runner: el pool gestionado de Actions usa máquinas de 2 vCPU; un runner self-hosted en una máquina de 4 vCPU es más rápido. En tiempo total de pipeline (incluyendo cola), Actions gana cuando hay volumen — tienen capacidad ociosa enorme. Self-hosted (cualquier herramienta) tiene cola proporcional al número de runners que provisionas.",[12,8587,8588],{},[27,8589,8590],{},"¿Puedo usar GitLab CI con repo en GitHub?",[12,8592,8593],{},"Técnicamente sí, vía \"pull mirror\" (GitLab espeja el GitHub y corre CI en él). En la práctica es frágil: webhooks atrasan, status checks no vuelven al GitHub de la forma que el equipo espera, MRs quedan confusos. No vale la pena. Si estás en GitHub, usa Actions o Drone\u002FWoodpecker (que aceptan GitHub como fuente nativa).",[12,8595,8596],{},[27,8597,8598],{},"¿Self-hosted runners de GitHub Actions valen la pena?",[12,8600,8601],{},"Para repos privados con volumen alto (más de 5000 minutos\u002Fmes), sí. Ahorras minutos pagados a cambio de operar máquinas. Para repos públicos, no — riesgo de seguridad (forks maliciosos corriendo código en tu máquina) supera el beneficio. ARC (Actions Runner Controller) ayuda en escala, pero añade una capa de Kubernetes; solo tiene sentido para equipos que ya operan K8s.",[12,8603,8604],{},[27,8605,8606],{},"¿Woodpecker es estable lo suficiente en 2026?",[12,8608,8609],{},"Sí. Releases mensuales, base de código sólida (forkado de Drone, que tenía cinco años de producción), comunidad activa. En producción en cientos de empresas pequeñas y medianas. No es la apuesta segura \"nadie es despedido por elegir\" — esa es Actions o GitLab — pero en tres años de fork no hubo incidente comunitario grave. Para equipo pequeño self-hosted, es la elección sensata.",[12,8611,8612],{},[27,8613,8614],{},"¿ArgoCD y FluxCD entran en esa decisión?",[12,8616,8617],{},"No directamente. ArgoCD\u002FFluxCD son herramientas de GitOps para Kubernetes, no CI. Asisten un repo Git y aplican cambios en cluster. CI sigue siendo Actions\u002FGitLab\u002FDrone generando imágenes; ArgoCD\u002FFlux aplican el deploy. Si no estás en Kubernetes, ArgoCD\u002FFlux no son para ti. Equipos en otros orquestadores hacen deploy directo desde el CI o vía APIs del orquestador.",[12,8619,8620],{},[27,8621,8622],{},"¿Cuántos runners simultáneos para equipo de 5 devs?",[12,8624,8625],{},"Regla práctica: un runner por dos desarrolladores activos, más un runner extra para builds largos no bloquear PRs rápidos. Equipo de cinco devs: tres runners es cómodo. En horas pico (release day), sube a cinco temporalmente. Cada runner consume 1 a 2 GB de RAM en workload típica; un servidor de 8 GB corre cuatro runners sin dolor.",[12,8627,8628],{},[27,8629,8630],{},"Cache de dependencias — ¿qué herramienta lidia mejor?",[12,8632,8633,8634,8637],{},"GitLab CI tiene cache nativo por clave\u002Fpath, integrado al registry propio. GitHub Actions tiene ",[231,8635,8636],{},"actions\u002Fcache"," (gratuito, 10 GB por repo). Drone\u002FWoodpecker dependen de plugin de cache externo (S3, MinIO local) — más setup pero más flexible. En volumen moderado, todos resuelven; en volumen alto (monorepo grande), GitLab tiene ventaja por integración con el registry.",[12,8639,8640],{},[27,8641,8642],{},"Migrar de GitHub Actions a Drone — ¿cuánto trabajo?",[12,8644,8645],{},"Para workflows simples (build + test + push), 1 a 2 días. Para workflows que dependen de muchas acciones del marketplace, 1 a 2 semanas (necesita reescribir cada acción como container). El mayor dolor son secretos y entornos — exporta y reimporta con cuidado. Recomendación: haz migración proyecto a proyecto, no todo de una vez.",[12,8647,8648],{},[27,8649,8650],{},"¿Puedo correr runners de Actions y Drone\u002FWoodpecker en el mismo servidor?",[12,8652,8653],{},"Técnicamente sí, ambos son containers. En la práctica, aislamiento mejora: runners en servidores separados evitan que un build pesado afecte al otro. Si el presupuesto es ajustado, dos servidores de 7 €\u002Fmes son mejores que uno de 15 €\u002Fmes con todo junto.",[12,8655,7571],{},[19,8657,8659],{"id":8658},"en-resumen","En resumen",[12,8661,8662],{},"CI\u002FCD en 2026 no tiene herramienta ganadora. Tiene perfiles de uso y tradeoffs honestos:",[2735,8664,8665,8671,8677,8683,8689],{},[70,8666,8667,8670],{},[27,8668,8669],{},"¿Estás en GitHub y el volumen es ligero a medio?"," Actions, plan gratuito. No busques problema donde no hay.",[70,8672,8673,8676],{},[27,8674,8675],{},"¿Estás en GitLab self-hosted?"," GitLab CI nativo. Ya está pagado.",[70,8678,8679,8682],{},[27,8680,8681],{},"¿Quieres coste previsible y tienes 1-2h\u002Fmes de ops disponible?"," Woodpecker self-hosted en VPS 15 €. La elección más económica.",[70,8684,8685,8688],{},[27,8686,8687],{},"¿Tienes monorepo grande con workflow complejo?"," GitLab CI (DAG nativo) o Actions con reusable workflows.",[70,8690,8691,8694],{},[27,8692,8693],{},"¿Tienes volumen alto y dolor de pricing de minutos?"," Híbrido: Actions para workflows ligeros, runners self-hosted para pesados.",[12,8696,8697],{},"Si estás pensando en correr la herramienta de CI como parte del mismo cluster que sirve producción — con alta disponibilidad real, métricas integradas y backup sin montar stack aparte — instala HeroCtl en un servidor:",[224,8699,8701],{"className":8700,"code":2949,"language":2530},[2528],[231,8702,2949],{"__ignoreMap":229},[12,8704,8705],{},"A partir de ahí, describir un servidor de Woodpecker con tres runners autoescalables es un archivo de configuración de cincuenta líneas. El cluster cuida del resto: distribuye los runners por los nodos, mantiene el servidor disponible incluso con pérdida de máquina, hace backup del estado, expone métricas en el panel embebido.",[12,8707,8708,8709,8711,8712,8716],{},"Para quien quiere más contexto, vale la pena leer también ",[3337,8710,3345],{"href":3344}," — discute cuándo tiene sentido salir de docker-compose para un plano de control replicado, con los mismos criterios honestos de este post. Y para equipos pensando en simplificar la stack de orquestación entera, ",[3337,8713,8715],{"href":8714},"\u002Fes\u002Fblog\u002Fmigrar-de-kubernetes-a-stack-mas-simple","Migrar de Kubernetes a una stack más simple — case real"," tiene números de una migración real, con ganancias y dolores.",[12,8718,8719,8720,8723],{},"La elección de CI\u002FCD es una de las decisiones más duraderas del equipo. Vale algunos días de comparación honesta antes de copiar el ",[231,8721,8722],{},".github\u002Fworkflows\u002F"," del proyecto anterior — porque tres años después, migrar cuesta caro.",{"title":229,"searchDepth":244,"depth":244,"links":8725},[8726,8727,8728,8733,8737,8742,8743,8744,8745,8752,8753,8759,8760],{"id":7531,"depth":244,"text":7532},{"id":7574,"depth":244,"text":7575},{"id":7611,"depth":244,"text":7612,"children":8729},[8730,8731,8732],{"id":7622,"depth":271,"text":7623},{"id":7658,"depth":271,"text":7659},{"id":7719,"depth":271,"text":7720},{"id":7752,"depth":244,"text":7753,"children":8734},[8735,8736],{"id":7759,"depth":271,"text":7760},{"id":7799,"depth":271,"text":7800},{"id":7886,"depth":244,"text":7887,"children":8738},[8739,8740,8741],{"id":7893,"depth":271,"text":7894},{"id":7940,"depth":271,"text":7941},{"id":7970,"depth":271,"text":7971},{"id":7984,"depth":244,"text":7985},{"id":8121,"depth":244,"text":8122},{"id":8194,"depth":244,"text":8195},{"id":8380,"depth":244,"text":8381,"children":8746},[8747,8748,8749,8750,8751],{"id":8387,"depth":271,"text":8388},{"id":8397,"depth":271,"text":8398},{"id":8410,"depth":271,"text":8411},{"id":8423,"depth":271,"text":8424},{"id":8433,"depth":271,"text":8434},{"id":8443,"depth":244,"text":8444},{"id":8492,"depth":244,"text":8493,"children":8754},[8755,8756,8757,8758],{"id":8496,"depth":271,"text":8497},{"id":8519,"depth":271,"text":8520},{"id":8540,"depth":271,"text":8541},{"id":8550,"depth":271,"text":8551},{"id":4244,"depth":244,"text":4245},{"id":8658,"depth":244,"text":8659},"comparison","2026-05-15","GitHub Actions ganó mindshare pero tiene costes de minutos. GitLab CI es más completo pero pesa más. Drone (y Woodpecker) auto-hospedado corre en VPS pequeño. Comparación práctica.",{},"\u002Fes\u002Fblog\u002Fgithub-actions-vs-gitlab-ci-vs-drone","14 min",{"title":7516,"description":8763},{"loc":8765},"es\u002Fblog\u002Fgithub-actions-vs-gitlab-ci-vs-drone",[8771,8772,8773,8774,8775],"github-actions","gitlab-ci","drone","ci-cd","comparativo","SA7FLRIt6kzCrSWq_4TfgiVd00Hhv5nBRA60Zs17xcA",{"id":8778,"title":8779,"author":7,"body":8780,"category":3379,"cover":3380,"date":11777,"description":11778,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":11779,"navigation":411,"path":11780,"readingTime":6387,"seo":11781,"sitemap":11782,"stem":11783,"tags":11784,"__hash__":11789},"blog_es\u002Fes\u002Fblog\u002Fstack-monitoring-prometheus-grafana-loki.md","Stack de monitoring completa en 2026: Prometheus + Grafana + Loki paso a paso",{"type":9,"value":8781,"toc":11757},[8782,8795,8798,8800,8807,8818,8821,8824,8828,8831,8869,8884,8888,8891,8924,8927,8931,8937,8940,8943,8970,8984,8988,8993,9000,9006,9013,9361,9380,9383,9421,9444,9448,9453,9459,9739,9749,9768,9772,9778,9781,9860,9880,9886,9924,9934,9938,9942,9948,10202,10205,10208,10395,10405,10412,10416,10421,10430,10436,10545,10552,10559,10579,10586,10590,10594,10597,10607,10945,10952,11170,11181,11195,11199,11203,11209,11232,11239,11243,11248,11251,11254,11287,11290,11322,11331,11342,11346,11349,11352,11378,11381,11385,11435,11438,11441,11445,11576,11579,11583,11586,11596,11606,11618,11624,11626,11632,11638,11644,11650,11659,11673,11679,11685,11689,11692,11720,11732,11735,11751,11754],[12,8783,8784,8785,571,8788,571,8791,8794],{},"La primera vez que tu sitio caiga a las tres de la mañana, vas a descubrir una cosa incómoda: no tienes cómo saber qué pasó. No hay gráfico de CPU, no hay log del contenedor que murió, no hay alerta que avisó antes. Vas a abrir una terminal, conectar a los servidores uno por uno, correr ",[231,8786,8787],{},"top",[231,8789,8790],{},"df",[231,8792,8793],{},"journalctl",", e intentar reconstituir una escena de crimen que ya se enfrió.",[12,8796,8797],{},"Este post es el atajo para que no pases por eso. En cuatro horas, con R$80 a R$120 al mes de hardware, se puede montar la stack de observabilidad open-source que sustituye Datadog, New Relic y CloudWatch en 95% de los casos para startup. Las herramientas son las mismas que corren dentro de empresas con decenas de miles de servidores — y caben confortablemente en una VPS pequeña para el equipo que está empezando.",[19,8799,22],{"id":21},[12,8801,8802,8803,8806],{},"La stack de monitoring open-source estándar en 2026 — ",[27,8804,8805],{},"Prometheus + Grafana + Loki + Alertmanager"," — cabe en una única VPS de 4 GB de RAM y cubre métricas, logs centralizados, dashboards y alertas. Este tutorial muestra setup paso a paso para un cluster de 4 a 5 servidores en aproximadamente cuatro horas, usando docker-compose o job specs del orquestador.",[12,8808,8809,8810,8813,8814,8817],{},"Para startup brasileña, eso significa ",[27,8811,8812],{},"R$80 a R$120 al mes de hardware"," contra ",[27,8815,8816],{},"R$1.000 a R$2.000 al mes"," de SaaS de observabilidad equivalente. El costo de tiempo es honesto: cuatro horas de setup inicial más dos a cuatro horas al mes de mantenimiento continuo.",[12,8819,8820],{},"Resultado entregable al final del tutorial: dashboards de CPU, RAM, disco, red y métricas HTTP; logs buscables con retención de 30 días; alertas ruteadas a Slack, Discord o e-mail. Prerrequisitos: 1 VPS Linux con 4 GB de RAM y 50 GB de SSD, Docker instalado, y un dominio con DNS controlado por ti.",[12,8822,8823],{},"La elección entre correr esta stack en una VPS dedicada fuera del cluster de producción o como job dentro del propio orquestador es una decisión arquitectural — cubrimos las dos opciones en el paso 8 y en \"Cómo correr esto dentro de HeroCtl\".",[19,8825,8827],{"id":8826},"que-hace-cada-componente-en-una-frase","Qué hace cada componente, en una frase",[12,8829,8830],{},"Antes de instalar cualquier cosa, vale la pena entender el papel de cada pieza. La stack tiene seis componentes; la confusión generalmente viene de pensar que alguno de ellos es \"el sistema de monitoring\". No lo es. Cada uno hace una cosa.",[2735,8832,8833,8839,8845,8851,8857,8863],{},[70,8834,8835,8838],{},[27,8836,8837],{},"Prometheus"," es una base de datos de series temporales (TSDB) que recolecta métricas vía HTTP scrape — él jala los números, nadie los empuja. Retiene 15 días por default.",[70,8840,8841,8844],{},[27,8842,8843],{},"Grafana"," es la capa de visualización. Conecta a Prometheus, a Loki, a Postgres, a casi cualquier fuente estructurada, y dibuja gráficos.",[70,8846,8847,8850],{},[27,8848,8849],{},"Loki"," es la pieza de logs. Sintaxis similar a la de Prometheus, indexa solo labels (no el contenido de los logs), y por eso queda cerca de diez veces más barato que ELK para correr.",[70,8852,8853,8856],{},[27,8854,8855],{},"Promtail"," (o el Grafana Agent, que está sustituyendo al Promtail en 2026) es el recolector que lee los archivos de log de cada servidor y envía a Loki.",[70,8858,8859,8862],{},[27,8860,8861],{},"node_exporter"," corre en cada nodo monitoreado y expone un endpoint HTTP con CPU, RAM, disco y red en formato Prometheus.",[70,8864,8865,8868],{},[27,8866,8867],{},"Alertmanager"," recibe reglas de alerta de Prometheus y cuida del ruteo — Slack, e-mail, PagerDuty, webhook arbitrario.",[12,8870,8871,8872,571,8875,571,8878,571,8881,101],{},"Quien diseña la primera stack suele confundir Prometheus con \"monitoring\" y Grafana con \"dashboards bonitos\". La separación real es: ",[27,8873,8874],{},"Prometheus guarda números",[27,8876,8877],{},"Loki guarda texto",[27,8879,8880],{},"Grafana muestra ambos",[27,8882,8883],{},"Alertmanager grita cuando algún número queda mal",[19,8885,8887],{"id":8886},"cual-es-la-arquitectura-recomendada","¿Cuál es la arquitectura recomendada?",[12,8889,8890],{},"Para un cluster de 3 a 5 servidores corriendo aplicaciones de producción, la topología que viene funcionando en la práctica es separar el servidor de observabilidad del resto. Un nodo dedicado, fuera del cluster que él monitorea, con dos objetivos: no morir junto cuando el cluster muera, y no competir por CPU\u002FRAM con la aplicación real.",[2735,8892,8893,8899,8905,8915],{},[70,8894,8895,8898],{},[27,8896,8897],{},"1 servidor \"observability\" dedicado",", 4 GB de RAM, 50 GB de SSD. Corre Prometheus, Grafana, Loki, Alertmanager.",[70,8900,8901,8904],{},[27,8902,8903],{},"Cada servidor monitoreado"," corre solo dos procesos livianos: node_exporter (métricas de sistema) y Promtail (envío de logs).",[70,8906,8907,8910,8911,8914],{},[27,8908,8909],{},"Tus aplicaciones"," exponen un endpoint ",[231,8912,8913],{},"\u002Fmetrics"," en formato Prometheus. Si usas un framework popular, existe un cliente listo. Si no, es una biblioteca de pocas decenas de líneas.",[70,8916,8917,8919,8920,8923],{},[27,8918,8843],{}," queda accesible vía subdominio (",[231,8921,8922],{},"monitor.tudominio.com",") con TLS automático y autenticación básica al frente.",[12,8925,8926],{},"Esa separación tiene un costo: pagas por una VPS más. A cambio, cuando el cluster principal caiga, todavía logras mirar los gráficos para entender qué pasó. Para startup, ese trade-off compensa casi siempre — el peor escenario en monitoring es descubrir que la única cosa que paró junto con el sitio fue el sistema que iba a avisarte que el sitio paró.",[19,8928,8930],{"id":8929},"paso-1-como-provisionar-la-vps-de-observabilidad","Paso 1 — ¿Cómo provisionar la VPS de observabilidad?",[12,8932,8933,8934,101],{},"Tiempo estimado: ",[27,8935,8936],{},"10 minutos",[12,8938,8939],{},"Cualquier proveedor barato sirve. Los dos con mejor costo-beneficio para el caso brasileño hoy son Hetzner (CPX21 a 7,99 EUR al mes con 3 vCPUs y 4 GB de RAM, datacenter en Alemania) y DigitalOcean (Basic Droplet de US$24 al mes con la misma configuración, datacenters más cercanos a Brasil). Para workload de monitoring, latencia de scrape en datacenter europeo no causa problema — Prometheus jala cada 15 segundos por default, entonces 200ms de RTT entre Hetzner y tus servidores no estorba.",[12,8941,8942],{},"Provisionando:",[67,8944,8945,8948,8951,8957,8964],{},[70,8946,8947],{},"Crea la VPS con Ubuntu 24.04 LTS o Debian 12.",[70,8949,8950],{},"Agrega tu clave SSH pública en la creación. Deshabilita login por contraseña.",[70,8952,8953,8954,101],{},"Instala Docker y el plugin de compose: ",[231,8955,8956],{},"curl -fsSL https:\u002F\u002Fget.docker.com | sh && apt install docker-compose-plugin",[70,8958,8959,8960,8963],{},"Configura el firewall: puerto 22 (SSH) abierto, puerto 443 (HTTPS) abierto, todos los demás cerrados. Los puertos internos (3000, 9090, 3100, 9093) solo quedan accesibles por el ",[231,8961,8962],{},"localhost"," de la propia VPS — el reverse proxy expone Grafana vía 443.",[70,8965,8966,8967,8969],{},"Apunta el DNS: crea un registro A ",[231,8968,8922],{}," para la IP de la VPS.",[12,8971,341,8972,8975,8976,8979,8980,8983],{},[231,8973,8974],{},"docker --version"," retorna 26.x o superior; ",[231,8977,8978],{},"dig monitor.tudominio.com"," retorna la IP correcta; ",[231,8981,8982],{},"ssh root@monitor.tudominio.com"," conecta sin pedir contraseña.",[19,8985,8987],{"id":8986},"paso-2-como-subir-la-stack-via-docker-compose","Paso 2 — ¿Cómo subir la stack vía docker-compose?",[12,8989,8933,8990,101],{},[27,8991,8992],{},"45 minutos",[12,8994,8995,8996,8999],{},"Crea el directorio de trabajo en ",[231,8997,8998],{},"\u002Fopt\u002Fobservability\u002F"," con la siguiente estructura:",[224,9001,9004],{"className":9002,"code":9003,"language":2530},[2528],"\u002Fopt\u002Fobservability\u002F\n├── docker-compose.yml\n├── prometheus\u002F\n│   ├── prometheus.yml\n│   └── alerts.yml\n├── alertmanager\u002F\n│   └── alertmanager.yml\n├── loki\u002F\n│   └── loki-config.yml\n└── grafana\u002F\n    └── provisioning\u002F\n        └── datasources\u002F\n            └── datasources.yml\n",[231,9005,9003],{"__ignoreMap":229},[12,9007,9008,9009,9012],{},"El ",[231,9010,9011],{},"docker-compose.yml"," abreviado pero funcional:",[224,9014,9018],{"className":9015,"code":9016,"language":9017,"meta":229,"style":229},"language-yaml shiki shiki-themes github-dark-default","services:\n  prometheus:\n    image: prom\u002Fprometheus:v2.55.0\n    volumes:\n      - .\u002Fprometheus:\u002Fetc\u002Fprometheus\n      - prometheus-data:\u002Fprometheus\n    command:\n      - '--config.file=\u002Fetc\u002Fprometheus\u002Fprometheus.yml'\n      - '--storage.tsdb.retention.time=30d'\n      - '--web.enable-lifecycle'  # permite reload via HTTP POST\n    ports:\n      - '127.0.0.1:9090:9090'\n    restart: unless-stopped\n\n  grafana:\n    image: grafana\u002Fgrafana:11.3.0\n    volumes:\n      - grafana-data:\u002Fvar\u002Flib\u002Fgrafana\n      - .\u002Fgrafana\u002Fprovisioning:\u002Fetc\u002Fgrafana\u002Fprovisioning\n    environment:\n      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}\n      - GF_USERS_ALLOW_SIGN_UP=false\n    ports:\n      - '127.0.0.1:3000:3000'\n    restart: unless-stopped\n\n  loki:\n    image: grafana\u002Floki:3.2.0\n    volumes:\n      - .\u002Floki\u002Floki-config.yml:\u002Fetc\u002Floki\u002Fconfig.yml\n      - loki-data:\u002Floki\n    command: -config.file=\u002Fetc\u002Floki\u002Fconfig.yml\n    ports:\n      - '127.0.0.1:3100:3100'\n    restart: unless-stopped\n\n  alertmanager:\n    image: prom\u002Falertmanager:v0.27.0\n    volumes:\n      - .\u002Falertmanager:\u002Fetc\u002Falertmanager\n    ports:\n      - '127.0.0.1:9093:9093'\n    restart: unless-stopped\n\nvolumes:\n  prometheus-data:\n  grafana-data:\n  loki-data:\n","yaml",[231,9019,9020,9029,9036,9046,9053,9061,9068,9075,9082,9089,9099,9106,9113,9123,9127,9134,9143,9149,9156,9163,9170,9177,9184,9190,9197,9205,9209,9216,9225,9231,9238,9245,9254,9260,9267,9275,9279,9286,9295,9301,9308,9314,9321,9329,9333,9340,9347,9354],{"__ignoreMap":229},[234,9021,9022,9026],{"class":236,"line":237},[234,9023,9025],{"class":9024},"sPWt5","services",[234,9027,9028],{"class":387},":\n",[234,9030,9031,9034],{"class":236,"line":244},[234,9032,9033],{"class":9024},"  prometheus",[234,9035,9028],{"class":387},[234,9037,9038,9041,9043],{"class":236,"line":271},[234,9039,9040],{"class":9024},"    image",[234,9042,6562],{"class":387},[234,9044,9045],{"class":255},"prom\u002Fprometheus:v2.55.0\n",[234,9047,9048,9051],{"class":236,"line":415},[234,9049,9050],{"class":9024},"    volumes",[234,9052,9028],{"class":387},[234,9054,9055,9058],{"class":236,"line":434},[234,9056,9057],{"class":387},"      - ",[234,9059,9060],{"class":255},".\u002Fprometheus:\u002Fetc\u002Fprometheus\n",[234,9062,9063,9065],{"class":236,"line":459},[234,9064,9057],{"class":387},[234,9066,9067],{"class":255},"prometheus-data:\u002Fprometheus\n",[234,9069,9070,9073],{"class":236,"line":464},[234,9071,9072],{"class":9024},"    command",[234,9074,9028],{"class":387},[234,9076,9077,9079],{"class":236,"line":479},[234,9078,9057],{"class":387},[234,9080,9081],{"class":255},"'--config.file=\u002Fetc\u002Fprometheus\u002Fprometheus.yml'\n",[234,9083,9084,9086],{"class":236,"line":484},[234,9085,9057],{"class":387},[234,9087,9088],{"class":255},"'--storage.tsdb.retention.time=30d'\n",[234,9090,9091,9093,9096],{"class":236,"line":490},[234,9092,9057],{"class":387},[234,9094,9095],{"class":255},"'--web.enable-lifecycle'",[234,9097,9098],{"class":240},"  # permite reload via HTTP POST\n",[234,9100,9101,9104],{"class":236,"line":508},[234,9102,9103],{"class":9024},"    ports",[234,9105,9028],{"class":387},[234,9107,9108,9110],{"class":236,"line":529},[234,9109,9057],{"class":387},[234,9111,9112],{"class":255},"'127.0.0.1:9090:9090'\n",[234,9114,9115,9118,9120],{"class":236,"line":535},[234,9116,9117],{"class":9024},"    restart",[234,9119,6562],{"class":387},[234,9121,9122],{"class":255},"unless-stopped\n",[234,9124,9125],{"class":236,"line":546},[234,9126,412],{"emptyLinePlaceholder":411},[234,9128,9129,9132],{"class":236,"line":552},[234,9130,9131],{"class":9024},"  grafana",[234,9133,9028],{"class":387},[234,9135,9136,9138,9140],{"class":236,"line":557},[234,9137,9040],{"class":9024},[234,9139,6562],{"class":387},[234,9141,9142],{"class":255},"grafana\u002Fgrafana:11.3.0\n",[234,9144,9145,9147],{"class":236,"line":594},[234,9146,9050],{"class":9024},[234,9148,9028],{"class":387},[234,9150,9151,9153],{"class":236,"line":635},[234,9152,9057],{"class":387},[234,9154,9155],{"class":255},"grafana-data:\u002Fvar\u002Flib\u002Fgrafana\n",[234,9157,9158,9160],{"class":236,"line":643},[234,9159,9057],{"class":387},[234,9161,9162],{"class":255},".\u002Fgrafana\u002Fprovisioning:\u002Fetc\u002Fgrafana\u002Fprovisioning\n",[234,9164,9165,9168],{"class":236,"line":659},[234,9166,9167],{"class":9024},"    environment",[234,9169,9028],{"class":387},[234,9171,9172,9174],{"class":236,"line":683},[234,9173,9057],{"class":387},[234,9175,9176],{"class":255},"GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}\n",[234,9178,9179,9181],{"class":236,"line":695},[234,9180,9057],{"class":387},[234,9182,9183],{"class":255},"GF_USERS_ALLOW_SIGN_UP=false\n",[234,9185,9186,9188],{"class":236,"line":717},[234,9187,9103],{"class":9024},[234,9189,9028],{"class":387},[234,9191,9192,9194],{"class":236,"line":723},[234,9193,9057],{"class":387},[234,9195,9196],{"class":255},"'127.0.0.1:3000:3000'\n",[234,9198,9199,9201,9203],{"class":236,"line":729},[234,9200,9117],{"class":9024},[234,9202,6562],{"class":387},[234,9204,9122],{"class":255},[234,9206,9207],{"class":236,"line":734},[234,9208,412],{"emptyLinePlaceholder":411},[234,9210,9211,9214],{"class":236,"line":771},[234,9212,9213],{"class":9024},"  loki",[234,9215,9028],{"class":387},[234,9217,9218,9220,9222],{"class":236,"line":776},[234,9219,9040],{"class":9024},[234,9221,6562],{"class":387},[234,9223,9224],{"class":255},"grafana\u002Floki:3.2.0\n",[234,9226,9227,9229],{"class":236,"line":815},[234,9228,9050],{"class":9024},[234,9230,9028],{"class":387},[234,9232,9233,9235],{"class":236,"line":820},[234,9234,9057],{"class":387},[234,9236,9237],{"class":255},".\u002Floki\u002Floki-config.yml:\u002Fetc\u002Floki\u002Fconfig.yml\n",[234,9239,9240,9242],{"class":236,"line":826},[234,9241,9057],{"class":387},[234,9243,9244],{"class":255},"loki-data:\u002Floki\n",[234,9246,9247,9249,9251],{"class":236,"line":846},[234,9248,9072],{"class":9024},[234,9250,6562],{"class":387},[234,9252,9253],{"class":255},"-config.file=\u002Fetc\u002Floki\u002Fconfig.yml\n",[234,9255,9256,9258],{"class":236,"line":859},[234,9257,9103],{"class":9024},[234,9259,9028],{"class":387},[234,9261,9262,9264],{"class":236,"line":872},[234,9263,9057],{"class":387},[234,9265,9266],{"class":255},"'127.0.0.1:3100:3100'\n",[234,9268,9269,9271,9273],{"class":236,"line":898},[234,9270,9117],{"class":9024},[234,9272,6562],{"class":387},[234,9274,9122],{"class":255},[234,9276,9277],{"class":236,"line":913},[234,9278,412],{"emptyLinePlaceholder":411},[234,9280,9281,9284],{"class":236,"line":1886},[234,9282,9283],{"class":9024},"  alertmanager",[234,9285,9028],{"class":387},[234,9287,9288,9290,9292],{"class":236,"line":1901},[234,9289,9040],{"class":9024},[234,9291,6562],{"class":387},[234,9293,9294],{"class":255},"prom\u002Falertmanager:v0.27.0\n",[234,9296,9297,9299],{"class":236,"line":1920},[234,9298,9050],{"class":9024},[234,9300,9028],{"class":387},[234,9302,9303,9305],{"class":236,"line":1944},[234,9304,9057],{"class":387},[234,9306,9307],{"class":255},".\u002Falertmanager:\u002Fetc\u002Falertmanager\n",[234,9309,9310,9312],{"class":236,"line":1962},[234,9311,9103],{"class":9024},[234,9313,9028],{"class":387},[234,9315,9316,9318],{"class":236,"line":1978},[234,9317,9057],{"class":387},[234,9319,9320],{"class":255},"'127.0.0.1:9093:9093'\n",[234,9322,9323,9325,9327],{"class":236,"line":1984},[234,9324,9117],{"class":9024},[234,9326,6562],{"class":387},[234,9328,9122],{"class":255},[234,9330,9331],{"class":236,"line":1992},[234,9332,412],{"emptyLinePlaceholder":411},[234,9334,9335,9338],{"class":236,"line":2004},[234,9336,9337],{"class":9024},"volumes",[234,9339,9028],{"class":387},[234,9341,9342,9345],{"class":236,"line":2014},[234,9343,9344],{"class":9024},"  prometheus-data",[234,9346,9028],{"class":387},[234,9348,9349,9352],{"class":236,"line":2020},[234,9350,9351],{"class":9024},"  grafana-data",[234,9353,9028],{"class":387},[234,9355,9356,9359],{"class":236,"line":2029},[234,9357,9358],{"class":9024},"  loki-data",[234,9360,9028],{"class":387},[12,9362,9363,9364,9367,9368,9371,9372,9375,9376,9379],{},"Tres puntos importantes en ese archivo. Primero, todos los puertos están atados a ",[231,9365,9366],{},"127.0.0.1"," — ninguno de los servicios es accesible directamente de internet. Segundo, los volúmenes son nombrados (no bind mounts), así que sobreviven a ",[231,9369,9370],{},"docker-compose down",". Tercero, la contraseña de Grafana viene de variable de ambiente: crea un ",[231,9373,9374],{},".env"," al lado del compose con ",[231,9377,9378],{},"GRAFANA_PASSWORD=algo_largo_aleatorio"," y nunca commitees eso.",[12,9381,9382],{},"Sube la stack:",[224,9384,9386],{"className":226,"code":9385,"language":228,"meta":229,"style":229},"cd \u002Fopt\u002Fobservability\ndocker compose up -d\ndocker compose ps  # todos deben estar \"Up\" \u002F healthy\n",[231,9387,9388,9396,9409],{"__ignoreMap":229},[234,9389,9390,9393],{"class":236,"line":237},[234,9391,9392],{"class":251},"cd",[234,9394,9395],{"class":255}," \u002Fopt\u002Fobservability\n",[234,9397,9398,9400,9403,9406],{"class":236,"line":244},[234,9399,1118],{"class":247},[234,9401,9402],{"class":255}," compose",[234,9404,9405],{"class":255}," up",[234,9407,9408],{"class":251}," -d\n",[234,9410,9411,9413,9415,9418],{"class":236,"line":271},[234,9412,1118],{"class":247},[234,9414,9402],{"class":255},[234,9416,9417],{"class":255}," ps",[234,9419,9420],{"class":240},"  # todos deben estar \"Up\" \u002F healthy\n",[12,9422,9423,9424,9427,9428,1895,9431,9427,9434,1895,9437,9440,9441,101],{},"Validación rápida: ",[231,9425,9426],{},"curl localhost:9090\u002F-\u002Fready"," retorna ",[231,9429,9430],{},"Prometheus Server is Ready",[231,9432,9433],{},"curl localhost:3100\u002Fready",[231,9435,9436],{},"ready",[231,9438,9439],{},"curl localhost:3000\u002Fapi\u002Fhealth"," retorna JSON con ",[231,9442,9443],{},"\"database\": \"ok\"",[19,9445,9447],{"id":9446},"paso-3-como-configurar-los-scrapes-de-prometheus","Paso 3 — ¿Cómo configurar los scrapes de Prometheus?",[12,9449,8933,9450,101],{},[27,9451,9452],{},"30 minutos",[12,9454,9008,9455,9458],{},[231,9456,9457],{},"prometheus\u002Fprometheus.yml"," es donde dices a Prometheus qué endpoints raspar. Para un cluster de 4 servidores, queda así:",[224,9460,9462],{"className":9015,"code":9461,"language":9017,"meta":229,"style":229},"global:\n  scrape_interval: 15s\n  evaluation_interval: 15s\n\nalerting:\n  alertmanagers:\n    - static_configs:\n        - targets: ['alertmanager:9093']\n\nrule_files:\n  - 'alerts.yml'\n\nscrape_configs:\n  - job_name: 'prometheus'\n    static_configs:\n      - targets: ['localhost:9090']\n\n  - job_name: 'node'\n    static_configs:\n      - targets:\n          - 'server-1.tudominio.internal:9100'\n          - 'server-2.tudominio.internal:9100'\n          - 'server-3.tudominio.internal:9100'\n          - 'worker-1.tudominio.internal:9100'\n        labels:\n          environment: 'production'\n\n  - job_name: 'apps'\n    static_configs:\n      - targets:\n          - 'api.tudominio.internal:8080'\n          - 'worker.tudominio.internal:8080'\n        labels:\n          environment: 'production'\n    metrics_path: '\u002Fmetrics'\n",[231,9463,9464,9471,9481,9490,9494,9501,9508,9518,9535,9539,9546,9554,9558,9565,9577,9584,9597,9601,9612,9618,9626,9634,9641,9648,9655,9662,9672,9676,9687,9693,9701,9708,9715,9721,9729],{"__ignoreMap":229},[234,9465,9466,9469],{"class":236,"line":237},[234,9467,9468],{"class":9024},"global",[234,9470,9028],{"class":387},[234,9472,9473,9476,9478],{"class":236,"line":244},[234,9474,9475],{"class":9024},"  scrape_interval",[234,9477,6562],{"class":387},[234,9479,9480],{"class":255},"15s\n",[234,9482,9483,9486,9488],{"class":236,"line":271},[234,9484,9485],{"class":9024},"  evaluation_interval",[234,9487,6562],{"class":387},[234,9489,9480],{"class":255},[234,9491,9492],{"class":236,"line":415},[234,9493,412],{"emptyLinePlaceholder":411},[234,9495,9496,9499],{"class":236,"line":434},[234,9497,9498],{"class":9024},"alerting",[234,9500,9028],{"class":387},[234,9502,9503,9506],{"class":236,"line":459},[234,9504,9505],{"class":9024},"  alertmanagers",[234,9507,9028],{"class":387},[234,9509,9510,9513,9516],{"class":236,"line":464},[234,9511,9512],{"class":387},"    - ",[234,9514,9515],{"class":9024},"static_configs",[234,9517,9028],{"class":387},[234,9519,9520,9523,9526,9529,9532],{"class":236,"line":479},[234,9521,9522],{"class":387},"        - ",[234,9524,9525],{"class":9024},"targets",[234,9527,9528],{"class":387},": [",[234,9530,9531],{"class":255},"'alertmanager:9093'",[234,9533,9534],{"class":387},"]\n",[234,9536,9537],{"class":236,"line":484},[234,9538,412],{"emptyLinePlaceholder":411},[234,9540,9541,9544],{"class":236,"line":490},[234,9542,9543],{"class":9024},"rule_files",[234,9545,9028],{"class":387},[234,9547,9548,9551],{"class":236,"line":508},[234,9549,9550],{"class":387},"  - ",[234,9552,9553],{"class":255},"'alerts.yml'\n",[234,9555,9556],{"class":236,"line":529},[234,9557,412],{"emptyLinePlaceholder":411},[234,9559,9560,9563],{"class":236,"line":535},[234,9561,9562],{"class":9024},"scrape_configs",[234,9564,9028],{"class":387},[234,9566,9567,9569,9572,9574],{"class":236,"line":546},[234,9568,9550],{"class":387},[234,9570,9571],{"class":9024},"job_name",[234,9573,6562],{"class":387},[234,9575,9576],{"class":255},"'prometheus'\n",[234,9578,9579,9582],{"class":236,"line":552},[234,9580,9581],{"class":9024},"    static_configs",[234,9583,9028],{"class":387},[234,9585,9586,9588,9590,9592,9595],{"class":236,"line":557},[234,9587,9057],{"class":387},[234,9589,9525],{"class":9024},[234,9591,9528],{"class":387},[234,9593,9594],{"class":255},"'localhost:9090'",[234,9596,9534],{"class":387},[234,9598,9599],{"class":236,"line":594},[234,9600,412],{"emptyLinePlaceholder":411},[234,9602,9603,9605,9607,9609],{"class":236,"line":635},[234,9604,9550],{"class":387},[234,9606,9571],{"class":9024},[234,9608,6562],{"class":387},[234,9610,9611],{"class":255},"'node'\n",[234,9613,9614,9616],{"class":236,"line":643},[234,9615,9581],{"class":9024},[234,9617,9028],{"class":387},[234,9619,9620,9622,9624],{"class":236,"line":659},[234,9621,9057],{"class":387},[234,9623,9525],{"class":9024},[234,9625,9028],{"class":387},[234,9627,9628,9631],{"class":236,"line":683},[234,9629,9630],{"class":387},"          - ",[234,9632,9633],{"class":255},"'server-1.tudominio.internal:9100'\n",[234,9635,9636,9638],{"class":236,"line":695},[234,9637,9630],{"class":387},[234,9639,9640],{"class":255},"'server-2.tudominio.internal:9100'\n",[234,9642,9643,9645],{"class":236,"line":717},[234,9644,9630],{"class":387},[234,9646,9647],{"class":255},"'server-3.tudominio.internal:9100'\n",[234,9649,9650,9652],{"class":236,"line":723},[234,9651,9630],{"class":387},[234,9653,9654],{"class":255},"'worker-1.tudominio.internal:9100'\n",[234,9656,9657,9660],{"class":236,"line":729},[234,9658,9659],{"class":9024},"        labels",[234,9661,9028],{"class":387},[234,9663,9664,9667,9669],{"class":236,"line":734},[234,9665,9666],{"class":9024},"          environment",[234,9668,6562],{"class":387},[234,9670,9671],{"class":255},"'production'\n",[234,9673,9674],{"class":236,"line":771},[234,9675,412],{"emptyLinePlaceholder":411},[234,9677,9678,9680,9682,9684],{"class":236,"line":776},[234,9679,9550],{"class":387},[234,9681,9571],{"class":9024},[234,9683,6562],{"class":387},[234,9685,9686],{"class":255},"'apps'\n",[234,9688,9689,9691],{"class":236,"line":815},[234,9690,9581],{"class":9024},[234,9692,9028],{"class":387},[234,9694,9695,9697,9699],{"class":236,"line":820},[234,9696,9057],{"class":387},[234,9698,9525],{"class":9024},[234,9700,9028],{"class":387},[234,9702,9703,9705],{"class":236,"line":826},[234,9704,9630],{"class":387},[234,9706,9707],{"class":255},"'api.tudominio.internal:8080'\n",[234,9709,9710,9712],{"class":236,"line":846},[234,9711,9630],{"class":387},[234,9713,9714],{"class":255},"'worker.tudominio.internal:8080'\n",[234,9716,9717,9719],{"class":236,"line":859},[234,9718,9659],{"class":9024},[234,9720,9028],{"class":387},[234,9722,9723,9725,9727],{"class":236,"line":872},[234,9724,9666],{"class":9024},[234,9726,6562],{"class":387},[234,9728,9671],{"class":255},[234,9730,9731,9734,9736],{"class":236,"line":898},[234,9732,9733],{"class":9024},"    metrics_path",[234,9735,6562],{"class":387},[234,9737,9738],{"class":255},"'\u002Fmetrics'\n",[12,9740,9741,9742,9744,9745,9748],{},"Para clusters mayores o que cambian de composición con frecuencia, cambia ",[231,9743,9515],{}," por ",[231,9746,9747],{},"file_sd_configs"," apuntando a un JSON que generas automáticamente. Para 4 servidores estáticos, el archivo de arriba resuelve.",[12,9750,9751,9752,9755,9756,9759,9760,9763,9764,9767],{},"Reload: ",[231,9753,9754],{},"curl -X POST localhost:9090\u002F-\u002Freload",". Verifica en ",[231,9757,9758],{},"localhost:9090\u002Ftargets"," si todos los jobs están ",[231,9761,9762],{},"UP",". Los que estén ",[231,9765,9766],{},"DOWN"," todavía no fueron instrumentados — ese es el paso 4.",[19,9769,9771],{"id":9770},"paso-4-como-instalar-el-node_exporter-en-cada-servidor","Paso 4 — ¿Cómo instalar el node_exporter en cada servidor?",[12,9773,8933,9774,9777],{},[27,9775,9776],{},"15 minutos"," para 4 servidores.",[12,9779,9780],{},"En cada servidor monitoreado, corre el node_exporter. Hay dos formas: binario directo vía systemd, o contenedor Docker. En 2026 el consenso es container — facilita actualización y aislamiento. En cada nodo:",[224,9782,9784],{"className":226,"code":9783,"language":228,"meta":229,"style":229},"docker run -d \\\n  --name node-exporter \\\n  --restart unless-stopped \\\n  --net=\"host\" \\\n  --pid=\"host\" \\\n  -v \"\u002F:\u002Fhost:ro,rslave\" \\\n  prom\u002Fnode-exporter:v1.8.2 \\\n  --path.rootfs=\u002Fhost\n",[231,9785,9786,9799,9809,9819,9829,9838,9848,9855],{"__ignoreMap":229},[234,9787,9788,9790,9793,9796],{"class":236,"line":237},[234,9789,1118],{"class":247},[234,9791,9792],{"class":255}," run",[234,9794,9795],{"class":251}," -d",[234,9797,9798],{"class":383}," \\\n",[234,9800,9801,9804,9807],{"class":236,"line":244},[234,9802,9803],{"class":251},"  --name",[234,9805,9806],{"class":255}," node-exporter",[234,9808,9798],{"class":383},[234,9810,9811,9814,9817],{"class":236,"line":271},[234,9812,9813],{"class":251},"  --restart",[234,9815,9816],{"class":255}," unless-stopped",[234,9818,9798],{"class":383},[234,9820,9821,9824,9827],{"class":236,"line":415},[234,9822,9823],{"class":251},"  --net=",[234,9825,9826],{"class":255},"\"host\"",[234,9828,9798],{"class":383},[234,9830,9831,9834,9836],{"class":236,"line":434},[234,9832,9833],{"class":251},"  --pid=",[234,9835,9826],{"class":255},[234,9837,9798],{"class":383},[234,9839,9840,9843,9846],{"class":236,"line":459},[234,9841,9842],{"class":251},"  -v",[234,9844,9845],{"class":255}," \"\u002F:\u002Fhost:ro,rslave\"",[234,9847,9798],{"class":383},[234,9849,9850,9853],{"class":236,"line":464},[234,9851,9852],{"class":255},"  prom\u002Fnode-exporter:v1.8.2",[234,9854,9798],{"class":383},[234,9856,9857],{"class":236,"line":479},[234,9858,9859],{"class":251},"  --path.rootfs=\u002Fhost\n",[12,9861,9008,9862,9865,9866,9869,9870,571,9873,2403,9876,9879],{},[231,9863,9864],{},"--net=host"," es necesario para que vea las interfaces de red reales. El bind mount en ",[231,9867,9868],{},"\u002Fhost"," permite leer ",[231,9871,9872],{},"\u002Fproc",[231,9874,9875],{},"\u002Fsys",[231,9877,9878],{},"\u002Fetc\u002Fpasswd"," del host (read-only) sin correr el contenedor con privilegios de root.",[12,9881,9882,9883,1272],{},"Firewall: abre el puerto 9100 solo para la IP del servidor de observabilidad. En Ubuntu con ",[231,9884,9885],{},"ufw",[224,9887,9889],{"className":226,"code":9888,"language":228,"meta":229,"style":229},"ufw allow from \u003CIP_DEL_OBSERVABILITY> to any port 9100\n",[231,9890,9891],{"__ignoreMap":229},[234,9892,9893,9895,9898,9901,9904,9907,9910,9912,9915,9918,9921],{"class":236,"line":237},[234,9894,9885],{"class":247},[234,9896,9897],{"class":255}," allow",[234,9899,9900],{"class":255}," from",[234,9902,9903],{"class":383}," \u003C",[234,9905,9906],{"class":255},"IP_DEL_OBSERVABILIT",[234,9908,9909],{"class":387},"Y",[234,9911,1935],{"class":383},[234,9913,9914],{"class":255}," to",[234,9916,9917],{"class":255}," any",[234,9919,9920],{"class":255}," port",[234,9922,9923],{"class":251}," 9100\n",[12,9925,9926,9927,9930,9931,101],{},"Validación: del servidor de observability, ",[231,9928,9929],{},"curl http:\u002F\u002Fserver-1.tudominio.internal:9100\u002Fmetrics"," debe retornar cientos de líneas empezando con ",[231,9932,9933],{},"# HELP node_cpu_seconds_total...",[19,9935,9937],{"id":9936},"paso-5-como-configurar-loki-promtail","Paso 5 — ¿Cómo configurar Loki + Promtail?",[12,9939,8933,9940,101],{},[27,9941,9452],{},[12,9943,9944,9945,1272],{},"Loki ya está corriendo en el compose del paso 2. Falta el ",[231,9946,9947],{},"loki-config.yml",[224,9949,9951],{"className":9015,"code":9950,"language":9017,"meta":229,"style":229},"auth_enabled: false\n\nserver:\n  http_listen_port: 3100\n\ncommon:\n  path_prefix: \u002Floki\n  storage:\n    filesystem:\n      chunks_directory: \u002Floki\u002Fchunks\n      rules_directory: \u002Floki\u002Frules\n  replication_factor: 1\n  ring:\n    kvstore:\n      store: inmemory\n\nschema_config:\n  configs:\n    - from: 2024-01-01\n      store: tsdb\n      object_store: filesystem\n      schema: v13\n      index:\n        prefix: index_\n        period: 24h\n\nlimits_config:\n  retention_period: 720h  # 30 días\n  reject_old_samples: true\n  reject_old_samples_max_age: 168h\n",[231,9952,9953,9963,9967,9974,9984,9988,9995,10005,10012,10019,10029,10039,10049,10056,10063,10073,10077,10084,10091,10102,10111,10121,10131,10138,10148,10158,10162,10169,10182,10192],{"__ignoreMap":229},[234,9954,9955,9958,9960],{"class":236,"line":237},[234,9956,9957],{"class":9024},"auth_enabled",[234,9959,6562],{"class":387},[234,9961,9962],{"class":251},"false\n",[234,9964,9965],{"class":236,"line":244},[234,9966,412],{"emptyLinePlaceholder":411},[234,9968,9969,9972],{"class":236,"line":271},[234,9970,9971],{"class":9024},"server",[234,9973,9028],{"class":387},[234,9975,9976,9979,9981],{"class":236,"line":415},[234,9977,9978],{"class":9024},"  http_listen_port",[234,9980,6562],{"class":387},[234,9982,9983],{"class":251},"3100\n",[234,9985,9986],{"class":236,"line":434},[234,9987,412],{"emptyLinePlaceholder":411},[234,9989,9990,9993],{"class":236,"line":459},[234,9991,9992],{"class":9024},"common",[234,9994,9028],{"class":387},[234,9996,9997,10000,10002],{"class":236,"line":464},[234,9998,9999],{"class":9024},"  path_prefix",[234,10001,6562],{"class":387},[234,10003,10004],{"class":255},"\u002Floki\n",[234,10006,10007,10010],{"class":236,"line":479},[234,10008,10009],{"class":9024},"  storage",[234,10011,9028],{"class":387},[234,10013,10014,10017],{"class":236,"line":484},[234,10015,10016],{"class":9024},"    filesystem",[234,10018,9028],{"class":387},[234,10020,10021,10024,10026],{"class":236,"line":490},[234,10022,10023],{"class":9024},"      chunks_directory",[234,10025,6562],{"class":387},[234,10027,10028],{"class":255},"\u002Floki\u002Fchunks\n",[234,10030,10031,10034,10036],{"class":236,"line":508},[234,10032,10033],{"class":9024},"      rules_directory",[234,10035,6562],{"class":387},[234,10037,10038],{"class":255},"\u002Floki\u002Frules\n",[234,10040,10041,10044,10046],{"class":236,"line":529},[234,10042,10043],{"class":9024},"  replication_factor",[234,10045,6562],{"class":387},[234,10047,10048],{"class":251},"1\n",[234,10050,10051,10054],{"class":236,"line":535},[234,10052,10053],{"class":9024},"  ring",[234,10055,9028],{"class":387},[234,10057,10058,10061],{"class":236,"line":546},[234,10059,10060],{"class":9024},"    kvstore",[234,10062,9028],{"class":387},[234,10064,10065,10068,10070],{"class":236,"line":552},[234,10066,10067],{"class":9024},"      store",[234,10069,6562],{"class":387},[234,10071,10072],{"class":255},"inmemory\n",[234,10074,10075],{"class":236,"line":557},[234,10076,412],{"emptyLinePlaceholder":411},[234,10078,10079,10082],{"class":236,"line":594},[234,10080,10081],{"class":9024},"schema_config",[234,10083,9028],{"class":387},[234,10085,10086,10089],{"class":236,"line":635},[234,10087,10088],{"class":9024},"  configs",[234,10090,9028],{"class":387},[234,10092,10093,10095,10097,10099],{"class":236,"line":643},[234,10094,9512],{"class":387},[234,10096,391],{"class":9024},[234,10098,6562],{"class":387},[234,10100,10101],{"class":251},"2024-01-01\n",[234,10103,10104,10106,10108],{"class":236,"line":659},[234,10105,10067],{"class":9024},[234,10107,6562],{"class":387},[234,10109,10110],{"class":255},"tsdb\n",[234,10112,10113,10116,10118],{"class":236,"line":683},[234,10114,10115],{"class":9024},"      object_store",[234,10117,6562],{"class":387},[234,10119,10120],{"class":255},"filesystem\n",[234,10122,10123,10126,10128],{"class":236,"line":695},[234,10124,10125],{"class":9024},"      schema",[234,10127,6562],{"class":387},[234,10129,10130],{"class":255},"v13\n",[234,10132,10133,10136],{"class":236,"line":717},[234,10134,10135],{"class":9024},"      index",[234,10137,9028],{"class":387},[234,10139,10140,10143,10145],{"class":236,"line":723},[234,10141,10142],{"class":9024},"        prefix",[234,10144,6562],{"class":387},[234,10146,10147],{"class":255},"index_\n",[234,10149,10150,10153,10155],{"class":236,"line":729},[234,10151,10152],{"class":9024},"        period",[234,10154,6562],{"class":387},[234,10156,10157],{"class":255},"24h\n",[234,10159,10160],{"class":236,"line":734},[234,10161,412],{"emptyLinePlaceholder":411},[234,10163,10164,10167],{"class":236,"line":771},[234,10165,10166],{"class":9024},"limits_config",[234,10168,9028],{"class":387},[234,10170,10171,10174,10176,10179],{"class":236,"line":776},[234,10172,10173],{"class":9024},"  retention_period",[234,10175,6562],{"class":387},[234,10177,10178],{"class":255},"720h",[234,10180,10181],{"class":240},"  # 30 días\n",[234,10183,10184,10187,10189],{"class":236,"line":815},[234,10185,10186],{"class":9024},"  reject_old_samples",[234,10188,6562],{"class":387},[234,10190,10191],{"class":251},"true\n",[234,10193,10194,10197,10199],{"class":236,"line":820},[234,10195,10196],{"class":9024},"  reject_old_samples_max_age",[234,10198,6562],{"class":387},[234,10200,10201],{"class":255},"168h\n",[12,10203,10204],{},"Storage en filesystem es suficiente para empezar. Cuando pases de 50 GB de logs por día o quieras retención de 90+ días, migra a S3 (o compatible). No migres antes — complica la operación sin ganancia real.",[12,10206,10207],{},"En cada servidor monitoreado, instala Promtail (o Grafana Agent) también vía container:",[224,10209,10211],{"className":9015,"code":10210,"language":9017,"meta":229,"style":229},"# \u002Fopt\u002Fpromtail\u002Fpromtail-config.yml en cada servidor\nserver:\n  http_listen_port: 9080\n\nclients:\n  - url: http:\u002F\u002Fmonitor.tudominio.com:3100\u002Floki\u002Fapi\u002Fv1\u002Fpush\n\nscrape_configs:\n  - job_name: system\n    static_configs:\n      - targets: [localhost]\n        labels:\n          job: varlogs\n          host: ${HOSTNAME}\n          __path__: \u002Fvar\u002Flog\u002F*.log\n\n  - job_name: docker\n    docker_sd_configs:\n      - host: unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\n    relabel_configs:\n      - source_labels: ['__meta_docker_container_name']\n        target_label: 'container'\n",[231,10212,10213,10218,10224,10233,10237,10244,10256,10260,10266,10277,10283,10295,10301,10311,10321,10331,10335,10346,10353,10364,10371,10385],{"__ignoreMap":229},[234,10214,10215],{"class":236,"line":237},[234,10216,10217],{"class":240},"# \u002Fopt\u002Fpromtail\u002Fpromtail-config.yml en cada servidor\n",[234,10219,10220,10222],{"class":236,"line":244},[234,10221,9971],{"class":9024},[234,10223,9028],{"class":387},[234,10225,10226,10228,10230],{"class":236,"line":271},[234,10227,9978],{"class":9024},[234,10229,6562],{"class":387},[234,10231,10232],{"class":251},"9080\n",[234,10234,10235],{"class":236,"line":415},[234,10236,412],{"emptyLinePlaceholder":411},[234,10238,10239,10242],{"class":236,"line":434},[234,10240,10241],{"class":9024},"clients",[234,10243,9028],{"class":387},[234,10245,10246,10248,10251,10253],{"class":236,"line":459},[234,10247,9550],{"class":387},[234,10249,10250],{"class":9024},"url",[234,10252,6562],{"class":387},[234,10254,10255],{"class":255},"http:\u002F\u002Fmonitor.tudominio.com:3100\u002Floki\u002Fapi\u002Fv1\u002Fpush\n",[234,10257,10258],{"class":236,"line":464},[234,10259,412],{"emptyLinePlaceholder":411},[234,10261,10262,10264],{"class":236,"line":479},[234,10263,9562],{"class":9024},[234,10265,9028],{"class":387},[234,10267,10268,10270,10272,10274],{"class":236,"line":484},[234,10269,9550],{"class":387},[234,10271,9571],{"class":9024},[234,10273,6562],{"class":387},[234,10275,10276],{"class":255},"system\n",[234,10278,10279,10281],{"class":236,"line":490},[234,10280,9581],{"class":9024},[234,10282,9028],{"class":387},[234,10284,10285,10287,10289,10291,10293],{"class":236,"line":508},[234,10286,9057],{"class":387},[234,10288,9525],{"class":9024},[234,10290,9528],{"class":387},[234,10292,8962],{"class":255},[234,10294,9534],{"class":387},[234,10296,10297,10299],{"class":236,"line":529},[234,10298,9659],{"class":9024},[234,10300,9028],{"class":387},[234,10302,10303,10306,10308],{"class":236,"line":535},[234,10304,10305],{"class":9024},"          job",[234,10307,6562],{"class":387},[234,10309,10310],{"class":255},"varlogs\n",[234,10312,10313,10316,10318],{"class":236,"line":546},[234,10314,10315],{"class":9024},"          host",[234,10317,6562],{"class":387},[234,10319,10320],{"class":255},"${HOSTNAME}\n",[234,10322,10323,10326,10328],{"class":236,"line":552},[234,10324,10325],{"class":9024},"          __path__",[234,10327,6562],{"class":387},[234,10329,10330],{"class":255},"\u002Fvar\u002Flog\u002F*.log\n",[234,10332,10333],{"class":236,"line":557},[234,10334,412],{"emptyLinePlaceholder":411},[234,10336,10337,10339,10341,10343],{"class":236,"line":594},[234,10338,9550],{"class":387},[234,10340,9571],{"class":9024},[234,10342,6562],{"class":387},[234,10344,10345],{"class":255},"docker\n",[234,10347,10348,10351],{"class":236,"line":635},[234,10349,10350],{"class":9024},"    docker_sd_configs",[234,10352,9028],{"class":387},[234,10354,10355,10357,10359,10361],{"class":236,"line":643},[234,10356,9057],{"class":387},[234,10358,1650],{"class":9024},[234,10360,6562],{"class":387},[234,10362,10363],{"class":255},"unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\n",[234,10365,10366,10369],{"class":236,"line":659},[234,10367,10368],{"class":9024},"    relabel_configs",[234,10370,9028],{"class":387},[234,10372,10373,10375,10378,10380,10383],{"class":236,"line":683},[234,10374,9057],{"class":387},[234,10376,10377],{"class":9024},"source_labels",[234,10379,9528],{"class":387},[234,10381,10382],{"class":255},"'__meta_docker_container_name'",[234,10384,9534],{"class":387},[234,10386,10387,10390,10392],{"class":236,"line":695},[234,10388,10389],{"class":9024},"        target_label",[234,10391,6562],{"class":387},[234,10393,10394],{"class":255},"'container'\n",[12,10396,10397,10398,10401,10402,10404],{},"Importante: el endpoint ",[231,10399,10400],{},"http:\u002F\u002Fmonitor.tudominio.com:3100\u002Floki\u002Fapi\u002Fv1\u002Fpush"," necesita estar accesible desde los servidores. Si seguiste el paso 2 y ataste Loki en ",[231,10403,9366],{},", tienes dos opciones: exponer el 3100 vía reverse proxy con autenticación básica, o abrir un túnel SSH\u002FWireGuard entre los servidores. La segunda opción es más segura y la que recomendamos.",[12,10406,10407,10408,10411],{},"Validación: en Grafana, ve a Explore, selecciona la fuente de datos Loki, corre ",[231,10409,10410],{},"{job=\"varlogs\"}"," y ve los logs apareciendo en tiempo real.",[19,10413,10415],{"id":10414},"paso-6-como-importar-los-dashboards-de-grafana","Paso 6 — ¿Cómo importar los dashboards de Grafana?",[12,10417,8933,10418,101],{},[27,10419,10420],{},"20 minutos",[12,10422,10423,10424,10427,10428,101],{},"Accede a ",[231,10425,10426],{},"https:\u002F\u002Fmonitor.tudominio.com"," (después de configurar el reverse proxy del paso 8 — puedes saltar para allá ahora si quieres). Login admin con la contraseña del ",[231,10429,9374],{},[12,10431,10432,10433,1272],{},"Agrega las dos fuentes de datos vía provisioning automático. En ",[231,10434,10435],{},"grafana\u002Fprovisioning\u002Fdatasources\u002Fdatasources.yml",[224,10437,10439],{"className":9015,"code":10438,"language":9017,"meta":229,"style":229},"apiVersion: 1\ndatasources:\n  - name: Prometheus\n    type: prometheus\n    access: proxy\n    url: http:\u002F\u002Fprometheus:9090\n    isDefault: true\n  - name: Loki\n    type: loki\n    access: proxy\n    url: http:\u002F\u002Floki:3100\n",[231,10440,10441,10450,10457,10469,10479,10489,10499,10508,10519,10528,10536],{"__ignoreMap":229},[234,10442,10443,10446,10448],{"class":236,"line":237},[234,10444,10445],{"class":9024},"apiVersion",[234,10447,6562],{"class":387},[234,10449,10048],{"class":251},[234,10451,10452,10455],{"class":236,"line":244},[234,10453,10454],{"class":9024},"datasources",[234,10456,9028],{"class":387},[234,10458,10459,10461,10464,10466],{"class":236,"line":271},[234,10460,9550],{"class":387},[234,10462,10463],{"class":9024},"name",[234,10465,6562],{"class":387},[234,10467,10468],{"class":255},"Prometheus\n",[234,10470,10471,10474,10476],{"class":236,"line":415},[234,10472,10473],{"class":9024},"    type",[234,10475,6562],{"class":387},[234,10477,10478],{"class":255},"prometheus\n",[234,10480,10481,10484,10486],{"class":236,"line":434},[234,10482,10483],{"class":9024},"    access",[234,10485,6562],{"class":387},[234,10487,10488],{"class":255},"proxy\n",[234,10490,10491,10494,10496],{"class":236,"line":459},[234,10492,10493],{"class":9024},"    url",[234,10495,6562],{"class":387},[234,10497,10498],{"class":255},"http:\u002F\u002Fprometheus:9090\n",[234,10500,10501,10504,10506],{"class":236,"line":464},[234,10502,10503],{"class":9024},"    isDefault",[234,10505,6562],{"class":387},[234,10507,10191],{"class":251},[234,10509,10510,10512,10514,10516],{"class":236,"line":479},[234,10511,9550],{"class":387},[234,10513,10463],{"class":9024},[234,10515,6562],{"class":387},[234,10517,10518],{"class":255},"Loki\n",[234,10520,10521,10523,10525],{"class":236,"line":484},[234,10522,10473],{"class":9024},[234,10524,6562],{"class":387},[234,10526,10527],{"class":255},"loki\n",[234,10529,10530,10532,10534],{"class":236,"line":490},[234,10531,10483],{"class":9024},[234,10533,6562],{"class":387},[234,10535,10488],{"class":255},[234,10537,10538,10540,10542],{"class":236,"line":508},[234,10539,10493],{"class":9024},[234,10541,6562],{"class":387},[234,10543,10544],{"class":255},"http:\u002F\u002Floki:3100\n",[12,10546,10547,10548,10551],{},"Reinicia Grafana con ",[231,10549,10550],{},"docker compose restart grafana"," y las fuentes aparecen automáticamente.",[12,10553,10554,10555,10558],{},"Importa los dashboards listos. En ",[27,10556,10557],{},"Dashboards → New → Import",", pega el ID del dashboard:",[2735,10560,10561,10567,10573],{},[70,10562,10563,10566],{},[27,10564,10565],{},"1860"," — Node Exporter Full. CPU, RAM, disco, red, sistema de archivos. Es el dashboard más usado de la comunidad Prometheus, con razón.",[70,10568,10569,10572],{},[27,10570,10571],{},"13639"," — Logs \u002F App. Visualización básica de logs de Loki con filtros por job, container, host.",[70,10574,10575,10578],{},[27,10576,10577],{},"15172"," — Cluster overview. Visión consolidada por servidor, útil para cluster pequeño.",[12,10580,10581,10582,10585],{},"Customiza cada uno para usar ",[231,10583,10584],{},"environment=\"production\""," en el filtro default. Después de dos semanas usándolos, vas a querer crear dashboards propios para workloads específicos — no hay atajo ahí, es tiempo de silla.",[19,10587,10589],{"id":10588},"paso-7-como-configurar-alertas-basicas","Paso 7 — ¿Cómo configurar alertas básicas?",[12,10591,8933,10592,101],{},[27,10593,8992],{},[12,10595,10596],{},"Alertas son donde 80% de los equipos tropiezan: o ponen poquísimos y descubren incidentes por los clientes, o ponen decenas y desensibilizan al equipo.",[12,10598,10599,10600,10603,10604,1272],{},"Empieza con ",[27,10601,10602],{},"seis alertas esenciales",". En ",[231,10605,10606],{},"prometheus\u002Falerts.yml",[224,10608,10610],{"className":9015,"code":10609,"language":9017,"meta":229,"style":229},"groups:\n  - name: essentials\n    interval: 30s\n    rules:\n      - alert: ServerDown\n        expr: up{job=\"node\"} == 0\n        for: 2m\n        labels:\n          severity: critical\n        annotations:\n          summary: \"Servidor {{ $labels.instance }} está fuera del aire\"\n\n      - alert: HighCPU\n        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100) > 80\n        for: 10m\n        labels:\n          severity: warning\n\n      - alert: DiskAlmostFull\n        expr: (node_filesystem_avail_bytes{mountpoint=\"\u002F\"} \u002F node_filesystem_size_bytes{mountpoint=\"\u002F\"}) * 100 \u003C 15\n        for: 5m\n        labels:\n          severity: critical\n\n      - alert: HighMemory\n        expr: (1 - (node_memory_MemAvailable_bytes \u002F node_memory_MemTotal_bytes)) * 100 > 90\n        for: 10m\n        labels:\n          severity: warning\n\n      - alert: HighHTTPErrorRate\n        expr: sum(rate(http_requests_total{status=~\"5..\"}[5m])) \u002F sum(rate(http_requests_total[5m])) > 0.05\n        for: 5m\n        labels:\n          severity: critical\n\n      - alert: HighLatency\n        expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 2\n        for: 10m\n        labels:\n          severity: warning\n",[231,10611,10612,10619,10630,10640,10647,10659,10669,10679,10685,10695,10702,10712,10716,10727,10736,10745,10751,10760,10764,10775,10784,10793,10799,10807,10811,10822,10831,10839,10845,10853,10857,10868,10877,10885,10891,10899,10903,10914,10923,10931,10937],{"__ignoreMap":229},[234,10613,10614,10617],{"class":236,"line":237},[234,10615,10616],{"class":9024},"groups",[234,10618,9028],{"class":387},[234,10620,10621,10623,10625,10627],{"class":236,"line":244},[234,10622,9550],{"class":387},[234,10624,10463],{"class":9024},[234,10626,6562],{"class":387},[234,10628,10629],{"class":255},"essentials\n",[234,10631,10632,10635,10637],{"class":236,"line":271},[234,10633,10634],{"class":9024},"    interval",[234,10636,6562],{"class":387},[234,10638,10639],{"class":255},"30s\n",[234,10641,10642,10645],{"class":236,"line":415},[234,10643,10644],{"class":9024},"    rules",[234,10646,9028],{"class":387},[234,10648,10649,10651,10654,10656],{"class":236,"line":434},[234,10650,9057],{"class":387},[234,10652,10653],{"class":9024},"alert",[234,10655,6562],{"class":387},[234,10657,10658],{"class":255},"ServerDown\n",[234,10660,10661,10664,10666],{"class":236,"line":459},[234,10662,10663],{"class":9024},"        expr",[234,10665,6562],{"class":387},[234,10667,10668],{"class":255},"up{job=\"node\"} == 0\n",[234,10670,10671,10674,10676],{"class":236,"line":464},[234,10672,10673],{"class":9024},"        for",[234,10675,6562],{"class":387},[234,10677,10678],{"class":255},"2m\n",[234,10680,10681,10683],{"class":236,"line":479},[234,10682,9659],{"class":9024},[234,10684,9028],{"class":387},[234,10686,10687,10690,10692],{"class":236,"line":484},[234,10688,10689],{"class":9024},"          severity",[234,10691,6562],{"class":387},[234,10693,10694],{"class":255},"critical\n",[234,10696,10697,10700],{"class":236,"line":490},[234,10698,10699],{"class":9024},"        annotations",[234,10701,9028],{"class":387},[234,10703,10704,10707,10709],{"class":236,"line":508},[234,10705,10706],{"class":9024},"          summary",[234,10708,6562],{"class":387},[234,10710,10711],{"class":255},"\"Servidor {{ $labels.instance }} está fuera del aire\"\n",[234,10713,10714],{"class":236,"line":529},[234,10715,412],{"emptyLinePlaceholder":411},[234,10717,10718,10720,10722,10724],{"class":236,"line":535},[234,10719,9057],{"class":387},[234,10721,10653],{"class":9024},[234,10723,6562],{"class":387},[234,10725,10726],{"class":255},"HighCPU\n",[234,10728,10729,10731,10733],{"class":236,"line":546},[234,10730,10663],{"class":9024},[234,10732,6562],{"class":387},[234,10734,10735],{"class":255},"100 - (avg by(instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100) > 80\n",[234,10737,10738,10740,10742],{"class":236,"line":552},[234,10739,10673],{"class":9024},[234,10741,6562],{"class":387},[234,10743,10744],{"class":255},"10m\n",[234,10746,10747,10749],{"class":236,"line":557},[234,10748,9659],{"class":9024},[234,10750,9028],{"class":387},[234,10752,10753,10755,10757],{"class":236,"line":594},[234,10754,10689],{"class":9024},[234,10756,6562],{"class":387},[234,10758,10759],{"class":255},"warning\n",[234,10761,10762],{"class":236,"line":635},[234,10763,412],{"emptyLinePlaceholder":411},[234,10765,10766,10768,10770,10772],{"class":236,"line":643},[234,10767,9057],{"class":387},[234,10769,10653],{"class":9024},[234,10771,6562],{"class":387},[234,10773,10774],{"class":255},"DiskAlmostFull\n",[234,10776,10777,10779,10781],{"class":236,"line":659},[234,10778,10663],{"class":9024},[234,10780,6562],{"class":387},[234,10782,10783],{"class":255},"(node_filesystem_avail_bytes{mountpoint=\"\u002F\"} \u002F node_filesystem_size_bytes{mountpoint=\"\u002F\"}) * 100 \u003C 15\n",[234,10785,10786,10788,10790],{"class":236,"line":683},[234,10787,10673],{"class":9024},[234,10789,6562],{"class":387},[234,10791,10792],{"class":255},"5m\n",[234,10794,10795,10797],{"class":236,"line":695},[234,10796,9659],{"class":9024},[234,10798,9028],{"class":387},[234,10800,10801,10803,10805],{"class":236,"line":717},[234,10802,10689],{"class":9024},[234,10804,6562],{"class":387},[234,10806,10694],{"class":255},[234,10808,10809],{"class":236,"line":723},[234,10810,412],{"emptyLinePlaceholder":411},[234,10812,10813,10815,10817,10819],{"class":236,"line":729},[234,10814,9057],{"class":387},[234,10816,10653],{"class":9024},[234,10818,6562],{"class":387},[234,10820,10821],{"class":255},"HighMemory\n",[234,10823,10824,10826,10828],{"class":236,"line":734},[234,10825,10663],{"class":9024},[234,10827,6562],{"class":387},[234,10829,10830],{"class":255},"(1 - (node_memory_MemAvailable_bytes \u002F node_memory_MemTotal_bytes)) * 100 > 90\n",[234,10832,10833,10835,10837],{"class":236,"line":771},[234,10834,10673],{"class":9024},[234,10836,6562],{"class":387},[234,10838,10744],{"class":255},[234,10840,10841,10843],{"class":236,"line":776},[234,10842,9659],{"class":9024},[234,10844,9028],{"class":387},[234,10846,10847,10849,10851],{"class":236,"line":815},[234,10848,10689],{"class":9024},[234,10850,6562],{"class":387},[234,10852,10759],{"class":255},[234,10854,10855],{"class":236,"line":820},[234,10856,412],{"emptyLinePlaceholder":411},[234,10858,10859,10861,10863,10865],{"class":236,"line":826},[234,10860,9057],{"class":387},[234,10862,10653],{"class":9024},[234,10864,6562],{"class":387},[234,10866,10867],{"class":255},"HighHTTPErrorRate\n",[234,10869,10870,10872,10874],{"class":236,"line":846},[234,10871,10663],{"class":9024},[234,10873,6562],{"class":387},[234,10875,10876],{"class":255},"sum(rate(http_requests_total{status=~\"5..\"}[5m])) \u002F sum(rate(http_requests_total[5m])) > 0.05\n",[234,10878,10879,10881,10883],{"class":236,"line":859},[234,10880,10673],{"class":9024},[234,10882,6562],{"class":387},[234,10884,10792],{"class":255},[234,10886,10887,10889],{"class":236,"line":872},[234,10888,9659],{"class":9024},[234,10890,9028],{"class":387},[234,10892,10893,10895,10897],{"class":236,"line":898},[234,10894,10689],{"class":9024},[234,10896,6562],{"class":387},[234,10898,10694],{"class":255},[234,10900,10901],{"class":236,"line":913},[234,10902,412],{"emptyLinePlaceholder":411},[234,10904,10905,10907,10909,10911],{"class":236,"line":1886},[234,10906,9057],{"class":387},[234,10908,10653],{"class":9024},[234,10910,6562],{"class":387},[234,10912,10913],{"class":255},"HighLatency\n",[234,10915,10916,10918,10920],{"class":236,"line":1901},[234,10917,10663],{"class":9024},[234,10919,6562],{"class":387},[234,10921,10922],{"class":255},"histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 2\n",[234,10924,10925,10927,10929],{"class":236,"line":1920},[234,10926,10673],{"class":9024},[234,10928,6562],{"class":387},[234,10930,10744],{"class":255},[234,10932,10933,10935],{"class":236,"line":1944},[234,10934,9659],{"class":9024},[234,10936,9028],{"class":387},[234,10938,10939,10941,10943],{"class":236,"line":1962},[234,10940,10689],{"class":9024},[234,10942,6562],{"class":387},[234,10944,10759],{"class":255},[12,10946,10947,10948,10951],{},"Y el ",[231,10949,10950],{},"alertmanager\u002Falertmanager.yml"," apuntando a un webhook de Slack o Discord:",[224,10953,10955],{"className":9015,"code":10954,"language":9017,"meta":229,"style":229},"route:\n  group_by: ['alertname', 'severity']\n  group_wait: 30s\n  group_interval: 5m\n  repeat_interval: 4h\n  receiver: 'slack-default'\n  routes:\n    - match:\n        severity: critical\n      receiver: 'slack-critical'\n      repeat_interval: 1h\n\nreceivers:\n  - name: 'slack-default'\n    slack_configs:\n      - api_url: 'https:\u002F\u002Fhooks.slack.com\u002Fservices\u002FTU\u002FWEBHOOK\u002FAQUI'\n        channel: '#alerts'\n        send_resolved: true\n\n  - name: 'slack-critical'\n    slack_configs:\n      - api_url: 'https:\u002F\u002Fhooks.slack.com\u002Fservices\u002FTU\u002FWEBHOOK\u002FAQUI'\n        channel: '#alerts-critical'\n        send_resolved: true\n",[231,10956,10957,10964,10981,10990,10999,11009,11019,11026,11035,11044,11054,11064,11068,11075,11085,11092,11104,11114,11123,11127,11137,11143,11153,11162],{"__ignoreMap":229},[234,10958,10959,10962],{"class":236,"line":237},[234,10960,10961],{"class":9024},"route",[234,10963,9028],{"class":387},[234,10965,10966,10969,10971,10974,10976,10979],{"class":236,"line":244},[234,10967,10968],{"class":9024},"  group_by",[234,10970,9528],{"class":387},[234,10972,10973],{"class":255},"'alertname'",[234,10975,571],{"class":387},[234,10977,10978],{"class":255},"'severity'",[234,10980,9534],{"class":387},[234,10982,10983,10986,10988],{"class":236,"line":271},[234,10984,10985],{"class":9024},"  group_wait",[234,10987,6562],{"class":387},[234,10989,10639],{"class":255},[234,10991,10992,10995,10997],{"class":236,"line":415},[234,10993,10994],{"class":9024},"  group_interval",[234,10996,6562],{"class":387},[234,10998,10792],{"class":255},[234,11000,11001,11004,11006],{"class":236,"line":434},[234,11002,11003],{"class":9024},"  repeat_interval",[234,11005,6562],{"class":387},[234,11007,11008],{"class":255},"4h\n",[234,11010,11011,11014,11016],{"class":236,"line":459},[234,11012,11013],{"class":9024},"  receiver",[234,11015,6562],{"class":387},[234,11017,11018],{"class":255},"'slack-default'\n",[234,11020,11021,11024],{"class":236,"line":464},[234,11022,11023],{"class":9024},"  routes",[234,11025,9028],{"class":387},[234,11027,11028,11030,11033],{"class":236,"line":479},[234,11029,9512],{"class":387},[234,11031,11032],{"class":9024},"match",[234,11034,9028],{"class":387},[234,11036,11037,11040,11042],{"class":236,"line":484},[234,11038,11039],{"class":9024},"        severity",[234,11041,6562],{"class":387},[234,11043,10694],{"class":255},[234,11045,11046,11049,11051],{"class":236,"line":490},[234,11047,11048],{"class":9024},"      receiver",[234,11050,6562],{"class":387},[234,11052,11053],{"class":255},"'slack-critical'\n",[234,11055,11056,11059,11061],{"class":236,"line":508},[234,11057,11058],{"class":9024},"      repeat_interval",[234,11060,6562],{"class":387},[234,11062,11063],{"class":255},"1h\n",[234,11065,11066],{"class":236,"line":529},[234,11067,412],{"emptyLinePlaceholder":411},[234,11069,11070,11073],{"class":236,"line":535},[234,11071,11072],{"class":9024},"receivers",[234,11074,9028],{"class":387},[234,11076,11077,11079,11081,11083],{"class":236,"line":546},[234,11078,9550],{"class":387},[234,11080,10463],{"class":9024},[234,11082,6562],{"class":387},[234,11084,11018],{"class":255},[234,11086,11087,11090],{"class":236,"line":552},[234,11088,11089],{"class":9024},"    slack_configs",[234,11091,9028],{"class":387},[234,11093,11094,11096,11099,11101],{"class":236,"line":557},[234,11095,9057],{"class":387},[234,11097,11098],{"class":9024},"api_url",[234,11100,6562],{"class":387},[234,11102,11103],{"class":255},"'https:\u002F\u002Fhooks.slack.com\u002Fservices\u002FTU\u002FWEBHOOK\u002FAQUI'\n",[234,11105,11106,11109,11111],{"class":236,"line":594},[234,11107,11108],{"class":9024},"        channel",[234,11110,6562],{"class":387},[234,11112,11113],{"class":255},"'#alerts'\n",[234,11115,11116,11119,11121],{"class":236,"line":635},[234,11117,11118],{"class":9024},"        send_resolved",[234,11120,6562],{"class":387},[234,11122,10191],{"class":251},[234,11124,11125],{"class":236,"line":643},[234,11126,412],{"emptyLinePlaceholder":411},[234,11128,11129,11131,11133,11135],{"class":236,"line":659},[234,11130,9550],{"class":387},[234,11132,10463],{"class":9024},[234,11134,6562],{"class":387},[234,11136,11053],{"class":255},[234,11138,11139,11141],{"class":236,"line":683},[234,11140,11089],{"class":9024},[234,11142,9028],{"class":387},[234,11144,11145,11147,11149,11151],{"class":236,"line":695},[234,11146,9057],{"class":387},[234,11148,11098],{"class":9024},[234,11150,6562],{"class":387},[234,11152,11103],{"class":255},[234,11154,11155,11157,11159],{"class":236,"line":717},[234,11156,11108],{"class":9024},[234,11158,6562],{"class":387},[234,11160,11161],{"class":255},"'#alerts-critical'\n",[234,11163,11164,11166,11168],{"class":236,"line":723},[234,11165,11118],{"class":9024},[234,11167,6562],{"class":387},[234,11169,10191],{"class":251},[12,11171,11172,11173,11176,11177,11180],{},"Dos detalles que ahorran noche de sueño. El ",[231,11174,11175],{},"for: 10m"," en CPU evita que picos cortos se vuelvan alertas — el servidor puede llegar a 95% por 30 segundos y eso ser normal. El ",[231,11178,11179],{},"repeat_interval: 4h"," para warnings garantiza que un warning resuelto en una hora no se vuelva 60 mensajes — el Alertmanager agrupa.",[12,11182,11183,11184,11186,11187,11190,11191,11194],{},"Recarga Prometheus (",[231,11185,9754],{},") y prueba forzando una alerta: ",[231,11188,11189],{},"stress --cpu 4 --timeout 700s"," en algún servidor debe disparar ",[231,11192,11193],{},"HighCPU"," en 10 minutos.",[19,11196,11198],{"id":11197},"paso-8-como-poner-reverse-proxy-y-tls-al-frente","Paso 8 — ¿Cómo poner reverse proxy y TLS al frente?",[12,11200,8933,11201,101],{},[27,11202,10420],{},[12,11204,11205,11206,11208],{},"Para acceder a Grafana vía ",[231,11207,10426],{}," con certificado válido, necesitas algo al frente del puerto 3000. Dos opciones:",[67,11210,11211,11220],{},[70,11212,11213,11215,11216,11219],{},[27,11214,5604],{}," — si ya tienes el cluster HeroCtl corriendo, basta declarar Grafana como job con ",[231,11217,11218],{},"ingress: { host: monitor.tudominio.com, tls: true }",". Certificado Let's Encrypt automático, sin herramienta adicional.",[70,11221,11222,11225,11226],{},[27,11223,11224],{},"Caddy standalone"," en la propia VPS de observabilidad — también emite Let's Encrypt automáticamente. Caddyfile mínimo:",[224,11227,11230],{"className":11228,"code":11229,"language":2530},[2528],"monitor.tudominio.com {\n  reverse_proxy localhost:3000\n  basicauth \u002Flogin {\n    admin \u003Chash_bcrypt>\n  }\n}\n",[231,11231,11229],{"__ignoreMap":229},[12,11233,11234,11235,11238],{},"Para defensa en profundidad, mantén autenticación básica del Caddy\u002Frouter al frente del login de Grafana — dos barreras, no una. La segunda es especialmente importante porque el login default de Grafana es ",[231,11236,11237],{},"admin\u002Fadmin"," y la primera cosa que los bots hacen en un Grafana expuesto es probar esa combinación.",[19,11240,11242],{"id":11241},"paso-9-como-instrumentar-metricas-de-aplicacion","Paso 9 — ¿Cómo instrumentar métricas de aplicación?",[12,11244,8933,11245,101],{},[27,11246,11247],{},"varía según número de aplicaciones",[12,11249,11250],{},"Métricas de sistema son la mitad de la historia. La otra mitad es lo que tu aplicación está haciendo — cuántas requests por segundo, cuál la latencia p99, cuántos errores, cuál el tamaño de la cola de jobs en background.",[12,11252,11253],{},"Cada lenguaje popular tiene cliente Prometheus oficial:",[2735,11255,11256,11264,11272,11279],{},[70,11257,11258,6562,11261],{},[27,11259,11260],{},"Node.js",[231,11262,11263],{},"prom-client",[70,11265,11266,6562,11269],{},[27,11267,11268],{},"Python",[231,11270,11271],{},"prometheus-client",[70,11273,11274,6562,11277],{},[27,11275,11276],{},"Ruby",[231,11278,11271],{},[70,11280,11281,6562,11284],{},[27,11282,11283],{},"Go",[231,11285,11286],{},"github.com\u002Fprometheus\u002Fclient_golang",[12,11288,11289],{},"El estándar mínimo son tres métricas por endpoint HTTP:",[2735,11291,11292,11306,11312],{},[70,11293,11294,11297,11298,571,11301,571,11304,101],{},[231,11295,11296],{},"http_requests_total"," — counter, con labels ",[231,11299,11300],{},"method",[231,11302,11303],{},"path",[231,11305,614],{},[70,11307,11308,11311],{},[231,11309,11310],{},"http_request_duration_seconds"," — histogram, mismo set de labels.",[70,11313,11314,11317,11318,11321],{},[231,11315,11316],{},"app_errors_total"," — counter, con label ",[231,11319,11320],{},"kind"," (\"validation\", \"db\", \"external_api\", etc).",[12,11323,11324,11325,11327,11328,11330],{},"Expone todo eso en ",[231,11326,8913],{},". Agrega el endpoint en el ",[231,11329,9562],{}," de Prometheus. En horas tienes dashboards por endpoint, alertas por tasa de error, y la capacidad de responder \"qué estaba ocurriendo a las 3:14 de ayer\" con un gráfico en lugar de un tiro al aire.",[12,11332,11333,11334,11337,11338,11341],{},"Cuidado con ",[27,11335,11336],{},"cardinalidad",". Cada combinación única de labels se vuelve una serie temporal separada. Si pones ",[231,11339,11340],{},"user_id"," como label, con 100k usuarios creas 100k series — y Prometheus va a consumir 8+ GB de RAM solo para indexar eso. Regla práctica: labels tienen valores en conjuntos pequeños (status code: 5 valores; método: 5 valores; path: decenas). Identificadores únicos van en logs, no en métricas.",[19,11343,11345],{"id":11344},"como-correr-esto-dentro-de-heroctl-en-lugar-de-vps-dedicada","¿Cómo correr esto dentro de HeroCtl en lugar de VPS dedicada?",[12,11347,11348],{},"Para clusters que ya corren el orquestador, tiene sentido considerar la stack como un job más. Trade-off: ahorras una VPS, pero pierdes aislamiento (si el cluster muere, el monitoring muere junto).",[12,11350,11351],{},"La topología queda así:",[2735,11353,11354,11360,11366,11372],{},[70,11355,11356,11359],{},[27,11357,11358],{},"1 job spec único"," con 4 tasks: prometheus, grafana, loki, alertmanager.",[70,11361,11362,11365],{},[27,11363,11364],{},"Volúmenes replicados"," en el cluster — los datos sobreviven a falla de un nodo.",[70,11367,11368,11371],{},[27,11369,11370],{},"Router integrado"," hace el TLS automático vía subdominio. No necesita Caddy adicional.",[70,11373,11374,11377],{},[27,11375,11376],{},"Métricas del propio cluster"," ya son expuestas en formato Prometheus en la API administrativa, entonces el scrape es directo.",[12,11379,11380],{},"Para producción crítica, recomendamos la separación física (VPS dedicada fuera del cluster). Para proyecto personal, MVP, o equipo pequeño donde \"todo cae junto\" es aceptable, correr dentro es más barato y operacionalmente más simple. El job spec entero queda en torno de 80 líneas de manifiesto.",[19,11382,11384],{"id":11383},"cuanto-cuesta-esa-stack-al-mes-en-brasil","¿Cuánto cuesta esa stack al mes en Brasil?",[119,11386,11387,11397],{},[122,11388,11389],{},[125,11390,11391,11394],{},[128,11392,11393],{},"Ítem",[128,11395,11396],{},"Costo mensual (BRL)",[141,11398,11399,11407,11415,11423],{},[125,11400,11401,11404],{},[146,11402,11403],{},"VPS observability dedicada (4 GB RAM)",[146,11405,11406],{},"R$40 a R$80",[125,11408,11409,11412],{},[146,11410,11411],{},"Object storage para retención larga de logs (opcional)",[146,11413,11414],{},"R$30",[125,11416,11417,11420],{},[146,11418,11419],{},"Tiempo de mantenimiento (2 a 4h × valor de la hora)",[146,11421,11422],{},"R$200 a R$400",[125,11424,11425,11430],{},[146,11426,11427],{},[27,11428,11429],{},"Total operacional",[146,11431,11432],{},[27,11433,11434],{},"R$300 a R$500",[12,11436,11437],{},"Para comparación, una suscripción de Datadog o New Relic con cobertura equivalente (5 hosts, retención de logs de 30 días, alertas, dashboards) sale en torno de R$1.500 a R$2.000 al mes — sin contar el overage automático que aparece al final del mes cuando alguien olvida un log verboso encendido.",[12,11439,11440],{},"La diferencia no es pequeña: en un año, la stack open-source self-hosted ahorra entre R$12.000 y R$18.000. Para startup en etapa inicial, eso es medio ingeniero júnior.",[19,11442,11444],{"id":11443},"tabla-de-puertos-recursos-y-caracteristicas-por-componente","Tabla de puertos, recursos y características por componente",[119,11446,11447,11467],{},[122,11448,11449],{},[125,11450,11451,11453,11456,11458,11461,11464],{},[128,11452,130],{},[128,11454,11455],{},"Puerto",[128,11457,3874],{},[128,11459,11460],{},"Disco",[128,11462,11463],{},"Retención default",[128,11465,11466],{},"Formato de los datos",[141,11468,11469,11488,11506,11524,11543,11559],{},[125,11470,11471,11473,11476,11479,11482,11485],{},[146,11472,8837],{},[146,11474,11475],{},"9090",[146,11477,11478],{},"512 MB",[146,11480,11481],{},"10 GB",[146,11483,11484],{},"15 días",[146,11486,11487],{},"TSDB binario",[125,11489,11490,11492,11495,11498,11501,11503],{},[146,11491,8843],{},[146,11493,11494],{},"3000",[146,11496,11497],{},"256 MB",[146,11499,11500],{},"1 GB",[146,11502,3056],{},[146,11504,11505],{},"SQLite o Postgres",[125,11507,11508,11510,11513,11515,11518,11521],{},[146,11509,8849],{},[146,11511,11512],{},"3100",[146,11514,11478],{},[146,11516,11517],{},"30 GB",[146,11519,11520],{},"30 días (configurable)",[146,11522,11523],{},"chunks comprimidos",[125,11525,11526,11529,11532,11535,11538,11540],{},[146,11527,11528],{},"Promtail \u002F Agent",[146,11530,11531],{},"9080",[146,11533,11534],{},"128 MB",[146,11536,11537],{},"mínimo",[146,11539,3056],{},[146,11541,11542],{},"pasa por valor",[125,11544,11545,11547,11550,11552,11554,11556],{},[146,11546,8867],{},[146,11548,11549],{},"9093",[146,11551,11534],{},[146,11553,11500],{},[146,11555,3056],{},[146,11557,11558],{},"log de notificaciones",[125,11560,11561,11563,11566,11569,11571,11573],{},[146,11562,8861],{},[146,11564,11565],{},"9100",[146,11567,11568],{},"64 MB",[146,11570,11537],{},[146,11572,3056],{},[146,11574,11575],{},"endpoint de scrape",[12,11577,11578],{},"Esas son las mínimas viables para cluster pequeño. En producción con 30 servidores y tráfico real, multiplica RAM por 3 y disco por 5.",[19,11580,11582],{"id":11581},"los-cuatro-errores-que-matan-stack-de-monitoring-nueva","Los cuatro errores que matan stack de monitoring nueva",[12,11584,11585],{},"Equipos montando observabilidad por primera vez tropiezan casi siempre en los mismos cuatro errores. Saber sobre ellos antes ahorra meses.",[12,11587,11588,11591,11592,11595],{},[27,11589,11590],{},"No monitorear el monitoring."," Prometheus paró de scrape el jueves; nadie vio. El miércoles de la semana siguiente un servidor cayó de verdad y descubrieron que no había alerta porque Prometheus estaba muerto hace 6 días. Solución: configura un cron externo simple (hasta un Pingdom gratuito sirve) que pegue en ",[231,11593,11594],{},"https:\u002F\u002Fmonitor.tudominio.com\u002Fapi\u002Fhealth"," cada 5 minutos y te avise cuando el propio Grafana caiga.",[12,11597,11598,11601,11602,11605],{},[27,11599,11600],{},"Sin estrategia de retención."," Disco se llena en tres meses, Prometheus para de grabar, alguien borra todo en la desesperación, pierde 90 días de historial. Configura ",[231,11603,11604],{},"--storage.tsdb.retention.time=30d"," desde el día uno y establece un job de housekeeping.",[12,11607,11608,11611,11612,571,11614,11617],{},[27,11609,11610],{},"Cardinalidad alta en labels."," Ya cubrimos en el paso 9, pero vale la pena repetir: cada ",[231,11613,11340],{},[231,11615,11616],{},"request_id"," o UUID que se vuelve label es un número que multiplica explosivamente el consumo de RAM de Prometheus. Identificadores únicos van a Loki, no a Prometheus.",[12,11619,11620,11623],{},[27,11621,11622],{},"Alertas ruidosas."," El equipo recibe 200 alertas por día. En dos semanas, nadie mira más. Cuando el sitio caiga de verdad, la alerta va a estar en medio de otras 199. Solución: empieza con seis alertas (las del paso 7), audita cada dos semanas, y excluye todo lo que disparó pero no exigió acción humana. Alerta sin acción es ruido.",[19,11625,3226],{"id":3225},[12,11627,11628,11631],{},[27,11629,11630],{},"¿Puedo correr todo en una VPS de 2 GB?","\nTécnicamente sí, para cluster de hasta 3 servidores y pocas aplicaciones. En la práctica vas a chocar contra el techo de RAM en 2 a 3 meses, especialmente si importas dashboards densos en Grafana. Paga los 50 reales más y ve directo a la VPS de 4 GB — el tiempo que ahorras no peleando con OOM kills se paga solo.",[12,11633,11634,11637],{},[27,11635,11636],{},"¿Cuánto disco para 30 días de logs?","\nDepende totalmente del volumen de logs de tu aplicación. Regla gruesa para startup pequeña: cluster de 4 servidores con aplicaciones web normales genera 1 a 5 GB de logs por día después de compresión de Loki. Treinta días da entre 30 y 150 GB. Empieza con 50 GB de SSD, monitorea el crecimiento por dos semanas, expande si es necesario. Si vas mucho más allá de eso, es hora de ir a object storage.",[12,11639,11640,11643],{},[27,11641,11642],{},"Grafana Cloud vs self-hosted, ¿cuál elegir?","\nGrafana Cloud free tier es generoso (10k series, 50 GB de logs, retención de 14 días) y elimina el trabajo de mantener el servidor. Para proyecto solo o equipo muy pequeño, tiene sentido. A partir del momento en que pasas del free tier, los precios escalan rápido — a partir de US$50\u002Fmes — y pierdes el control sobre los datos. Self-hosted cuesta hardware + tiempo, Cloud cuesta dinero + lock-in. Para empresa que pretende crecer y tiene un dev DevOps en el equipo, self-hosted gana.",[12,11645,11646,11649],{},[27,11647,11648],{},"¿Promtail o Grafana Agent?","\nEn 2026, Grafana Agent (rebautizado a Grafana Alloy) está sustituyendo al Promtail oficialmente. Para setup nuevo, ve directo a Alloy. Para setup que ya corre Promtail hace tiempo, no hay urgencia en migrar — Promtail va a seguir funcionando por años.",[12,11651,11652,11655,11656,11658],{},[27,11653,11654],{},"¿OpenTelemetry encaja dónde en esa stack?","\nOTel es el estándar de instrumentación de aplicación que está consolidando. En lugar de usar ",[231,11657,11263],{}," directo, usas el SDK de OTel y él exporta a Prometheus, Loki y Tempo simultáneamente. La ventaja grande es portabilidad — si quieres cambiar Prometheus por otra cosa de aquí a 3 años, tu aplicación no cambia una línea. Para startup empezando hoy, recomendamos OTel desde el día uno.",[12,11660,11661,11664,11665,11668,11669,11672],{},[27,11662,11663],{},"¿Cómo hago backup de Prometheus?","\nPrometheus tiene snapshot vía API: ",[231,11666,11667],{},"curl -X POST localhost:9090\u002Fapi\u002Fv1\u002Fadmin\u002Ftsdb\u002Fsnapshot"," crea un snapshot en el directorio de datos. Hazlo una vez al día vía cron, haz ",[231,11670,11671],{},"tar.gz"," y envíalo a object storage. En caso de desastre, lo que pierdes son métricas — y métricas, diferente de logs, son típicamente recuperables en horas (vuelves a recolectar y los dashboards vuelven). Logs perdidos están perdidos para siempre, entonces invierte más en backup de Loki.",[12,11674,11675,11678],{},[27,11676,11677],{},"¿Tempo (traces distribuidos) vale la pena instalar ahora?","\nNo. Traces se vuelven útiles a partir del momento en que tienes 5+ servicios conversando entre sí y depurar latencia involucra seguir una request por varios hops. Para arquitectura monolítica o pocos servicios, traces dan trabajo desproporcional al valor. Agrégalos cuando la complejidad lo pida.",[12,11680,11681,11684],{},[27,11682,11683],{},"¿Loki indexa full-text como ELK?","\nNo, y esa es la feature, no bug. Loki indexa solo labels (job, host, container, severity) y el contenido del log queda comprimido sin índice. Para buscar texto, filtras por labels primero y después haces grep en los chunks resultantes. Eso es lo que vuelve a Loki diez veces más barato que ELK en RAM y CPU. A cambio, queries de texto libre en todo el historial son más lentas. Para 90% de los casos de debugging, filtrar por job + host + ventana de tiempo ya reduce a decenas de MB donde el grep vuela.",[19,11686,11688],{"id":11687},"proximos-pasos","Próximos pasos",[12,11690,11691],{},"¿Subiste la stack, tienes dashboard, tienes alerta, tienes log buscable? Bien. Las próximas tres cosas que valen la inversión son, en orden:",[67,11693,11694,11700,11714],{},[70,11695,11696,11699],{},[27,11697,11698],{},"Custom dashboards por aplicación"," — métricas de negocio (suscripciones creadas\u002Fhora, jobs procesados, cola de e-mails) en lugar de solo infraestructura.",[70,11701,11702,11705,11706,11709,11710,11713],{},[27,11703,11704],{},"Runbooks linkados en las alertas"," — toda regla en ",[231,11707,11708],{},"alerts.yml"," debe tener ",[231,11711,11712],{},"annotations.runbook_url"," apuntando a una página explicando qué hacer. Cuando la alerta dispare a las 3 de la mañana, el sueño no piensa.",[70,11715,11716,11719],{},[27,11717,11718],{},"Revisión mensual de alertas"," — 30 minutos una vez al mes auditando lo que disparó en el mes anterior, eliminando lo que se volvió ruido, ajustando thresholds.",[12,11721,11722,11723,11727,11728,101],{},"Para quien quiere ir más allá y entender por qué elegimos esta stack en lugar de SaaS gestionado, lee ",[3337,11724,11726],{"href":11725},"\u002Fes\u002Fblog\u002Fobservabilidad-sin-datadog-stack-startup","Observabilidad sin Datadog: la stack de la startup",". Y para cerrar el ciclo de operación — porque no sirve saber que la base cayó si no logras restaurar — vale la pena leer ",[3337,11729,11731],{"href":11730},"\u002Fes\u002Fblog\u002Fbackup-de-base-de-datos-en-cluster","Backup de base en cluster: estrategias para las 3 de la mañana",[12,11733,11734],{},"Si quieres saltarte ese montaje todo y correr la stack como job dentro de un orquestador que ya cuida de TLS, rolling update y replicación de volumen:",[224,11736,11737],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,11738,11739],{"__ignoreMap":229},[234,11740,11741,11743,11745,11747,11749],{"class":236,"line":237},[234,11742,1220],{"class":247},[234,11744,2958],{"class":251},[234,11746,5329],{"class":255},[234,11748,2964],{"class":383},[234,11750,2967],{"class":247},[12,11752,11753],{},"Cuatro horas se vuelven cuarenta minutos. El resto es el mismo trabajo de pensar qué alertas importan — y en esa parte nadie te libra.",[3351,11755,11756],{},"html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}",{"title":229,"searchDepth":244,"depth":244,"links":11758},[11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,11776],{"id":21,"depth":244,"text":22},{"id":8826,"depth":244,"text":8827},{"id":8886,"depth":244,"text":8887},{"id":8929,"depth":244,"text":8930},{"id":8986,"depth":244,"text":8987},{"id":9446,"depth":244,"text":9447},{"id":9770,"depth":244,"text":9771},{"id":9936,"depth":244,"text":9937},{"id":10414,"depth":244,"text":10415},{"id":10588,"depth":244,"text":10589},{"id":11197,"depth":244,"text":11198},{"id":11241,"depth":244,"text":11242},{"id":11344,"depth":244,"text":11345},{"id":11383,"depth":244,"text":11384},{"id":11443,"depth":244,"text":11444},{"id":11581,"depth":244,"text":11582},{"id":3225,"depth":244,"text":3226},{"id":11687,"depth":244,"text":11688},"2026-05-12","Tutorial honesto para subir métricas, logs y dashboards de tu cluster — en 4 horas, sin Datadog. Stack open-source que cabe en 1 VPS de R$80\u002Fmes.",{},"\u002Fes\u002Fblog\u002Fstack-monitoring-prometheus-grafana-loki",{"title":8779,"description":11778},{"loc":11780},"es\u002Fblog\u002Fstack-monitoring-prometheus-grafana-loki",[11785,11786,11787,11788,3393,3379],"prometheus","grafana","loki","monitoring","324n4tX2U_bO1GLljCpReEqIs6qn0hm9GJVO3FvHiGM",{"id":11791,"title":11792,"author":7,"body":11793,"category":3379,"cover":3380,"date":12743,"description":12744,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":12745,"navigation":411,"path":12746,"readingTime":4402,"seo":12747,"sitemap":12748,"stem":12749,"tags":12750,"__hash__":12755},"blog_es\u002Fes\u002Fblog\u002Fcloudflare-frente-a-cluster-auto-hospedado.md","CloudFlare frente al cluster auto-hospedado: ¿vale la pena en 2026?",{"type":9,"value":11794,"toc":12721},[11795,11798,11802,11805,11808,11811,11815,11818,11874,11877,11881,11884,12024,12027,12031,12034,12040,12046,12053,12056,12060,12063,12089,12096,12099,12119,12123,12126,12164,12167,12171,12174,12247,12266,12270,12273,12279,12285,12291,12297,12301,12304,12324,12327,12331,12534,12537,12541,12544,12564,12568,12571,12575,12581,12585,12588,12592,12595,12631,12634,12638,12641,12645,12648,12652,12659,12663,12666,12670,12673,12676,12692,12695,12698,12716,12719],[12,11796,11797],{},"La pregunta vuelve cada semana en un grupo de DevOps: \"subí mi cluster con tres servidores en DigitalOcean, ¿vale poner CloudFlare al frente?\". La respuesta corta es \"casi siempre sí\" — pero el \"casi\" carga trade-offs que nadie menciona hasta la primera vez que algo se rompe en producción y pasas dos horas depurando una regla de caché que enmascaró un 500 del app. Este post es la versión larga, con criterios mensurables, de la decisión que necesitas tomar antes de mover el nameserver.",[19,11799,11801],{"id":11800},"tldr-el-resumen-de-200-palabras","TL;DR — el resumen de 200 palabras",[12,11803,11804],{},"CloudFlare gratis se volvió estándar de hecho para cualquier site con tráfico: protege contra DDoS sin límite contractual, emite certificado SSL automático, cachea assets en más de 300 ciudades, esconde la IP de origen del servidor y aún entrega DNS con sub-10ms. Para cluster auto-hospedado — sea HeroCtl, Coolify, k3s o Docker Swarm — poner CloudFlare al frente es decisión fácil en cerca de 90% de los casos.",[12,11806,11807],{},"El 10% restante tiene trade-offs concretos: latencia adicional de 10 a 30ms en rutas dinámicas, TLS termina en CloudFlare por defecto (ya no es punta-a-punta hasta tu servidor), reglas de caché pueden enmascarar bugs sutiles en el app, y el lock-in crece conforme adoptas Workers, R2 y Pages.",[12,11809,11810],{},"Vale la pena cuando: quieres DDoS protection sin pagar; caché global para reducir coste de banda; esconder la IP del servidor de scanners. No vale cuando: cumplimiento financiero\u002Fsalud exige TLS verdaderamente punta-a-punta; necesitas p99 por debajo de 50ms en rutas dinámicas; el cluster ya tiene CDN edge interna en múltiples data centers. Cluster con router integrado ya cubre cerca de 60% de lo que CloudFlare ofrece — combinar los dos es el camino más común.",[19,11812,11814],{"id":11813},"que-ofrece-cloudflare-gratis-en-2026","¿Qué ofrece CloudFlare gratis en 2026?",[12,11816,11817],{},"La oferta gratuita aumentó de tamaño año a año. Hoy, el plan gratis cubre lo que era plan pagado de 2019:",[2735,11819,11820,11826,11832,11838,11844,11850,11856,11862,11868],{},[70,11821,11822,11825],{},[27,11823,11824],{},"DDoS protection sin límite contractual"," — Layer 3, 4 y 7. CloudFlare absorbe ataques de cientos de Gbps sin cobrar excedente.",[70,11827,11828,11831],{},[27,11829,11830],{},"Certificado SSL\u002FTLS automático"," — emitido en minutos por el propio CloudFlare, renovado automáticamente. Wildcard requiere plan Advanced Certificate Manager (US$ 10\u002Fmes).",[70,11833,11834,11837],{},[27,11835,11836],{},"CDN global"," — más de 300 ciudades en más de 120 países. Incluye São Paulo, Río, Fortaleza, Curitiba y Porto Alegre.",[70,11839,11840,11843],{},[27,11841,11842],{},"DNS authoritative"," — sub-10ms global medio, anycast, con APIs para automatización.",[70,11845,11846,11849],{},[27,11847,11848],{},"Bot protection básica"," — bloqueo de bots conocidos y desafíos JavaScript en tráfico sospechoso.",[70,11851,11852,11855],{},[27,11853,11854],{},"Caché de assets estáticos"," — extensiones reconocidas (CSS, JS, imágenes, fuentes) cacheadas por defecto.",[70,11857,11858,11861],{},[27,11859,11860],{},"Page Rules"," — tres reglas gratis para forzar HTTPS, caché extra, redirects.",[70,11863,11864,11867],{},[27,11865,11866],{},"Always Online"," — cuando el origen cae, CloudFlare sirve la última versión cacheada.",[70,11869,11870,11873],{},[27,11871,11872],{},"Web Analytics"," — métricas de RUM (visitas, países, navegadores), sin cookies.",[12,11875,11876],{},"La línea de corte es generosa lo suficiente para que un site de 10 mil visitantes\u002Fdía corra 100% en el gratis sin ningún problema operacional.",[19,11878,11880],{"id":11879},"y-que-cobra-cloudflare-extra","¿Y qué cobra CloudFlare extra?",[12,11882,11883],{},"Cuatro planes: Free, Pro (US$ 25\u002Fmes por dominio), Business (US$ 250\u002Fmes por dominio) y Enterprise (bajo consulta, en general por encima de US$ 5 mil\u002Fmes).",[119,11885,11886,11903],{},[122,11887,11888],{},[125,11889,11890,11893,11895,11898,11901],{},[128,11891,11892],{},"Recurso",[128,11894,7829],{},[128,11896,11897],{},"Pro US$ 25",[128,11899,11900],{},"Business US$ 250",[128,11902,4360],{},[141,11904,11905,11921,11935,11948,11962,11977,11990,12007],{},[125,11906,11907,11910,11912,11915,11918],{},[146,11908,11909],{},"WAF managed rulesets",[146,11911,3059],{},[146,11913,11914],{},"Sí (OWASP básico)",[146,11916,11917],{},"Sí (avanzado)",[146,11919,11920],{},"Custom",[125,11922,11923,11926,11928,11931,11933],{},[146,11924,11925],{},"Image Resizing",[146,11927,3059],{},[146,11929,11930],{},"Sí (US$ 5\u002FM)",[146,11932,3065],{},[146,11934,3065],{},[125,11936,11937,11940,11942,11944,11946],{},[146,11938,11939],{},"Polish (optimización de imagen)",[146,11941,3059],{},[146,11943,3065],{},[146,11945,3065],{},[146,11947,3065],{},[125,11949,11950,11953,11955,11958,11960],{},[146,11951,11952],{},"Argo Smart Routing",[146,11954,3059],{},[146,11956,11957],{},"US$ 5\u002Fmes add-on",[146,11959,3065],{},[146,11961,3065],{},[125,11963,11964,11967,11969,11972,11974],{},[146,11965,11966],{},"Page Rules incluidas",[146,11968,2699],{},[146,11970,11971],{},"20",[146,11973,5693],{},[146,11975,11976],{},"125+",[125,11978,11979,11982,11984,11986,11988],{},[146,11980,11981],{},"Cache Reserve",[146,11983,3059],{},[146,11985,3059],{},[146,11987,3065],{},[146,11989,3065],{},[125,11991,11992,11995,11998,12001,12004],{},[146,11993,11994],{},"Customer Support SLA",[146,11996,11997],{},"Best-effort",[146,11999,12000],{},"24h",[146,12002,12003],{},"Chat 24\u002F7",[146,12005,12006],{},"Ingeniero dedicado",[125,12008,12009,12012,12015,12018,12021],{},[146,12010,12011],{},"Análisis de logs",[146,12013,12014],{},"Última hora",[146,12016,12017],{},"Últimas 24h",[146,12019,12020],{},"Últimos 7 días",[146,12022,12023],{},"30 días",[12,12025,12026],{},"Workers y R2 tienen tier gratuito independiente del plan: 100 mil peticiones\u002Fdía para Workers, 10 GB de almacenamiento y 1 millón de operaciones Class A\u002Fmes para R2. Para un site marketing modesto, da para correr storage de imágenes en el R2 sin nunca llegar a la factura.",[19,12028,12030],{"id":12029},"cloudflare-anade-latencia","¿CloudFlare añade latencia?",[12,12032,12033],{},"La pregunta honesta. Respuesta también honesta: depende de la ruta.",[12,12035,12036,12039],{},[27,12037,12038],{},"Para rutas con caché"," (HTML estático, assets, imágenes optimizadas), CloudFlare reduce latencia. El usuario en Recife toma el contenido del POP de Fortaleza o São Paulo en 15 a 40ms, en vez de hacer round-trip hasta tu servidor en New Jersey o Frankfurt. Ahorro típico: 150 a 250ms por request.",[12,12041,12042,12045],{},[27,12043,12044],{},"Para rutas dinámicas"," (API, dashboard logado, checkout), el tráfico pasa por el proxy de CloudFlare antes de llegar a tu servidor. Eso añade entre 10 y 30ms en condiciones normales. El número exacto depende de cuál POP el usuario está conectado y dónde está el servidor de origen.",[12,12047,12048,12049,12052],{},"Medimos en el cluster público en producción: la media de tiempo de respuesta de ",[231,12050,12051],{},"manage.heroctl.com\u002Fv1\u002Fnodes"," es de 38ms sin proxy CloudFlare y 51ms con proxy activado, requiriendo del mismo notebook en São Paulo. Un delta de 13ms — perceptible en benchmark, invisible para humano.",[12,12054,12055],{},"La latencia solo es dealbreaker en tres escenarios reales: juegos online, subasta financiera de alta frecuencia, y cargas WebSocket de baja latencia (trading, colaboración en vivo). Para el resto, los 13ms desaparecen en el tiempo de render del navegador.",[19,12057,12059],{"id":12058},"cloudflare-rompe-tls-punta-a-punta","¿CloudFlare rompe TLS punta-a-punta?",[12,12061,12062],{},"Por defecto, sí. Mira los modos:",[2735,12064,12065,12071,12077,12083],{},[70,12066,12067,12070],{},[27,12068,12069],{},"Flexible"," (NUNCA uses esto) — TLS solo entre cliente y CloudFlare. Conexión CloudFlare → servidor es HTTP puro. Vulnerable a interceptación en la pierna interna.",[70,12072,12073,12076],{},[27,12074,12075],{},"Full"," — TLS entre cliente y CloudFlare, y separadamente entre CloudFlare y servidor. Pero CloudFlare acepta certificado inválido\u002Fauto-firmado en el servidor. Riesgo de man-in-the-middle entre CloudFlare y el origen.",[70,12078,12079,12082],{},[27,12080,12081],{},"Full (strict)"," — TLS en ambas piernas, y CloudFlare exige certificado válido en el origen. Esta es la configuración mínima razonable.",[70,12084,12085,12088],{},[27,12086,12087],{},"Strict (SSL-Only Origin Pull)"," — CloudFlare verifica que el certificado del origen fue emitido por una CA pública y válida para el hostname. Más seguro que Full strict.",[12,12090,12091,12092,12095],{},"En todos esos modos, ",[27,12093,12094],{},"CloudFlare descifra el tráfico en el medio del camino",". Ven cuerpo de request, headers, cookies — todo. Para la mayoría de los casos eso es aceptable (el contrato con CloudFlare es claro), pero en cumplimiento estricto (salud, financiero, gobierno) puede romper requisito de auditoría.",[12,12097,12098],{},"La salida real para punta-a-punta:",[2735,12100,12101,12107,12113],{},[70,12102,12103,12106],{},[27,12104,12105],{},"Authenticated Origin Pulls"," — CloudFlare presenta un certificado cliente cuando conecta a tu origen; el servidor solo acepta conexiones de esa cadena. Sigue descifrando en el medio, pero al menos solo CloudFlare consigue llegar a tu origen.",[70,12108,12109,12112],{},[27,12110,12111],{},"CloudFlare Tunnel + cliente mTLS en la punta"," — para apps internas, Tunnel sustituye IP público y exige certificado de cliente.",[70,12114,12115,12118],{},[27,12116,12117],{},"Gray cloud (DNS only)"," — desactiva el proxy. Pierdes DDoS protection, caché, WAF — pero ganas conexión directa cliente-servidor con TLS verdaderamente punta-a-punta. Es una opción válida cuando cumplimiento manda.",[19,12120,12122],{"id":12121},"voy-a-quedar-lock-in-con-cloudflare","¿Voy a quedar lock-in con CloudFlare?",[12,12124,12125],{},"Depende exclusivamente de qué features adoptas. Vamos por capa:",[2735,12127,12128,12134,12140,12146,12152,12158],{},[70,12129,12130,12133],{},[27,12131,12132],{},"DNS"," — trivialmente reversible. Mover nameserver toma 24 a 48h de propagación y nada se rompe. Lock-in cero.",[70,12135,12136,12139],{},[27,12137,12138],{},"Proxy + caché + WAF"," — reversible en horas. Desactivas el orange cloud, ajustas DNS para apuntar directo al servidor, reconfiguras WAF en tu origen (si la hay). Lock-in bajo.",[70,12141,12142,12145],{},[27,12143,12144],{},"Workers"," — lock-in real. La API de Workers es propietaria; reescribir para Lambda@Edge o Fastly Compute@Edge cuesta de días a semanas dependiendo del código. No es el peor caso, pero cuenta con re-trabajo.",[70,12147,12148,12151],{},[27,12149,12150],{},"R2 Object Storage"," — API compatible con S3, así que código sigue funcionando. Pero R2 no cobra egress (S3 cobra US$ 0,09\u002FGB), entonces mover a otro proveedor encarece la cuenta. Lock-in económico, no técnico.",[70,12153,12154,12157],{},[27,12155,12156],{},"Pages"," — lock-in moderado. Build process es custom; rewrite para Vercel\u002FNetlify\u002Fstatic host genérico toma una tarde, pero exige.",[70,12159,12160,12163],{},[27,12161,12162],{},"Zero Trust"," — lock-in alto. Políticas, identidad, túneles: rewrite completo para Tailscale\u002FTwingate\u002Fequivalente.",[12,12165,12166],{},"La recomendación operacional es: usa el core CloudFlare (DNS + proxy + WAF + Page Rules) sin titubear — puedes revertir en un día. Adopta Workers\u002FR2\u002FPages solo con consciencia clara de que estás aceptando lock-in proporcional al valor que aquella feature entrega.",[19,12168,12170],{"id":12169},"configuracion-minima-recomendada-para-cluster-auto-hospedado","Configuración mínima recomendada para cluster auto-hospedado",[12,12172,12173],{},"Secuencia práctica, sin secreto:",[67,12175,12176,12182,12191,12201,12207,12213,12219,12229,12235,12241],{},[70,12177,12178,12181],{},[27,12179,12180],{},"Crea cuenta en CloudFlare"," y añade el dominio. El site va a escanear tus DNS records actuales y copiarlos a la nueva zona.",[70,12183,12184,12187,12188,101],{},[27,12185,12186],{},"Cambia los nameservers"," en el registrar (Hostinger, Registro.br, GoDaddy, donde quiera que esté). Espera de 4 a 48 horas por la propagación. Verifica con ",[231,12189,12190],{},"dig NS heroctl.com +short",[70,12192,12193,12196,12197,12200],{},[27,12194,12195],{},"DNS records del cluster",": crea un registro A para el dominio raíz apuntando al IP del servidor que recibe tráfico, y un registro A wildcard ",[231,12198,12199],{},"*"," apuntando al mismo IP. Marca ambos con proxy activado (orange cloud).",[70,12202,12203,12206],{},[27,12204,12205],{},"SSL\u002FTLS mode",": configura Full (strict). Eso exige que el cluster tenga un certificado válido. El router integrado de HeroCtl emite Let's Encrypt automáticamente — funciona out-of-the-box.",[70,12208,12209,12212],{},[27,12210,12211],{},"Always Use HTTPS",": ON. Redirige cualquier HTTP a HTTPS en el borde.",[70,12214,12215,12218],{},[27,12216,12217],{},"HSTS",": 6 meses, include subdomains, sin preload por ahora. Preload es decisión definitiva — no se puede deshacer rápido si algo se rompe.",[70,12220,12221,12224,12225,12228],{},[27,12222,12223],{},"Page Rule de caché"," para assets estáticos: ",[231,12226,12227],{},"*heroctl.com\u002Fstatic\u002F*"," → Cache Level: Cache Everything, Edge Cache TTL: 1 mes.",[70,12230,12231,12234],{},[27,12232,12233],{},"WAF managed ruleset"," (Pro+): activa el CloudFlare Managed Ruleset y el OWASP Core Rule Set en modo Block para reglas de score alto.",[70,12236,12237,12240],{},[27,12238,12239],{},"Security Level",": Medium. Low deja pasar bot demasiado; High desafía gente legítima.",[70,12242,12243,12246],{},[27,12244,12245],{},"Bot Fight Mode",": ON en el plan gratis. Controla scrapers básicos sin pedir CAPTCHA al humano.",[12,12248,12249,12250,12253,12254,12257,12258,12261,12262,12265],{},"Después de aplicar todo eso, corre ",[231,12251,12252],{},"curl -I https:\u002F\u002Ftudominio.com"," y confirma: header ",[231,12255,12256],{},"cf-ray"," presente, header ",[231,12259,12260],{},"server: cloudflare",", header ",[231,12263,12264],{},"strict-transport-security"," con max-age largo.",[19,12267,12269],{"id":12268},"cuando-no-vale-cloudflare","¿Cuándo NO vale CloudFlare?",[12,12271,12272],{},"Cuatro escenarios donde la recomendación cambia. Importan más de lo que parecen.",[12,12274,12275,12278],{},[27,12276,12277],{},"Cluster con CDN\u002Fedge interna robusta."," Si ya corres en cuatro o cinco regiones geográficamente esparcidas, con balanceo DNS por proximidad y caché local en cada región, la CDN de CloudFlare añade latencia sin ganancia. Vale correr gray cloud (solo DNS) y mantener el resto directo.",[12,12280,12281,12284],{},[27,12282,12283],{},"Cumplimiento financiero o de salud con mTLS punta-a-punta obligatorio."," La LGPD por sí sola no exige eso; pero auditorías específicas (PCI-DSS Level 1 con requisitos custom, certificaciones HIPAA estrictas, frameworks bancarios) pueden exigir que tráfico cifrado nunca sea descifrado en tercero. Como CloudFlare descifra en el medio del camino, no pasa.",[12,12286,12287,12290],{},[27,12288,12289],{},"Apps puramente internas (intranet\u002FSaaS B2B cerrado)."," CloudFlare Free no cubre Zero Trust avanzado. Para app que sirve exclusivamente a empleados, Tailscale o WireGuard nativo entregan más con menos.",[12,12292,12293,12296],{},[27,12294,12295],{},"Sites pequeños sin tráfico y sin enemigo público."," Blog personal de 200 visitas\u002Fmes, sin formulario de pago, sin datos sensibles. DNS directo en Hostinger\u002FRegistro.br + Let's Encrypt del router integrado sirve perfectamente. Añadir CloudFlare es ceremonia innecesaria.",[19,12298,12300],{"id":12299},"como-cloudflare-interactua-con-cluster-de-alta-disponibilidad","¿Cómo CloudFlare interactúa con cluster de alta disponibilidad?",[12,12302,12303],{},"Aquí el diseño importa. Cluster con tres o más nodos sirve tráfico en todos ellos — no tiene nodo \"principal\" único. La configuración pragmática es:",[2735,12305,12306,12312,12318],{},[70,12307,12308,12311],{},[27,12309,12310],{},"DNS round-robin con salud",": registra A records para el IP de todos los nodos que corren el router. CloudFlare hace health check (Pro+) y remueve nodo roto de la rotación automáticamente.",[70,12313,12314,12317],{},[27,12315,12316],{},"Failover de CloudFlare",": ~30 segundos para detectar nodo muerto y sacarlo de la rotación (configurable hasta 5 segundos en el Enterprise).",[70,12319,12320,12323],{},[27,12321,12322],{},"Failover interno del cluster",": el router integrado de HeroCtl re-enruta tráfico entre nodos saludables en cerca de 5 segundos. Elección de nuevo coordinador ocurre en ~7 segundos cuando el nodo-líder cae.",[12,12325,12326],{},"Combinado, downtime real percibido por el usuario queda por debajo de 40 segundos en el peor caso (CloudFlare detecta + cluster reacciona). Sin CloudFlare, queda en ~7 segundos (cluster solo). Con CloudFlare y configuración de monitorización agresiva (Pro+), vuelve a ~10 segundos. La elección es clara: si no necesitas DDoS protection, el cluster solo ya es más rápido. Si necesitas, CloudFlare añade 30s de detección a cambio de protección contra ataque.",[19,12328,12330],{"id":12329},"tabla-comparativa-12-criterios-de-decision","Tabla comparativa: 12 criterios de decisión",[119,12332,12333,12351],{},[122,12334,12335],{},[125,12336,12337,12339,12342,12345,12348],{},[128,12338,2983],{},[128,12340,12341],{},"Sin CloudFlare",[128,12343,12344],{},"CF Free",[128,12346,12347],{},"CF Pro US$ 25",[128,12349,12350],{},"CF Business US$ 250",[141,12352,12353,12369,12386,12403,12419,12432,12447,12462,12477,12489,12501,12517],{},[125,12354,12355,12358,12361,12364,12366],{},[146,12356,12357],{},"DDoS Layer 3\u002F4",[146,12359,12360],{},"Te las arreglas",[146,12362,12363],{},"Ilimitado",[146,12365,12363],{},[146,12367,12368],{},"Ilimitado + SLA",[125,12370,12371,12374,12377,12380,12383],{},[146,12372,12373],{},"DDoS Layer 7",[146,12375,12376],{},"No tiene",[146,12378,12379],{},"Básico",[146,12381,12382],{},"Avanzado",[146,12384,12385],{},"Avanzado + Custom Rules",[125,12387,12388,12391,12394,12397,12400],{},[146,12389,12390],{},"Latencia adicional en rutas dinámicas",[146,12392,12393],{},"0ms",[146,12395,12396],{},"+13 a 30ms",[146,12398,12399],{},"+10 a 25ms (Argo opcional)",[146,12401,12402],{},"+5 a 15ms (Argo incluido)",[125,12404,12405,12408,12411,12414,12416],{},[146,12406,12407],{},"Caché global de estáticos",[146,12409,12410],{},"Lo montas",[146,12412,12413],{},"300+ ciudades",[146,12415,12413],{},[146,12417,12418],{},"300+ ciudades + Reserve",[125,12420,12421,12424,12426,12428,12430],{},[146,12422,12423],{},"Esconde IP del servidor",[146,12425,3059],{},[146,12427,3065],{},[146,12429,3065],{},[146,12431,3065],{},[125,12433,12434,12437,12439,12442,12444],{},[146,12435,12436],{},"TLS punta-a-punta verdadero",[146,12438,3065],{},[146,12440,12441],{},"No (descifra)",[146,12443,3059],{},[146,12445,12446],{},"No (pero Origin Pulls)",[125,12448,12449,12452,12454,12456,12459],{},[146,12450,12451],{},"WAF managed",[146,12453,12376],{},[146,12455,3059],{},[146,12457,12458],{},"OWASP básico",[146,12460,12461],{},"OWASP avanzado",[125,12463,12464,12467,12469,12471,12474],{},[146,12465,12466],{},"Bot protection",[146,12468,12410],{},[146,12470,12245],{},[146,12472,12473],{},"Super Bot Fight",[146,12475,12476],{},"Bot Management ML",[125,12478,12479,12481,12483,12485,12487],{},[146,12480,11860],{},[146,12482,3056],{},[146,12484,2699],{},[146,12486,11971],{},[146,12488,5693],{},[125,12490,12491,12493,12495,12497,12499],{},[146,12492,11866],{},[146,12494,3059],{},[146,12496,3065],{},[146,12498,3065],{},[146,12500,3065],{},[125,12502,12503,12506,12509,12511,12514],{},[146,12504,12505],{},"Coste mensual por dominio",[146,12507,12508],{},"US$ 0",[146,12510,12508],{},[146,12512,12513],{},"US$ 25",[146,12515,12516],{},"US$ 250",[125,12518,12519,12522,12525,12528,12531],{},[146,12520,12521],{},"Lock-in proporcional",[146,12523,12524],{},"Cero",[146,12526,12527],{},"Bajo (DNS+proxy)",[146,12529,12530],{},"Bajo a medio",[146,12532,12533],{},"Medio (Workers\u002FR2 empiezan a entrar)",[12,12535,12536],{},"La línea que decide para la mayoría es \"DDoS Layer 7 + esconde IP\". Esos dos solos justifican el plan gratis. Las líneas pagadas solo tienen sentido con tráfico voluminoso o requisito formal de WAF.",[19,12538,12540],{"id":12539},"cloudflare-gratis-tiene-limite-de-trafico","¿CloudFlare gratis tiene límite de tráfico?",[12,12542,12543],{},"No hay límite contractual de banda en el plan gratis para tráfico web normal a través del proxy. Pero existen tres límites prácticos que vale mencionar:",[2735,12545,12546,12552,12558],{},[70,12547,12548,12551],{},[27,12549,12550],{},"Section 2.8 de los Terms of Service",": el plan gratis es para sites cuyo contenido principal es HTML, y CloudFlare se reserva el derecho de pedir upgrade si usas el servicio primariamente para servir vídeo o archivos grandes. En la práctica, raramente accionan — pero si te vuelves un host de vídeos pirateados de 50TB\u002Fmes, espera recibir email.",[70,12553,12554,12557],{},[27,12555,12556],{},"Workers gratis",": 100 mil peticiones\u002Fdía. Por encima de eso, Workers Paid (US$ 5\u002Fmes) con 10M peticiones incluidas.",[70,12559,12560,12563],{},[27,12561,12562],{},"R2 gratis",": 10GB de almacenamiento, 1M Class A operations\u002Fmes, 10M Class B operations\u002Fmes. Por encima, US$ 0,015\u002FGB-mes.",[19,12565,12567],{"id":12566},"puedo-usar-cloudflare-dns-sin-el-proxy","¿Puedo usar CloudFlare DNS sin el proxy?",[12,12569,12570],{},"Sí — modo \"DNS only\" (gray cloud). Usas el DNS de CloudFlare (rápido, free, anycast global) pero tráfico va directo a tu servidor sin pasar por el proxy. Pierdes DDoS, caché, WAF, IP hiding — mantienes solo la infraestructura DNS. Útil cuando: cumplimiento prohíbe descifrado en tercero; solo quieres DNS rápido sin tocar el path del tráfico; estás probando antes de activar el proxy.",[19,12572,12574],{"id":12573},"waf-gratis-bloquea-sql-injection","¿WAF gratis bloquea SQL injection?",[12,12576,12577,12578,12580],{},"CloudFlare Free tiene ",[27,12579,12245],{}," y reglas automáticas de mitigación para patrones obvios, pero no tiene el Managed Ruleset OWASP completo. Para bloqueo confiable de SQL injection, XSS, RCE patterns conocidos, necesitas el plan Pro o superior. Alternativa: correr ModSecurity o WAF propio en tu origen — funciona, pero añade CPU y configuración.",[19,12582,12584],{"id":12583},"cloudflare-tiene-datacenter-en-brasil","¿CloudFlare tiene datacenter en Brasil?",[12,12586,12587],{},"Sí. En 2026 son cinco POPs brasileños: São Paulo (dos POPs), Río de Janeiro, Fortaleza, Curitiba y Porto Alegre. Latencia típica de cualquier ciudad del Sudeste a un POP queda por debajo de 20ms. El POP de Fortaleza atiende muy bien el Nordeste por causa de los cables submarinos que aterrizan ahí (EllaLink, Monet, GlobeNet). Para el Norte, aún es camino más largo — Manaus llega a Fortaleza en 80 a 120ms.",[19,12589,12591],{"id":12590},"como-migrar-nameservers-de-hostinger-a-cloudflare","¿Cómo migrar nameservers de Hostinger a CloudFlare?",[12,12593,12594],{},"Cuatro pasos. Tarda menos de una hora activa, más hasta 48h de propagación:",[67,12596,12597,12603,12615,12621],{},[70,12598,12599,12602],{},[27,12600,12601],{},"CloudFlare",": añade el dominio. El wizard escanea tus DNS actuales y crea los records correspondientes en la nueva zona. Confirma que copió todo — MX, TXT (SPF\u002FDKIM\u002FDMARC), CNAME, A. Errores de copia aquí causan email derribado por una semana.",[70,12604,12605,12607,12608,2403,12611,12614],{},[27,12606,12601],{},": te da dos nameservers (algo como ",[231,12609,12610],{},"kim.ns.cloudflare.com",[231,12612,12613],{},"walt.ns.cloudflare.com","). Anota.",[70,12616,12617,12620],{},[27,12618,12619],{},"Hostinger",": panel → Dominios → tu dominio → Nameservers → \"Use custom nameservers\" → pega los dos de CloudFlare. Guarda.",[70,12622,12623,12626,12627,12630],{},[27,12624,12625],{},"Aguarda propagación",". Verifica con ",[231,12628,12629],{},"dig NS tudominio.com +short",". Cuando aparezcan los nameservers de CloudFlare, el dominio está bajo gestión de ellos. Records DNS siguen siendo editados en el panel de CloudFlare de ahí en adelante.",[12,12632,12633],{},"Importante: mientras la propagación ocurre, parte de los usuarios aún resuelve vía Hostinger. No apagues la zona vieja hasta confirmar que 100% de los resolvers ya cambiaron (24 a 48 horas es seguro).",[19,12635,12637],{"id":12636},"tls-termina-donde-e2e-se-rompe","¿TLS termina dónde? ¿E2E se rompe?",[12,12639,12640],{},"En modo proxy (orange cloud), TLS termina en CloudFlare. Re-establecen otra conexión TLS a tu servidor (en modo Full strict). Técnicamente: descifra, procesa, re-cifra. Para punta-a-punta verdadero: gray cloud (DNS only) o CloudFlare Tunnel con configuración custom. Para la mayoría de las aplicaciones, \"TLS verdaderamente punta-a-punta\" es menos importante de lo que parece — el ataque que eso protege (interceptación en el medio de la red) requiere atacante ya dentro de la red de CloudFlare, escenario poco realista.",[19,12642,12644],{"id":12643},"cloudflare-workers-vs-serverless-de-mi-cloud-cuando-vale","¿CloudFlare Workers vs serverless de mi cloud — cuándo vale?",[12,12646,12647],{},"Workers son buenos para: edge computing donde latencia \u003C50ms importa (geo-routing, A\u002FB testing, rewrite de header); transformación liviana de request\u002Fresponse; auth en el borde (validar JWT antes de llegar al origen). No son buenos para: workload con más de 30 segundos de runtime; integración heavy con bases relacionales (latencia de cold start de DB driver mata); código que necesita bibliotecas que dependen de filesystem o proceso. Lambda de AWS sigue mejor para workload de runtime largo; Workers ganan en el borde. Usa ambos, no sustituyas uno por el otro.",[19,12649,12651],{"id":12650},"puedo-usar-cloudflare-r2-con-cluster-auto-hospedado","¿Puedo usar CloudFlare R2 con cluster auto-hospedado?",[12,12653,12654,12655,12658],{},"Sí — R2 es S3-compatible en la API. Tu app usa ",[231,12656,12657],{},"aws-sdk"," configurado con endpoint de R2 y credenciales R2; código sigue igual. Ventaja económica: cero egress fee. Puedes servir descargas pesadas (instaladores, vídeos de producto, backups) directo del R2 sin pagar por banda saliendo. Desventaja: durabilidad documentada es 99.999999999% (11 nueves), misma del S3, pero histórico operacional del R2 es más corto. Para hot path crítico, algunos equipos prefieren mantener S3 y usar R2 solo para cold storage y static delivery.",[19,12660,12662],{"id":12661},"origen-cayo-always-online-resuelve","¿Origen cayó — Always Online resuelve?",[12,12664,12665],{},"En parte. Always Online sirve la última versión cacheada de páginas HTML cuando el servidor está fuera. Pero: solo funciona para rutas que estaban siendo cacheadas; solo sirve la versión estática (sin datos dinámicos actualizados); solo dura mientras CloudFlare mantiene el snapshot (generalmente algunos días). Es una red de seguridad buena para blog estático y marketing. No sustituye alta disponibilidad real del cluster — para app dinámico, lo que resuelve es el cluster tener tres nodos y elección automática cuando uno cae.",[19,12667,12669],{"id":12668},"cerrando-combinando-cloudflare-con-cluster-auto-hospedado","Cerrando — combinando CloudFlare con cluster auto-hospedado",[12,12671,12672],{},"La combinación que recomendamos para 90% de los casos es: cluster auto-hospedado con tres o más nodos (alta disponibilidad real) + CloudFlare Free en el borde (DDoS, caché, IP hiding). El cluster cuida del enrutamiento interno, certificados automáticos, failover entre nodos en segundos. CloudFlare cuida de protección pública, caché global y ofuscación de IP. Las dos capas se complementan — no compiten.",[12,12674,12675],{},"Para empezar desde cero con esa combinación:",[224,12677,12678],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,12679,12680],{"__ignoreMap":229},[234,12681,12682,12684,12686,12688,12690],{"class":236,"line":237},[234,12683,1220],{"class":247},[234,12685,2958],{"class":251},[234,12687,5329],{"class":255},[234,12689,2964],{"class":383},[234,12691,2967],{"class":247},[12,12693,12694],{},"Te quedas con cluster funcional en tres nodos, certificado Let's Encrypt automático en el dominio que elijas, panel web para enviar jobs, alta disponibilidad real. Después, añades CloudFlare Free al frente del dominio y configuras conforme la sección \"Configuración mínima\" de este post. Total de tiempo: una tarde.",[12,12696,12697],{},"Más lectura en esta línea:",[2735,12699,12700,12710],{},[70,12701,12702,12705,12706,12709],{},[3337,12703,12704],{"href":3344},"Deploy Docker en producción: del compose al cluster"," — cómo salir del ",[231,12707,12708],{},"docker compose up"," y llegar a alta disponibilidad real, con los pasos intermedios.",[70,12711,12712,12715],{},[3337,12713,12714],{"href":11725},"Observabilidad sin DataDog: stack para startup"," — métricas, logs y tracing sin pagar US$ 2.000\u002Fmes de SaaS de observabilidad.",[12,12717,12718],{},"CloudFlare es una de las pocas herramientas donde el tier gratis es tan bueno que rechazarlo es terquedad. Pero como toda elección de infra, la parte difícil es entender exactamente dónde está la frontera — y, principalmente, dónde pasa por dentro del tráfico cifrado de tu aplicación.",[3351,12720,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":12722},[12723,12724,12725,12726,12727,12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742],{"id":11800,"depth":244,"text":11801},{"id":11813,"depth":244,"text":11814},{"id":11879,"depth":244,"text":11880},{"id":12029,"depth":244,"text":12030},{"id":12058,"depth":244,"text":12059},{"id":12121,"depth":244,"text":12122},{"id":12169,"depth":244,"text":12170},{"id":12268,"depth":244,"text":12269},{"id":12299,"depth":244,"text":12300},{"id":12329,"depth":244,"text":12330},{"id":12539,"depth":244,"text":12540},{"id":12566,"depth":244,"text":12567},{"id":12573,"depth":244,"text":12574},{"id":12583,"depth":244,"text":12584},{"id":12590,"depth":244,"text":12591},{"id":12636,"depth":244,"text":12637},{"id":12643,"depth":244,"text":12644},{"id":12650,"depth":244,"text":12651},{"id":12661,"depth":244,"text":12662},{"id":12668,"depth":244,"text":12669},"2026-05-08","CloudFlare gratis bloquea DDoS, cachea estático y esconde la IP del servidor. Pero añade latencia, lock-in y features que tal vez no uses. Cuándo vale y cuándo es overkill.",{},"\u002Fes\u002Fblog\u002Fcloudflare-frente-a-cluster-auto-hospedado",{"title":11792,"description":12744},{"loc":12746},"es\u002Fblog\u002Fcloudflare-frente-a-cluster-auto-hospedado",[12751,12752,12753,12754,3379],"cloudflare","cdn","ddos","performance","anNMR0LCPmSxGr2HA6KuK6H9TYKnYL7Z73S9z0DPL44",{"id":12757,"title":12758,"author":7,"body":12759,"category":3379,"cover":3380,"date":13838,"description":13839,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":13840,"navigation":411,"path":13841,"readingTime":4402,"seo":13842,"sitemap":13843,"stem":13844,"tags":13845,"__hash__":13849},"blog_es\u002Fes\u002Fblog\u002Fsentry-auto-hospedado-vs-saas-cuanto-se-ahorra.md","Sentry auto-hospedado vs SaaS: cuánto se ahorra realmente",{"type":9,"value":12760,"toc":13822},[12761,12764,12767,12771,12786,12797,12808,12814,12818,12821,12865,12868,12872,12875,12880,12890,12893,12898,12917,12920,12925,12944,12947,12950,12954,12961,13088,13095,13106,13110,13121,13169,13175,13179,13182,13192,13197,13211,13218,13223,13243,13248,13268,13271,13275,13278,13334,13337,13367,13374,13376,13550,13554,13557,13563,13569,13575,13581,13585,13588,13594,13600,13606,13609,13613,13616,13636,13639,13643,13646,13681,13684,13686,13696,13706,13712,13718,13727,13748,13754,13764,13766,13769,13772,13783,13786,13789,13805,13808,13820],[12,12762,12763],{},"La pregunta llega casi todas las semanas a la bandeja de entrada de quien acompaña el blog: ¿vale la pena dejar Sentry SaaS y auto-hospedar? La respuesta honesta empieza con un \"depende\" — y la mayor parte del contenido que circula sobre el tema trata el \"depende\" como si fuera evasiva. No lo es. Existen tres variables duras que deciden la cuenta — volumen de eventos, capacidad operacional del equipo y exigencia de compliance — y cada una de ellas tiene un número que consigues medir antes de tomar la decisión.",[12,12765,12766],{},"Este post es la versión larga de la respuesta. Si eres CTO de una startup en la etapa entre cinco y cincuenta ingenieros, leyendo la factura de Sentry subir mes a mes, lo que viene abajo sirve como una calculadora explicada — no como sermón a favor o en contra de auto-hospedado. Al final tiene una tabla con doce criterios, una sección de FAQ para preguntas que no cupieron en el cuerpo del texto, y tres perfiles bien definidos de cuándo cada camino tiene sentido.",[19,12768,12770],{"id":12769},"tldr-version-de-30-segundos","TL;DR — versión de 30 segundos",[12,12772,12773,12774,12777,12778,12781,12782,12785],{},"Sentry SaaS empieza en ",[27,12775,12776],{},"US$26\u002Fmes"," en el plan Team — cubre 50 mil errores\u002Fmes y cinco usuarios. Para startup con tráfico serio, la cuenta sube rápido al rango de ",[27,12779,12780],{},"US$80–200\u002Fmes"," (R$400–1.000\u002Fmes al cambio de R$5\u002FUSD), y en scale-up llega tranquilamente en ",[27,12783,12784],{},"US$300–500\u002Fmes"," (R$1,5k–2,5k\u002Fmes). Es predecible y no pide nada al equipo más allá de la tarjeta de crédito.",[12,12787,12788,12789,12792,12793,12796],{},"Auto-hospedado es \"open-source gratuito\" en el marketing, pero el software corre ",[27,12790,12791],{},"diez a doce contenedores"," — PostgreSQL, Redis, Kafka, ZooKeeper, ClickHouse, Symbolicator y cuatro procesos Sentry distintos. Pide entre ",[27,12794,12795],{},"8 GB de RAM y 4 vCPUs"," en un servidor dedicado, más almacenamiento, backup, actualizaciones trimestrales y el tiempo del dev que cuida de eso todo.",[12,12798,12799,12800,12803,12804,12807],{},"Vale auto-hospedar cuando: (a) volumen pasó de ",[27,12801,12802],{},"1 millón de errores\u002Fmes"," y la factura SaaS empezó a doler, (b) el equipo tiene capacidad operacional para cuidar de stack complejo sin volverse cuello de botella, o (c) compliance exige datos en servidor propio. ",[27,12805,12806],{},"No vale"," para equipo de una a tres personas enfocado en producto, o volumen bajo donde el SaaS es solo ruido de presupuesto.",[12,12809,12810,12813],{},[27,12811,12812],{},"Término medio interesante:"," GlitchTip — open-source MIT, compatible con el Sentry SDK existente, corre en Postgres + Redis (sin Kafka, sin ClickHouse, sin ZooKeeper). Cubre 80% del valor de Sentry con 20% del overhead operacional.",[19,12815,12817],{"id":12816},"lo-que-sentry-saas-hace-bien","Lo que Sentry SaaS hace bien",[12,12819,12820],{},"Antes de discutir coste, vale la pena reconocer por qué estás pagando. Sentry hospedado entrega una combinación que es difícil de reproducir en casa sin invertir varios trimestres del equipo:",[2735,12822,12823,12829,12835,12841,12847,12853,12859],{},[70,12824,12825,12828],{},[27,12826,12827],{},"Stack pre-configurada."," Creas cuenta, instalas el SDK en la aplicación, y en quince minutos tienes errores llegando. Cero servidor, cero archivo de configuración, cero backup para agendar.",[70,12830,12831,12834],{},[27,12832,12833],{},"Performance Monitoring integrado."," Tracing distribuido, n+1 queries detection, slow database queries — todo en el mismo dashboard donde ya estás mirando los errores.",[70,12836,12837,12840],{},[27,12838,12839],{},"Session Replay."," Grabación anonimizada de la sesión del usuario hasta el momento del error. Vale oro para debugar escenarios que no se reproducen en dev.",[70,12842,12843,12846],{},[27,12844,12845],{},"Alerting maduro."," Integración con Slack, PagerDuty, Microsoft Teams, e-mail y webhooks. Reglas finas — alerta solo cuando tasa de error duplica en 5 minutos, solo en producción, solo para usuarios autenticados.",[70,12848,12849,12852],{},[27,12850,12851],{},"Issue tracking + sync."," Linka issue al Linear\u002FJira\u002FGitHub Issues automáticamente. Resuelve del lado del tracker, cierra del lado de Sentry.",[70,12854,12855,12858],{},[27,12856,12857],{},"Continuous Profiling."," Profile en producción sin overhead perceptible, descubriendo cuellos de botella de CPU sin necesidad de reproducir localmente. Disponible solo en la versión SaaS — auto-hospedado aún no soporta.",[70,12860,12861,12864],{},[27,12862,12863],{},"Soporte técnico."," Dependiendo del plan, equipo humano respondiendo en hasta cuatro horas útiles.",[12,12866,12867],{},"Ese paquete entero cuesta US$26\u002Fmes en el plan de entrada. Para un equipo de tres personas empezando un SaaS, es literalmente el mejor uso de R$130\u002Fmes que existe en la estantería.",[19,12869,12871],{"id":12870},"la-cuenta-saas-linea-por-linea","La cuenta SaaS, línea por línea",[12,12873,12874],{},"La trampa de Sentry SaaS no es el precio de entrada — es la curva. Vamos a detallar para startup en tres etapas distintas:",[12,12876,12877],{},[27,12878,12879],{},"Etapa 1 — primer producto, R$10–30k MRR.",[2735,12881,12882,12885],{},[70,12883,12884],{},"Plan Team: US$26\u002Fmes (50 mil errores\u002Fmes, 5 usuarios)",[70,12886,12887,12888],{},"Total: ",[27,12889,6727],{},[12,12891,12892],{},"Esa es el rango en que nadie debería estar pensando en auto-hospedado. R$130\u002Fmes es casi ruido de presupuesto — gastar cuatro horas del CTO instalando infraestructura de monitoreo cuesta más que dos años de suscripción.",[12,12894,12895],{},[27,12896,12897],{},"Etapa 2 — producto creciendo, R$50–100k MRR.",[2735,12899,12900,12903,12906,12909,12912],{},[70,12901,12902],{},"Plan Business: US$80\u002Fmes (300 mil errores\u002Fmes incluidos)",[70,12904,12905],{},"Performance events extras: US$15–30\u002Fmes",[70,12907,12908],{},"Session Replay: US$25–50\u002Fmes",[70,12910,12911],{},"Usuarios adicionales (10 devs): US$50\u002Fmes",[70,12913,12887,12914],{},[27,12915,12916],{},"US$170–210\u002Fmes = R$850–1.050\u002Fmes",[12,12918,12919],{},"Aquí la factura empieza a aparecer en el reporte financiero mensual. No duele aún, pero notas.",[12,12921,12922],{},[27,12923,12924],{},"Etapa 3 — scale-up, R$200k+ MRR, 20+ ingenieros.",[2735,12926,12927,12930,12933,12936,12939],{},[70,12928,12929],{},"Plan Business con ajustes: US$200–300\u002Fmes base",[70,12931,12932],{},"Performance events: US$50–100\u002Fmes",[70,12934,12935],{},"Session Replay: US$100\u002Fmes",[70,12937,12938],{},"Usuarios: US$100\u002Fmes",[70,12940,12887,12941],{},[27,12942,12943],{},"US$450–600\u002Fmes = R$2.250–3.000\u002Fmes",[12,12945,12946],{},"En esa etapa, R$30 mil\u002Faño en error tracking empieza a competir con salario parcial de ingeniero. Es el punto en que la conversación \"¿vale auto-hospedar?\" deja de ser teórica y se vuelve reunión agendada.",[12,12948,12949],{},"El dolor real del plan Business no es el precio base — es la multiplicación por add-ons. Performance, Replay, Profiling, Cron Monitoring, Code Coverage — cada uno viene con su propio conteo de eventos y su propia cuenta. Es predecible, pero no es barato.",[19,12951,12953],{"id":12952},"sentry-auto-hospedado-que-es-exactamente","Sentry auto-hospedado — qué es exactamente",[12,12955,12956,12957,12960],{},"La carpeta oficial ",[231,12958,12959],{},"getsentry\u002Fself-hosted"," instala un stack que tiene la forma siguiente, en producción:",[119,12962,12963,12975],{},[122,12964,12965],{},[125,12966,12967,12970,12972],{},[128,12968,12969],{},"Servicio",[128,12971,139],{},[128,12973,12974],{},"RAM típica",[141,12976,12977,12987,12998,13008,13018,13028,13037,13047,13057,13068,13078],{},[125,12978,12979,12982,12985],{},[146,12980,12981],{},"sentry-web",[146,12983,12984],{},"Frontend Django + API",[146,12986,11478],{},[125,12988,12989,12992,12995],{},[146,12990,12991],{},"sentry-worker",[146,12993,12994],{},"Procesamiento asíncrono (Celery)",[146,12996,12997],{},"768 MB",[125,12999,13000,13003,13006],{},[146,13001,13002],{},"sentry-cron",[146,13004,13005],{},"Tareas agendadas",[146,13007,11497],{},[125,13009,13010,13013,13016],{},[146,13011,13012],{},"relay",[146,13014,13015],{},"Ingestión de eventos",[146,13017,11478],{},[125,13019,13020,13023,13026],{},[146,13021,13022],{},"postgres",[146,13024,13025],{},"Metadatos, proyectos, usuarios",[146,13027,11500],{},[125,13029,13030,13032,13035],{},[146,13031,7510],{},[146,13033,13034],{},"Cache + colas Celery",[146,13036,11478],{},[125,13038,13039,13042,13045],{},[146,13040,13041],{},"kafka",[146,13043,13044],{},"Stream de eventos brutos",[146,13046,11500],{},[125,13048,13049,13052,13055],{},[146,13050,13051],{},"zookeeper",[146,13053,13054],{},"Coordinación de Kafka",[146,13056,11497],{},[125,13058,13059,13062,13065],{},[146,13060,13061],{},"clickhouse",[146,13063,13064],{},"Almacenamiento analítico de eventos",[146,13066,13067],{},"1,5 GB",[125,13069,13070,13073,13076],{},[146,13071,13072],{},"symbolicator",[146,13074,13075],{},"Resolución de stack traces nativos",[146,13077,11478],{},[125,13079,13080,13083,13086],{},[146,13081,13082],{},"snuba-api \u002F snuba-consumer \u002F snuba-replacer",[146,13084,13085],{},"Capa entre Sentry y ClickHouse",[146,13087,11500],{},[12,13089,13090,13091,13094],{},"Suma: cerca de ",[27,13092,13093],{},"8 GB de RAM en uso firme"," en un cluster pequeño, 12 contenedores, y eso es el piso. En volumen mayor, Kafka y ClickHouse quedan con hambre bien rápido.",[12,13096,13097,13098,13101,13102,13105],{},"La trampa menos discutida es la licencia: desde 2019, Sentry licencia el producto auto-hospedado bajo ",[27,13099,13100],{},"BSL 1.1"," (Business Source License). Es open-source en la forma — lees el código, modificas, contribuyes — pero tiene una cláusula que ",[27,13103,13104],{},"prohíbe ofrecer Sentry como servicio comercial a terceros",". Para empresa que usa internamente, es irrelevante. Para agencia que pensaba incluir error tracking en el paquete vendido al cliente, es prohibitivo.",[19,13107,13109],{"id":13108},"setup-en-cluster-pasos-altos","Setup en cluster — pasos altos",[12,13111,13112,13113,13116,13117,13120],{},"La documentación oficial asume que vas a correr ",[231,13114,13115],{},".\u002Finstall.sh"," en un servidor Ubuntu, y enseguida el ",[231,13118,13119],{},"docker-compose up -d"," administra el stack. Para quien opera cluster moderno, el camino es ligeramente distinto:",[67,13122,13123,13133,13143,13153,13163],{},[70,13124,13125,13128,13129,13132],{},[27,13126,13127],{},"Definir job spec con 12 contenedores."," HeroCtl acepta archivo de configuración de hasta algunos miles de líneas, y la traducción del compose oficial al job spec es mecánica. Reserva un turno de trabajo para hacer eso bien — incluyendo ",[231,13130,13131],{},"depends_on",", health checks, y órdenes de boot (ZooKeeper antes de Kafka, Postgres antes de sentry-web, y así sucesivamente).",[70,13134,13135,13138,13139,13142],{},[27,13136,13137],{},"Volúmenes persistentes para Postgres, ClickHouse y Kafka."," Los tres tienen datos que no puedes perder. ClickHouse es el que más crece — eventos brutos se vuelven líneas analíticas y el disco llena. Reserva ",[27,13140,13141],{},"50 GB de SSD inicial",", ajusta a 200 GB después de seis meses si el volumen lo justifica.",[70,13144,13145,13148,13149,13152],{},[27,13146,13147],{},"Backup, y backup de cada uno por separado."," El error más común en auto-hospedado es hacer backup solo de Postgres, olvidando que ",[27,13150,13151],{},"los eventos viven en ClickHouse",". Postgres tiene metadatos (proyecto, usuario, configuración de alerta); ClickHouse tiene el historial de errores. Backup solo de Postgres recupera la interfaz vacía.",[70,13154,13155,13158,13159,13162],{},[27,13156,13157],{},"TLS automático en el dominio interno."," El panel necesita estar accesible para los devs con certificado válido — sin ",[231,13160,13161],{},"-k"," en el curl, sin aviso amarillo en Chrome. El cluster de HeroCtl resuelve eso automáticamente con Let's Encrypt; en otros stacks añades un operador o configuras manualmente.",[70,13164,13165,13168],{},[27,13166,13167],{},"Actualizaciones trimestrales."," Sentry libera versión major cada tres meses, y la auto-hospedada exige migración de schema de Postgres + reindex parcial de ClickHouse. Reserva una ventana de mantenimiento en cada release — en general entre 15 minutos y dos horas, dependiendo del volumen acumulado.",[12,13170,13171,13174],{},[27,13172,13173],{},"Tiempo total de instalación:"," 4 a 8 horas para dev competente que conoce el producto, 2 a 3 días para alguien aprendiendo desde cero. Eso es el setup limpio. Añade 50% para debugar el caso real (DNS interno errado, volumen no montado, Kafka trabado por ZooKeeper que tardó en subir).",[19,13176,13178],{"id":13177},"glitchtip-el-sentry-lite-que-mucha-gente-olvida","GlitchTip — el \"Sentry-lite\" que mucha gente olvida",[12,13180,13181],{},"GlitchTip es la alternativa que aparece poco en comparativos y merece destaque. Es open-source MIT (no BSL) — usas para cualquier fin, incluso comercial, sin cláusula. Fue diseñado específicamente para cubrir el caso 80\u002F20 de Sentry.",[12,13183,13184,13187,13188,13191],{},[27,13185,13186],{},"Cómo funciona el \"compatible con Sentry SDK\":"," el SDK de Sentry envía eventos a un endpoint HTTP estándar. GlitchTip implementa ese mismo endpoint. Cambias la URL en el ",[231,13189,13190],{},"Sentry.init({ dsn: ... })"," de tu aplicación para apuntar a GlitchTip y nada más cambia — ni código, ni dependencia, ni build. La migración inversa también es directa.",[12,13193,13194],{},[27,13195,13196],{},"Stack de GlitchTip:",[2735,13198,13199,13202,13205,13208],{},[70,13200,13201],{},"PostgreSQL",[70,13203,13204],{},"Redis (colas)",[70,13206,13207],{},"Django web",[70,13209,13210],{},"Celery worker",[12,13212,13213,13214,13217],{},"Son 4 contenedores contra 12 de Sentry. Recursos: ",[27,13215,13216],{},"2 GB de RAM, 1 vCPU",". Corre cómodo en un droplet de US$12\u002Fmes. Acepta los mismos SDKs (JavaScript, Python, Go, Ruby, PHP, Java, .NET, mobile) sin cambio.",[12,13219,13220],{},[27,13221,13222],{},"Lo que GlitchTip no tiene:",[2735,13224,13225,13228,13231,13234,13237,13240],{},[70,13226,13227],{},"Session Replay",[70,13229,13230],{},"Continuous Profiling",[70,13232,13233],{},"Performance Monitoring al nivel de detalle de Sentry (tiene versión simplificada)",[70,13235,13236],{},"Tracing distribuido con waterfall completo",[70,13238,13239],{},"Code Coverage",[70,13241,13242],{},"Cron monitoring sofisticado",[12,13244,13245],{},[27,13246,13247],{},"Lo que GlitchTip tiene:",[2735,13249,13250,13253,13256,13259,13262,13265],{},[70,13251,13252],{},"Error tracking completo, con agrupamiento, frecuencia, primero\u002Fúltimo visto",[70,13254,13255],{},"Stack traces de cualquier lenguaje soportado por los SDKs Sentry",[70,13257,13258],{},"Uptime monitoring básico",[70,13260,13261],{},"Alerting vía webhook, e-mail e integraciones populares",[70,13263,13264],{},"Issue tracking minimal — asignar, resolver, ignorar",[70,13266,13267],{},"Multi-proyecto, multi-equipo, RBAC simple",[12,13269,13270],{},"Para startup pequeña o mediana que no usa Replay ni Profiling avanzado, GlitchTip cubre lo que importa con una fracción de la operación. Es el caso más subestimado de la estantería.",[19,13272,13274],{"id":13273},"la-cuenta-auto-hospedado-siendo-honesto","La cuenta auto-hospedado, siendo honesto",[12,13276,13277],{},"Si tu premisa para auto-hospedar es \"va a salir gratis\", te vas a decepcionar. Costes reales de auto-hospedar Sentry en proveedor barato:",[119,13279,13280,13289],{},[122,13281,13282],{},[125,13283,13284,13286],{},[128,13285,11393],{},[128,13287,13288],{},"Coste mensual (BRL)",[141,13290,13291,13299,13306,13314,13322],{},[125,13292,13293,13296],{},[146,13294,13295],{},"Servidor dedicado 8 GB \u002F 4 vCPU (Hetzner CPX31, €13,49)",[146,13297,13298],{},"R$74",[125,13300,13301,13304],{},[146,13302,13303],{},"Backup storage S3-compatible (50 GB)",[146,13305,11414],{},[125,13307,13308,13311],{},[146,13309,13310],{},"Tiempo de mantenimiento (2–4h\u002Fmes × R$100\u002Fh valor de hora)",[146,13312,13313],{},"R$200–400",[125,13315,13316,13319],{},[146,13317,13318],{},"Actualizaciones trimestrales amortizadas (4h × R$100\u002Fh ÷ 3 meses)",[146,13320,13321],{},"R$130",[125,13323,13324,13329],{},[146,13325,13326],{},[27,13327,13328],{},"Total honesto",[146,13330,13331],{},[27,13332,13333],{},"R$430–630\u002Fmes",[12,13335,13336],{},"Compara:",[2735,13338,13339,13348,13358],{},[70,13340,13341,2578,13344,13347],{},[27,13342,13343],{},"Versus SaaS Team (R$130\u002Fmes):",[27,13345,13346],{},"perjuicio de R$300–500\u002Fmes."," Auto-hospedado en esa etapa es hobby, no economía.",[70,13349,13350,13353,13354,13357],{},[27,13351,13352],{},"Versus SaaS Business en uso medio (R$850\u002Fmes):"," economía de ",[27,13355,13356],{},"R$220–420\u002Fmes."," Empieza a tener sentido.",[70,13359,13360,13353,13363,13366],{},[27,13361,13362],{},"Versus SaaS scale-up (R$2.500\u002Fmes):",[27,13364,13365],{},"R$1.870–2.070\u002Fmes."," Ahí vale el esfuerzo.",[12,13368,13369,13370,13373],{},"Para GlitchTip, la cuenta es distinta — el servidor puede ser la mitad del tamaño (2 GB \u002F 1 vCPU, R$30\u002Fmes) y el mantenimiento cae a cerca de 1h\u002Fmes. Total honesto: ",[27,13371,13372],{},"R$150–200\u002Fmes",". Ahí el punto de equilibrio con SaaS Team llega.",[19,13375,3838],{"id":3837},[119,13377,13378,13393],{},[122,13379,13380],{},[125,13381,13382,13384,13387,13390],{},[128,13383,2983],{},[128,13385,13386],{},"Sentry SaaS",[128,13388,13389],{},"Sentry auto-hospedado",[128,13391,13392],{},"GlitchTip auto-hospedado",[141,13394,13395,13409,13423,13437,13449,13462,13474,13485,13495,13509,13522,13536],{},[125,13396,13397,13400,13403,13406],{},[146,13398,13399],{},"Coste mensual mínimo (BRL)",[146,13401,13402],{},"R$130 (Team)",[146,13404,13405],{},"R$430 honesto",[146,13407,13408],{},"R$150 honesto",[125,13410,13411,13414,13417,13420],{},[146,13412,13413],{},"Coste a 100k errors\u002Fmes",[146,13415,13416],{},"R$130–250",[146,13418,13419],{},"R$430–500",[146,13421,13422],{},"R$150–200",[125,13424,13425,13428,13431,13434],{},[146,13426,13427],{},"Coste a 1M errors\u002Fmes",[146,13429,13430],{},"R$1.500–2.500",[146,13432,13433],{},"R$500–700",[146,13435,13436],{},"R$250–350",[125,13438,13439,13441,13443,13446],{},[146,13440,3008],{},[146,13442,9776],{},[146,13444,13445],{},"4–8 horas (1ª vez 2–3 días)",[146,13447,13448],{},"1–2 horas",[125,13450,13451,13454,13456,13459],{},[146,13452,13453],{},"Recursos mínimos cluster",[146,13455,12524],{},[146,13457,13458],{},"8 GB RAM \u002F 4 vCPU \u002F 50 GB SSD",[146,13460,13461],{},"2 GB RAM \u002F 1 vCPU \u002F 20 GB SSD",[125,13463,13464,13467,13470,13472],{},[146,13465,13466],{},"Performance Monitoring",[146,13468,13469],{},"Completo",[146,13471,13469],{},[146,13473,12379],{},[125,13475,13476,13478,13480,13483],{},[146,13477,13227],{},[146,13479,3065],{},[146,13481,13482],{},"No (solo SaaS)",[146,13484,3059],{},[125,13486,13487,13489,13491,13493],{},[146,13488,13230],{},[146,13490,3065],{},[146,13492,3059],{},[146,13494,3059],{},[125,13496,13497,13500,13503,13506],{},[146,13498,13499],{},"Alerting integrations",[146,13501,13502],{},"Slack, PagerDuty, Teams, Linear, Jira, e-mail, webhook",[146,13504,13505],{},"Mismo conjunto",[146,13507,13508],{},"Slack, e-mail, webhook",[125,13510,13511,13514,13517,13520],{},[146,13512,13513],{},"Compliance \u002F data residency",[146,13515,13516],{},"Datacenters US\u002FEU (transferencia internacional)",[146,13518,13519],{},"Servidor tuyo",[146,13521,13519],{},[125,13523,13524,13527,13530,13533],{},[146,13525,13526],{},"Comunidad \u002F SDKs",[146,13528,13529],{},"Toda la industria",[146,13531,13532],{},"Mismos SDKs Sentry",[146,13534,13535],{},"SDKs Sentry compatibles",[125,13537,13538,13541,13544,13547],{},[146,13539,13540],{},"Rango ideal",[146,13542,13543],{},"\u003C500k events\u002Fmes o equipo pequeño",[146,13545,13546],{},">1M events\u002Fmes con 1 dev para cuidar",[146,13548,13549],{},"Startup pequeña\u002Fmediana sin Replay\u002FProfiling",[19,13551,13553],{"id":13552},"cuando-quedarse-en-el-saas","Cuándo quedarse en el SaaS",[12,13555,13556],{},"Cuatro perfiles en que pagar a Sentry todos los meses es la decisión correcta:",[12,13558,13559,13562],{},[27,13560,13561],{},"Volumen por debajo de 100 mil errores\u002Fmes."," El plan Team a US$26\u002Fmes cubre, sin add-ons. Auto-hospedado de ese tamaño es proyecto de hobby — gastas más tiempo configurando de lo que ahorras.",[12,13564,13565,13568],{},[27,13566,13567],{},"Equipo de 1 a 3 devs sin capacidad operacional."," Cada hora gastada operando Sentry es hora no gastada en el producto. Si aún no contrataste al primer ingeniero de plataforma, paga el SaaS y sigue adelante. La línea \"primero contratar SRE para correr Sentry\" no es estrategia, es distracción.",[12,13570,13571,13574],{},[27,13572,13573],{},"Usas Session Replay y Profiling."," Son features SaaS-only — auto-hospedar aún no es opción. Si tu workflow de debug depende de esas dos, la discusión termina.",[12,13576,13577,13580],{},[27,13578,13579],{},"Compliance exige solo LGPD, sin residencia de datos local."," Sentry tiene opción de datacenter en la Unión Europea, en conformidad con GDPR y por extensión LGPD. Si tu jurídico acepta transferencia internacional de datos anonimizados, la conformidad no fuerza auto-hospedar.",[19,13582,13584],{"id":13583},"cuando-auto-hospedar-sentry-tiene-sentido","Cuándo auto-hospedar Sentry tiene sentido",[12,13586,13587],{},"Tres condiciones — necesitas al menos dos para justificar el esfuerzo:",[12,13589,13590,13593],{},[27,13591,13592],{},"Volumen pasó de 1 millón de errores\u002Fmes."," Ahí la factura SaaS empieza a competir con salario, y la economía paga el tiempo del dev cuidando de la infraestructura.",[12,13595,13596,13599],{},[27,13597,13598],{},"Compliance exige datos en servidor controlado."," Sectores regulados (salud, financiero, gobierno, educación infantil) frecuentemente tienen cláusula de residencia de datos que vuelve SaaS inviable. Auto-hospedado es el camino.",[12,13601,13602,13605],{},[27,13603,13604],{},"Equipo tiene 1+ dev con tiempo recurrente para cuidar."," \"Tiempo recurrente\" = al menos 4 horas al mes asignadas explícitamente, con persona nombrada y backup. Si fuera \"ah, cualquiera cuida\", en tres meses nadie cuida y el sistema se vuelve punto ciego.",[12,13607,13608],{},"Bono: no necesitas Session Replay ni Profiling. Esos dos quedan en el SaaS, así que auto-hospedar significa renunciar a ellos. Para muchos equipos B2B con aplicaciones server-side, esa renuncia es trivial. Para equipos B2C con app mobile\u002FSPA complejo, puede ser deal-breaker.",[19,13610,13612],{"id":13611},"cuando-glitchtip-es-la-mejor-eleccion-de-las-tres","Cuándo GlitchTip es la mejor elección de las tres",[12,13614,13615],{},"El perfil ideal de GlitchTip es específico:",[2735,13617,13618,13621,13624,13627,13630,13633],{},[70,13619,13620],{},"Startup con R$10–50k MRR, equipo de 2 a 5 ingenieros.",[70,13622,13623],{},"Aplicaciones relativamente simples — SaaS B2B, web app, backend de mobile, API.",[70,13625,13626],{},"No usa Session Replay (o nunca usó, y no siente falta).",[70,13628,13629],{},"No usa Continuous Profiling.",[70,13631,13632],{},"Quiere auto-hospedado por el control y la licencia MIT, pero no quiere operar 12 contenedores.",[70,13634,13635],{},"Ya usa el SDK de Sentry y no quiere reescribir instrumentación.",[12,13637,13638],{},"Si tres de esos cuatro puntos pegan con tu equipo, GlitchTip probablemente ahorra R$500\u002Fmes versus SaaS Business sin costar el overhead operacional de Sentry auto-hospedado. Es el caso menos discutido y el más frecuentemente útil.",[19,13640,13642],{"id":13641},"heroctl-como-capa-operacional","HeroCtl como capa operacional",[12,13644,13645],{},"Si decidiste auto-hospedar (Sentry o GlitchTip), el cluster donde eso corre importa casi tanto como la elección del producto. Algunas observaciones sobre correr error tracking sobre HeroCtl:",[2735,13647,13648,13654,13660,13666,13675],{},[70,13649,13650,13653],{},[27,13651,13652],{},"Job spec con volúmenes persistentes"," es nativo del producto — Postgres, ClickHouse y Kafka tienen donde grabar datos sin perder nada en un rolling update.",[70,13655,13656,13659],{},[27,13657,13658],{},"Backup gestionado"," está disponible en el plan Business, abarcando bases de datos corriendo como jobs en el cluster. Postgres + ClickHouse entran juntos en el mismo agendamiento.",[70,13661,13662,13665],{},[27,13663,13664],{},"Métricas integradas"," del propio HeroCtl muestran CPU\u002FRAM\u002FIO de cada servicio de Sentry — no necesitas montar Prometheus por fuera solo para saber si ClickHouse está saludable.",[70,13667,13668,13670,13671,13674],{},[27,13669,11370],{}," con TLS automático cuida del ",[231,13672,13673],{},"sentry.tuempresa.com"," sin ningún operador de certificado adicional.",[70,13676,13677,13680],{},[27,13678,13679],{},"Plano de control compacto"," — 200 a 400 MB por servidor, sobra mucho recurso para workload real (Sentry, en el caso).",[12,13682,13683],{},"Para cluster de 4 servidores cloud, eso significa: 8 GB de RAM disponibles en el servidor que aloja Sentry, métricas y backup viniendo gratis del orquestador, y cero operador externo a configurar. El ROI cambia — porque parte del coste \"honesto\" de auto-hospedado es exactamente la infra que el cluster ya ofrece.",[19,13685,3226],{"id":3225},[12,13687,13688,13691,13692,13695],{},[27,13689,13690],{},"¿Cuánto consume de RAM Sentry auto-hospedado?","\nEn producción pequeña, ",[27,13693,13694],{},"8 GB de RAM es el piso firme"," — debajo de eso, Kafka empieza a OOM-killar procesos bajo carga. Recomendado: 12 GB para tener holgura. ClickHouse y Kafka son los dos mayores consumidores; juntos suman la mitad de la memoria total.",[12,13697,13698,13701,13702,13705],{},[27,13699,13700],{},"¿GlitchTip es compatible con el Sentry SDK existente?","\nSí. GlitchTip implementa el mismo endpoint HTTP que Sentry recibe los eventos. Cambiar la URL en el ",[231,13703,13704],{},"Sentry.init({ dsn: 'https:\u002F\u002F...' })"," apuntando a tu GlitchTip basta — el SDK no nota diferencia. La migración inversa también es trivial. Los SDKs cubiertos incluyen JavaScript, Python, Go, Ruby, PHP, Java, .NET, iOS, Android y React Native.",[12,13707,13708,13711],{},[27,13709,13710],{},"¿Puedo migrar de SaaS a auto-hospedado sin perder historial de errores?","\nTécnicamente sí, pero con reservas. Sentry SaaS ofrece exportación de eventos vía API, y el auto-hospedado acepta ingestión. En la práctica, la mayoría de los equipos simplemente no migra historial — empiezan a cero en el nuevo, y mantienen SaaS read-only por unos 90 días para consultar incidentes antiguos cuando necesario. Historial de errores viejo suele tener valor decreciente; lo que importa es lo que pasó en las últimas 4 semanas.",[12,13713,13714,13717],{},[27,13715,13716],{},"¿Sentry auto-hospedado tiene soporte oficial?","\nNo, en ningún nivel. La versión auto-hospedada es \"best effort\" de la empresa Sentry — publican la release, documentan, pero el soporte técnico solo aparece en los planes pagos del SaaS. La comunidad en GitHub y en el foro oficial es activa, y la mayoría de los problemas comunes ya fue resuelta allí. Para problemas exóticos, estás solo — o contratas una consultoría especializada.",[12,13719,13720,13723,13726],{},[27,13721,13722],{},"La licencia BSL — ¿puedo usar para SaaS comercial?",[27,13724,13725],{},"No."," La BSL 1.1 de Sentry prohíbe explícitamente ofrecer Sentry como servicio comercial a terceros. Puedes usar internamente sin límite, en cualquier empresa de cualquier tamaño. Pero si tu idea era incluir \"error tracking dedicado\" en el paquete de tu cliente cobrando por ello, la licencia bloquea. Para ese caso, GlitchTip (MIT) u otras alternativas open-source MIT son el camino.",[12,13728,13729,13732,13733,13736,13737,13740,13741,13736,13744,13747],{},[27,13730,13731],{},"¿Cuánto tiempo lleva hacer setup desde cero?","\nSentry auto-hospedado: ",[27,13734,13735],{},"4 a 8 horas"," para dev experimentado, ",[27,13738,13739],{},"2 a 3 días"," para alguien aprendiendo. GlitchTip: ",[27,13742,13743],{},"1 a 2 horas",[27,13745,13746],{},"medio día"," para principiante. Esos números cubren instalación limpia, ingestión funcionando, alerta básica configurada, TLS listo. No incluye migración de SDKs (que es trivial) ni ajuste fino de reglas de alerta (que toma semanas en cualquier producto).",[12,13749,13750,13753],{},[27,13751,13752],{},"¿ClickHouse es realmente necesario, o SQLite sirve?","\nPara Sentry auto-hospedado: ClickHouse es mandatorio. El producto usa la base analítica para queries de agregación que Postgres no da abasto bajo volumen real. Para GlitchTip: el producto usa solo Postgres, y eso es parte del motivo de él ser dramáticamente más ligero. SQLite no sirve para ninguno de los dos en producción.",[12,13755,13756,13759,13760,13763],{},[27,13757,13758],{},"¿Performance impact en el app cliente?","\nEl SDK de Sentry (y de GlitchTip, que usa el mismo SDK) tiene overhead ",[27,13761,13762],{},"debajo de 1ms en la mayoría de los casos"," — captura error local, envía en background sin bloquear. En SPAs, el tamaño del bundle añade 30–60 KB gzipped dependiendo de las integraciones. Para apps server-side, el overhead es despreciable. El Performance Monitoring tiene coste ligeramente mayor (sampling de 10% suele ser el default), pero bajo configuración razonable queda debajo de 5ms p99.",[19,13765,3310],{"id":3309},[12,13767,13768],{},"La pregunta \"Sentry SaaS vs auto-hospedado\" tiene una respuesta distinta en cada etapa de la empresa. Para startup pequeña, SaaS siempre. Para scale-up con volumen alto y equipo competente, auto-hospedado ahorra dinero real. Para medio de camino, GlitchTip suele ser la elección más lúcida — economía significativa, complejidad operacional manejable, licencia permisiva.",[12,13770,13771],{},"La cuenta es mensurable, no filosófica. Antes de decidir, comprueba tres números:",[67,13773,13774,13777,13780],{},[70,13775,13776],{},"Cuántos errores\u002Fmes tu aplicación genera hoy (cualquier dashboard de error tracking muestra).",[70,13778,13779],{},"Cuál la factura mensual Sentry proyectada para dentro de 12 meses (multiplica tráfico previsto por el plan correspondiente).",[70,13781,13782],{},"Cuántas horas\u002Fmes tu equipo puede asignar para operar infraestructura sin perjuicio de producto.",[12,13784,13785],{},"Si número 1 está por encima de 1 millón, número 2 está por encima de R$1.500, y número 3 está por encima de 4 horas — auto-hospedar es decisión financiera sana. Caso contrario, quédate en el SaaS y usa el tiempo ahorrado para entregar feature.",[12,13787,13788],{},"Para correr auto-hospedado (Sentry o GlitchTip) en un cluster que cuida de TLS, backup y métricas sin operador externo:",[224,13790,13791],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,13792,13793],{"__ignoreMap":229},[234,13794,13795,13797,13799,13801,13803],{"class":236,"line":237},[234,13796,1220],{"class":247},[234,13798,2958],{"class":251},[234,13800,5329],{"class":255},[234,13802,2964],{"class":383},[234,13804,2967],{"class":247},[12,13806,13807],{},"Posts relacionados:",[2735,13809,13810,13815],{},[70,13811,13812],{},[3337,13813,13814],{"href":11725},"Observabilidad sin Datadog: stack honesto para startup",[70,13816,13817],{},[3337,13818,13819],{"href":7466},"Postgres en producción: gestionado vs auto-hospedado, la cuenta real",[3351,13821,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":13823},[13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837],{"id":12769,"depth":244,"text":12770},{"id":12816,"depth":244,"text":12817},{"id":12870,"depth":244,"text":12871},{"id":12952,"depth":244,"text":12953},{"id":13108,"depth":244,"text":13109},{"id":13177,"depth":244,"text":13178},{"id":13273,"depth":244,"text":13274},{"id":3837,"depth":244,"text":3838},{"id":13552,"depth":244,"text":13553},{"id":13583,"depth":244,"text":13584},{"id":13611,"depth":244,"text":13612},{"id":13641,"depth":244,"text":13642},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"2026-05-05","Sentry SaaS empieza en US$26\u002Fmes, escalando rápido con volumen. Auto-hospedado es 'gratuito' — pero corre Postgres + Redis + Kafka + ClickHouse. Análisis honesto de cuándo vale auto-hospedar.",{},"\u002Fes\u002Fblog\u002Fsentry-auto-hospedado-vs-saas-cuanto-se-ahorra",{"title":12758,"description":13839},{"loc":13841},"es\u002Fblog\u002Fsentry-auto-hospedado-vs-saas-cuanto-se-ahorra",[13846,13847,7512,13848,3394],"sentry","error-tracking","coste","rIH8QSHGoS81yviF9kK8Dlfta7AELjL-CnWXFCzJjw4",{"id":13851,"title":13852,"author":7,"body":13853,"category":8761,"cover":3380,"date":14936,"description":14937,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":14938,"navigation":411,"path":14939,"readingTime":8766,"seo":14940,"sitemap":14941,"stem":14942,"tags":14943,"__hash__":14950},"blog_es\u002Fes\u002Fblog\u002Fhetzner-vs-digitalocean-vs-magalu-cloud.md","Hetzner vs DigitalOcean vs Magalu Cloud: qué VPS elegir para una startup en 2026",{"type":9,"value":13854,"toc":14891},[13855,13858,13861,13865,13868,13872,13875,13879,13882,13928,13935,13939,13942,13945,13977,13980,13984,13987,14007,14011,14043,14047,14050,14054,14057,14104,14111,14115,14118,14144,14147,14151,14189,14193,14218,14222,14225,14229,14232,14258,14261,14265,14279,14283,14309,14313,14345,14349,14515,14519,14522,14525,14528,14532,14535,14573,14576,14580,14583,14636,14639,14642,14646,14649,14652,14672,14675,14679,14683,14705,14709,14726,14730,14747,14751,14754,14757,14760,14763,14767,14770,14773,14776,14778,14781,14784,14788,14791,14795,14798,14802,14805,14809,14812,14816,14819,14823,14826,14830,14833,14836,14839,14841,14844,14847,14850,14866,14869,14872,14886,14889],[12,13856,13857],{},"La elección de VPS para una startup brasileña en 2026 no es una sola pregunta — son cuatro preguntas que se cruzan. Cuánto cuesta en dólar o euro contra ingresos que entran en real. Cuánta latencia aguanta tu producto sin ofender al usuario. Cuánto servicio gestionado quieres pagar para tercerizar. Y cuánta madurez tiene el proveedor para sostenerte cuando algo se rompa de madrugada.",[12,13859,13860],{},"Los tres nombres que aparecen en casi toda mesa de discusión hoy son Hetzner, DigitalOcean y Magalu Cloud. Cada uno resuelve uno de los lados de la ecuación muy bien y pierde en los otros dos. No existe ganador universal. Existe ganador por perfil de uso. Este post abre las cuentas, con números, y cierra con una recomendación honesta por escenario.",[19,13862,13864],{"id":13863},"tldr-que-vps-elegir-para-una-startup-brasilena-en-2026","TL;DR — qué VPS elegir para una startup brasileña en 2026",[12,13866,13867],{},"Hetzner es la opción correcta cuando lo que pesa es costo absoluto y el público tolera 200ms de latencia — proyectos hobby, MVPs, herramientas de uso interno, integraciones asíncronas, runners de CI, batch jobs y clusters auto-hospedados sirviendo público fuera de Brasil. El CX11 sale por € 4,09 al mes, cerca de R$22, e incluye 20 TB de tráfico de salida. DigitalOcean es la elección sensata para indie hacker brasileño con público B2C que necesita menos de 100ms de respuesta — datacenters en Nueva York y Toronto entregan 120-140ms para São Paulo, la interfaz es la mejor del segmento y la comunidad en portugués es extensa, pero el precio es roughly 2-3× el de Hetzner. Magalu Cloud es la respuesta correcta cuando data residency en Brasil es exigencia regulatoria — salud, financiero, gobierno, contratos LGPD sectoriales — con latencia de 5-15ms para São Paulo, facturación en real y soporte en portugués, al costo de un ecosistema todavía en maduración. Para cluster auto-hospedado de 3-4 nodos corriendo decenas de aplicaciones, cualquiera de los tres funciona bien.",[19,13869,13871],{"id":13870},"hetzner-el-ataque-al-bolsillo","Hetzner — el ataque al bolsillo",[12,13873,13874],{},"Hetzner es una empresa alemana con más de 25 años de operación. Su modelo es simple: VPS sin adornos, servidores dedicados en subasta, network europeo de buena calidad, y pricing que mata a cualquier competidor en valor absoluto. En 2026 la tabla sigue siendo la misma de siempre — sube poco con el tiempo, al contrario de casi toda nube americana.",[368,13876,13878],{"id":13877},"cuanto-cuesta-un-vps-en-hetzner-en-2026","¿Cuánto cuesta un VPS en Hetzner en 2026?",[12,13880,13881],{},"La línea de Cloud Servers tiene dos sabores, x86 y ARM, y los planes más relevantes son:",[2735,13883,13884,13894,13903,13911,13919],{},[70,13885,13886,13889,13890,13893],{},[27,13887,13888],{},"CX11"," (1 vCPU x86, 2 GB RAM, 20 GB SSD): € 4,09\u002Fmes — cerca de ",[27,13891,13892],{},"R$22"," al cambio de R$5,5\u002Feuro.",[70,13895,13896,13899,13900,101],{},[27,13897,13898],{},"CPX11"," (2 vCPU AMD, 2 GB RAM, 40 GB SSD): € 4,75\u002Fmes — ",[27,13901,13902],{},"R$26",[70,13904,13905,13907,13908,101],{},[27,13906,6707],{}," (3 vCPU AMD, 4 GB RAM, 80 GB SSD): € 7,99\u002Fmes — ",[27,13909,13910],{},"R$44",[70,13912,13913,13915,13916,101],{},[27,13914,6717],{}," (4 vCPU AMD, 8 GB RAM, 160 GB SSD): € 14,86\u002Fmes — ",[27,13917,13918],{},"R$82",[70,13920,13921,13924,13925,101],{},[27,13922,13923],{},"CAX11"," (2 vCPU ARM, 4 GB RAM, 40 GB SSD): € 3,79\u002Fmes — ",[27,13926,13927],{},"R$21",[12,13929,13930,13931,13934],{},"Cada VPS incluye ",[27,13932,13933],{},"20 TB de tráfico de salida por mes",". Es una cantidad que roza el absurdo cuando se compara con nubes americanas — el mismo tráfico en AWS São Paulo cuesta $0,09 por gigabyte fuera de los primeros 100 GB, es decir, 20 TB rinden cerca de $1.800 al mes solo de banda.",[368,13936,13938],{"id":13937},"hetzner-tiene-datacenter-en-brasil","¿Hetzner tiene datacenter en Brasil?",[12,13940,13941],{},"No. Hetzner opera datacenters en Falkenstein, Núremberg y Helsinki en Europa, Hillsboro (Oregón) y Ashburn (Virginia) en Estados Unidos, y Singapur en Asia. No hay presencia sudamericana.",[12,13943,13944],{},"La latencia típica de un servidor para un usuario en São Paulo:",[2735,13946,13947,13953,13959,13965,13971],{},[70,13948,13949,13950],{},"Falkenstein, Alemania: ",[27,13951,13952],{},"200-220ms",[70,13954,13955,13956],{},"Helsinki, Finlandia: ",[27,13957,13958],{},"210-240ms",[70,13960,13961,13962],{},"Ashburn, Virginia: ",[27,13963,13964],{},"140-160ms",[70,13966,13967,13968],{},"Hillsboro, Oregón: ",[27,13969,13970],{},"170-190ms",[70,13972,13973,13974],{},"Singapur: ",[27,13975,13976],{},"300-340ms",[12,13978,13979],{},"Para contexto, 200ms es el punto en que el usuario empieza a notar lentitud al hacer clic en un botón. Para una SPA pesada que ya carga assets del navegador y hace tres llamadas en paralelo, 200ms acumulativos de cada round-trip se vuelven cinco a ocho segundos perceptibles. Una app B2C con público brasileño hospedada en Falkenstein es un producto que parece \"lento\", aunque el servidor responda en 5ms.",[368,13981,13983],{"id":13982},"donde-hetzner-brilla","Donde Hetzner brilla",[12,13985,13986],{},"La combinación de pricing + bandwidth incluido hace de Hetzner la elección obvia para tres tipos de carga:",[67,13988,13989,13995,14001],{},[70,13990,13991,13994],{},[27,13992,13993],{},"Workloads no-latency-críticas",": runners de CI, batch jobs, workers asíncronos, ETL nocturno, tareas cron. No importa que respondan 200ms más.",[70,13996,13997,14000],{},[27,13998,13999],{},"Aplicaciones con público fuera de Brasil",": SaaS B2B con clientes en Europa o EE. UU. Falkenstein a Berlín es 15ms, Ashburn a Nueva York es 5ms.",[70,14002,14003,14006],{},[27,14004,14005],{},"Clusters auto-hospedados de orquestador",": correr HeroCtl, Coolify o similar en 3-4 nodos Hetzner para hospedar decenas de apps internas cuesta lo que un único droplet equivalente costaría en DigitalOcean.",[368,14008,14010],{"id":14009},"donde-hetzner-pierde","Donde Hetzner pierde",[2735,14012,14013,14019,14025,14031,14037],{},[70,14014,14015,14018],{},[27,14016,14017],{},"Sin datacenter brasileño"," — fin de la historia para cualquier compliance que exija data residency.",[70,14020,14021,14024],{},[27,14022,14023],{},"Soporte solo en inglés y alemán"," — chat y tickets responden rápido, pero en horario comercial europeo.",[70,14026,14027,14030],{},[27,14028,14029],{},"Facturación en euro"," — pagas con tarjeta de crédito internacional, con IOF de 4,38% y spread cambiario del banco.",[70,14032,14033,14036],{},[27,14034,14035],{},"Marketplace de servicios limitado"," — no tiene Managed Postgres del nivel de DigitalOcean ni App Platform serverless. Lo que tiene es Object Storage compatible con S3, balanceadores de carga y Volumes. El resto, lo montas tú.",[70,14038,14039,14042],{},[27,14040,14041],{},"Verificación de registro puede demorar"," — los primeros usuarios reportan hasta 48 horas para liberar la cuenta nueva. En algunos casos Hetzner pide selfie con documento.",[19,14044,14046],{"id":14045},"digitalocean-el-all-around","DigitalOcean — el all-around",[12,14048,14049],{},"DigitalOcean es la opción que aparece delante de casi todo indie hacker brasileño en 2026, y por buena razón. El producto tiene 14 años, la interfaz es la mejor del segmento, la documentación es referencia, la comunidad brasileña es enorme. El precio es más alto que Hetzner en valor absoluto, pero viene envuelto en UX y servicios gestionados que ahorran horas de trabajo.",[368,14051,14053],{"id":14052},"cuanto-cuesta-un-droplet-digitalocean-en-2026","¿Cuánto cuesta un Droplet DigitalOcean en 2026?",[12,14055,14056],{},"La línea Basic tiene tres sabores: Regular Intel, Premium Intel y Premium AMD. Al cambio de R$5\u002Fdólar:",[2735,14058,14059,14068,14077,14086,14095],{},[70,14060,14061,14064,14065,101],{},[27,14062,14063],{},"Basic 1 GB \u002F 1 vCPU \u002F 25 GB SSD",": $4-6\u002Fmes — ",[27,14066,14067],{},"R$20-30",[70,14069,14070,14073,14074,101],{},[27,14071,14072],{},"Basic 2 GB \u002F 1 vCPU \u002F 50 GB SSD",": $12\u002Fmes — ",[27,14075,14076],{},"R$60",[70,14078,14079,14082,14083,101],{},[27,14080,14081],{},"Basic 4 GB \u002F 2 vCPU \u002F 80 GB SSD",": $24\u002Fmes — ",[27,14084,14085],{},"R$120",[70,14087,14088,14091,14092,101],{},[27,14089,14090],{},"Basic 8 GB \u002F 4 vCPU \u002F 160 GB SSD",": $48\u002Fmes — ",[27,14093,14094],{},"R$240",[70,14096,14097,14100,14101,101],{},[27,14098,14099],{},"Basic 16 GB \u002F 8 vCPU \u002F 320 GB SSD",": $96\u002Fmes — ",[27,14102,14103],{},"R$480",[12,14105,14106,14107,14110],{},"Todos incluyen ",[27,14108,14109],{},"1 TB de tráfico de salida por mes",", con excedente a $0,01\u002FGB — bastante más barato que AWS, pero lejos de los 20 TB de Hetzner.",[368,14112,14114],{"id":14113},"cual-es-la-latencia-digitalocean-para-sao-paulo","¿Cuál es la latencia DigitalOcean para São Paulo?",[12,14116,14117],{},"DigitalOcean opera 14 regiones. No hay presencia directa en América del Sur, pero las regiones más cercanas tienen latencia aceptable:",[2735,14119,14120,14126,14132,14138],{},[70,14121,14122,14125],{},[27,14123,14124],{},"NYC (Nueva York)",": ~120ms",[70,14127,14128,14131],{},[27,14129,14130],{},"TOR (Toronto)",": ~140ms",[70,14133,14134,14137],{},[27,14135,14136],{},"SFO (San Francisco)",": ~180ms",[70,14139,14140,14143],{},[27,14141,14142],{},"AMS (Ámsterdam)",": ~210ms",[12,14145,14146],{},"NYC es la elección obvia para cualquier público que tenga brasileños como audiencia principal. 120ms es la franja en que un botón respondiendo \"justo después del clic\" todavía parece inmediato para ojos no entrenados.",[368,14148,14150],{"id":14149},"donde-digitalocean-brilla","Donde DigitalOcean brilla",[2735,14152,14153,14159,14165,14171,14177,14183],{},[70,14154,14155,14158],{},[27,14156,14157],{},"Interfaz web",": la mejor del segmento. Levanta un Droplet en 60 segundos, monta firewall en tres clics, registra un dominio, configura DNS, instala una base de datos gestionada.",[70,14160,14161,14164],{},[27,14162,14163],{},"Marketplace one-click",": WordPress, Ghost, GitLab, Mattermost, MongoDB, decenas de stacks listas.",[70,14166,14167,14170],{},[27,14168,14169],{},"Managed Postgres \u002F MySQL \u002F Redis",": bases gestionadas con backup automático, failover, réplica de lectura. A partir de $15\u002Fmes — caro, pero ahorra un SRE.",[70,14172,14173,14176],{},[27,14174,14175],{},"App Platform",": serverless con deploy vía Git, autoscaling, certificados Let's Encrypt automáticos. A partir de $5\u002Fmes.",[70,14178,14179,14182],{},[27,14180,14181],{},"Comunidad brasileña activa",": tutoriales en portugués, foro, Discord no oficial, ex-empleado hablando en conferencia.",[70,14184,14185,14188],{},[27,14186,14187],{},"Facturación en dólar con tarjeta internacional",", pero con checkout que acepta tarjeta BR sin fricción (ya está consolidado).",[368,14190,14192],{"id":14191},"donde-digitalocean-pierde","Donde DigitalOcean pierde",[2735,14194,14195,14201,14206,14212],{},[70,14196,14197,14200],{},[27,14198,14199],{},"Pricing",": 2-3× más caro que Hetzner por vCPU equivalente.",[70,14202,14203,14205],{},[27,14204,14017],{},": el más cercano es NYC.",[70,14207,14208,14211],{},[27,14209,14210],{},"Algunos productos pricier que AWS",": Spaces (Object Storage compatible con S3) cuesta $5\u002Fmes con 250 GB; el equivalente en S3 cuesta $1.50\u002Fmes con la misma clase de durabilidad.",[70,14213,14214,14217],{},[27,14215,14216],{},"Networking simple",": VPC entre regiones existe pero no es el producto bien pulido como en AWS.",[19,14219,14221],{"id":14220},"magalu-cloud-el-nacional","Magalu Cloud — el nacional",[12,14223,14224],{},"Magalu Cloud es el brazo de infraestructura del grupo Magazine Luiza. Lanzado en 2023, todavía está en maduración, pero en 2026 ya tiene oferta consistente de VPS, Object Storage, Kubernetes gestionado y soporte en portugués. Es la apuesta brasileña viable para quien necesita data residency.",[368,14226,14228],{"id":14227},"cuanto-cuesta-magalu-cloud-en-2026","¿Cuánto cuesta Magalu Cloud en 2026?",[12,14230,14231],{},"Los planes que importan para startup, con estimaciones de tabla 2026:",[2735,14233,14234,14240,14246,14252],{},[70,14235,14236,14239],{},[27,14237,14238],{},"vCPU 1 \u002F 1 GB RAM \u002F 25 GB SSD",": ~R$30\u002Fmes.",[70,14241,14242,14245],{},[27,14243,14244],{},"vCPU 2 \u002F 4 GB RAM \u002F 80 GB SSD",": ~R$80\u002Fmes.",[70,14247,14248,14251],{},[27,14249,14250],{},"vCPU 4 \u002F 8 GB RAM \u002F 160 GB SSD",": ~R$160\u002Fmes.",[70,14253,14254,14257],{},[27,14255,14256],{},"vCPU 8 \u002F 16 GB RAM \u002F 320 GB SSD",": ~R$320\u002Fmes.",[12,14259,14260],{},"Pricing en real, sin conversión cambiaria, sin IOF, con NF-e emitida.",[368,14262,14264],{"id":14263},"magalu-cloud-tiene-datacenter-en-brasil","¿Magalu Cloud tiene datacenter en Brasil?",[12,14266,14267,14268,2403,14271,14274,14275,14278],{},"Sí — ese es el punto entero del producto. Operación en ",[27,14269,14270],{},"Tamboré, São Paulo",[27,14272,14273],{},"Curitiba",", Paraná. Latencia de São Paulo capital a Tamboré: ",[27,14276,14277],{},"5-15ms",". Prácticamente indistinguible de loopback.",[368,14280,14282],{"id":14281},"donde-magalu-cloud-brilla","Donde Magalu Cloud brilla",[2735,14284,14285,14291,14297,14303],{},[70,14286,14287,14290],{},[27,14288,14289],{},"Data residency",": los datos quedan en Brasil. Para sectores regulados (salud con la LGPD sectorial, financiero con el Banco Central, gobierno) eso resuelve el argumento legal de una sola vez.",[70,14292,14293,14296],{},[27,14294,14295],{},"Facturación en real",": cuentas en CNPJ, NF-e emitida, conciliación contable simple.",[70,14298,14299,14302],{},[27,14300,14301],{},"Soporte en portugués",": chat y ticket responden en horario comercial brasileño, con gente que entiende el vocabulario del mercado nacional.",[70,14304,14305,14308],{},[27,14306,14307],{},"Latencia imbatible para usuario BR",": 5-15ms para cualquier punto del sudeste.",[368,14310,14312],{"id":14311},"donde-magalu-cloud-pierde","Donde Magalu Cloud pierde",[2735,14314,14315,14321,14327,14333,14339],{},[70,14316,14317,14320],{},[27,14318,14319],{},"Ecosistema en maduración",": Managed Postgres existe, pero con menos opciones de configuración que DigitalOcean. Object Storage compatible con S3 funciona, pero las integraciones de terceros no siempre están listas.",[70,14322,14323,14326],{},[27,14324,14325],{},"Comunidad pequeña",": tutoriales en portugués empezando a aparecer en 2025-2026, pero lejos de la base de DigitalOcean.",[70,14328,14329,14332],{},[27,14330,14331],{},"Rango de instancias menor",": tipos especializados de máquina (GPU, memoria optimizada, computación intensiva) todavía llegan en oleadas.",[70,14334,14335,14338],{},[27,14336,14337],{},"Madurez de SLA",": los primeros incidentes públicos fueron bien comunicados, pero el historial todavía es corto.",[70,14340,14341,14344],{},[27,14342,14343],{},"Más caro que Hetzner",": el VPS de 4 GB RAM cuesta R$80 en Magalu contra R$44 en Hetzner — casi el doble.",[19,14346,14348],{"id":14347},"lado-a-lado-12-criterios-que-importan","Lado a lado: 12 criterios que importan",[119,14350,14351,14366],{},[122,14352,14353],{},[125,14354,14355,14357,14360,14363],{},[128,14356,2983],{},[128,14358,14359],{},"Hetzner",[128,14361,14362],{},"DigitalOcean",[128,14364,14365],{},"Magalu Cloud",[141,14367,14368,14380,14394,14408,14422,14433,14445,14456,14469,14481,14491,14502],{},[125,14369,14370,14373,14375,14377],{},[146,14371,14372],{},"VPS 4 GB RAM, 2 vCPU (BRL\u002Fmes)",[146,14374,13910],{},[146,14376,14085],{},[146,14378,14379],{},"R$80",[125,14381,14382,14385,14388,14391],{},[146,14383,14384],{},"Tráfico salida 1 TB incluido",[146,14386,14387],{},"Sí (20 TB)",[146,14389,14390],{},"Sí (1 TB)",[146,14392,14393],{},"Sí (variable)",[125,14395,14396,14399,14402,14405],{},[146,14397,14398],{},"Datacenter más cercano de SP",[146,14400,14401],{},"Ashburn\u002FVA",[146,14403,14404],{},"NYC\u002FTOR",[146,14406,14407],{},"Tamboré\u002FSP",[125,14409,14410,14413,14416,14419],{},[146,14411,14412],{},"Latencia media SP (ms)",[146,14414,14415],{},"150-220",[146,14417,14418],{},"120-140",[146,14420,14421],{},"5-15",[125,14423,14424,14427,14429,14431],{},[146,14425,14426],{},"Datacenter en Brasil",[146,14428,3059],{},[146,14430,3059],{},[146,14432,3065],{},[125,14434,14435,14438,14440,14443],{},[146,14436,14437],{},"Managed Postgres",[146,14439,3059],{},[146,14441,14442],{},"Sí ($15+)",[146,14444,3065],{},[125,14446,14447,14450,14452,14454],{},[146,14448,14449],{},"Object Storage S3-compatible",[146,14451,3065],{},[146,14453,3065],{},[146,14455,3065],{},[125,14457,14458,14461,14464,14467],{},[146,14459,14460],{},"Balanceador de carga gestionado",[146,14462,14463],{},"Sí (€4,90)",[146,14465,14466],{},"Sí ($12)",[146,14468,3065],{},[125,14470,14471,14474,14476,14478],{},[146,14472,14473],{},"Comunidad BR\u002FPT-BR",[146,14475,4920],{},[146,14477,4915],{},[146,14479,14480],{},"Creciendo",[125,14482,14483,14485,14487,14489],{},[146,14484,14301],{},[146,14486,3059],{},[146,14488,3062],{},[146,14490,3065],{},[125,14492,14493,14496,14498,14500],{},[146,14494,14495],{},"Facturación en real (NF-e)",[146,14497,3059],{},[146,14499,3059],{},[146,14501,3065],{},[125,14503,14504,14506,14509,14512],{},[146,14505,13540],{},[146,14507,14508],{},"Hobby, MVP, B2B global",[146,14510,14511],{},"Indie hacker, B2C BR",[146,14513,14514],{},"B2B regulado, datos sensibles",[19,14516,14518],{"id":14517},"que-vps-es-mas-barato-para-una-startup-brasilena-en-2026","¿Qué VPS es más barato para una startup brasileña en 2026?",[12,14520,14521],{},"En pricing absoluto por vCPU y gigabyte de RAM, Hetzner gana de lejos. Un servidor de 4 GB RAM cuesta R$44 al mes en Hetzner contra R$120 en DigitalOcean y R$80 en Magalu Cloud. La diferencia es de 2-3× en el caso de DigitalOcean y casi 2× para Magalu.",[12,14523,14524],{},"Pero la cuenta total cambia cuando incluyes banda. DigitalOcean da 1 TB de salida incluido por droplet, Hetzner da 20 TB. Para una aplicación que sirve assets pesados (vídeo, imágenes, descargas) y supera el techo de banda, el cálculo aproxima a las dos. Para app web tradicional sin entrega masiva de medios, Hetzner sigue siendo más barato.",[12,14526,14527],{},"Magalu Cloud nunca va a ser el más barato en comparación directa. Pero cuando comparas contra \"DigitalOcean + IOF de 4,38% + spread cambiario de 2-3% + riesgo de variación cambiaria de 10-15% en el año\", el argumento financiero se acerca. Si tus ingresos también están en real, Magalu te saca del riesgo de volverte una empresa que paga R$120 hoy y R$160 en el próximo trimestre porque el real se devaluó.",[19,14529,14531],{"id":14530},"cual-tiene-mejor-latencia-para-usuario-brasileno","¿Cuál tiene mejor latencia para usuario brasileño?",[12,14533,14534],{},"El orden es directo:",[67,14536,14537,14543,14549,14555,14561,14567],{},[70,14538,14539,14542],{},[27,14540,14541],{},"Magalu Cloud (Tamboré)",": 5-15ms — categoría aparte.",[70,14544,14545,14548],{},[27,14546,14547],{},"DigitalOcean (NYC)",": 120ms — aceptable para B2C.",[70,14550,14551,14554],{},[27,14552,14553],{},"DigitalOcean (Toronto)",": 140ms — alternativa buena para NYC.",[70,14556,14557,14560],{},[27,14558,14559],{},"Hetzner (Ashburn, US East)",": 150ms — borderline para B2C.",[70,14562,14563,14566],{},[27,14564,14565],{},"Hetzner (Falkenstein, Alemania)",": 200-220ms — solo para B2B async u hobby.",[70,14568,14569,14572],{},[27,14570,14571],{},"Hetzner (Singapur)",": 300ms+ — no es una opción para Brasil.",[12,14574,14575],{},"La regla práctica que el equipo usa internamente: si el producto tiene botón que el usuario clica y espera respuesta inmediata, quédate en Magalu Cloud Tamboré o DigitalOcean NYC. Si el producto es asíncrono — webhook, procesamiento en background, dashboard que recarga cada 30 segundos — Hetzner Ashburn o Falkenstein resuelven con holgura.",[19,14577,14579],{"id":14578},"cual-elegir-para-correr-heroctl-coolify-o-dokploy-en-cluster-de-4-vps","¿Cuál elegir para correr HeroCtl, Coolify o Dokploy en cluster de 4 VPS?",[12,14581,14582],{},"Cluster auto-hospedado de orquestador es el caso donde los tres proveedores brillan, porque la mayor parte del tráfico es este-oeste interno (entre nodos) y la latencia cliente importa solo para el tráfico norte-sur (que va al Traefik o Caddy ingressante). Cálculo de costo absoluto por mes para tres configuraciones típicas:",[119,14584,14585,14597],{},[122,14586,14587],{},[125,14588,14589,14592,14594],{},[128,14590,14591],{},"Proveedor",[128,14593,4104],{},[128,14595,14596],{},"Costo mensual",[141,14598,14599,14612,14624],{},[125,14600,14601,14603,14606],{},[146,14602,14359],{},[146,14604,14605],{},"4× CPX21 (3 vCPU, 4 GB)",[146,14607,14608,14609],{},"€27,96 = ",[27,14610,14611],{},"R$155",[125,14613,14614,14616,14619],{},[146,14615,14362],{},[146,14617,14618],{},"4× Basic 4 GB (2 vCPU, 4 GB)",[146,14620,14621,14622],{},"$96 = ",[27,14623,14103],{},[125,14625,14626,14628,14631],{},[146,14627,14365],{},[146,14629,14630],{},"4× vCPU 2 \u002F 4 GB",[146,14632,14633],{},[27,14634,14635],{},"R$320",[12,14637,14638],{},"La diferencia entre Hetzner y DigitalOcean es R$325\u002Fmes — casi R$4.000\u002Faño. Para un indie hacker en fase pre-MRR o MRR bajo, eso es la diferencia entre un SaaS que paga sus propias cuentas y un SaaS que necesita aporte.",[12,14640,14641],{},"Para correr HeroCtl específicamente: el plano de control ocupa 200-400 MB de RAM por servidor, así que cualquiera de los tres proveedores tiene holgura sobrando para workload real. Tres de los cuatro nodos corren plano de control replicado (servidor); el cuarto corre solo agente. El cluster de demostración público usa esa topología exacta en cuatro servidores cloud, totalizando 5 vCPU y 10 GB de RAM, sirviendo cinco sitios con TLS automático y dieciséis contenedores activos.",[19,14643,14645],{"id":14644},"cuando-tiene-sentido-quedarse-en-proveedor-brasileno-tradicional-locaweb-kinghost-uol-host","¿Cuándo tiene sentido quedarse en proveedor brasileño tradicional (Locaweb, KingHost, UOL Host)?",[12,14647,14648],{},"Casi nunca, en la práctica. Los proveedores brasileños tradicionales — Locaweb, KingHost, UOL Host, HostGator BR — operan en un modelo heredado de reventa de hospedaje compartido, con VPS ofrecidos como producto secundario. El pricing es más alto que Magalu Cloud, la infra es menos moderna y el ecosistema es menor.",[12,14650,14651],{},"Los tres escenarios donde tiene sentido:",[67,14653,14654,14660,14666],{},[70,14655,14656,14659],{},[27,14657,14658],{},"Compliance que lista nominalmente un proveedor",": algunos contratos de gobierno o de grandes empresas exigen proveedor específico registrado en el SICAF o en listas internas. Si tu cliente exige Locaweb, es Locaweb.",[70,14661,14662,14665],{},[27,14663,14664],{},"NF-e como prioridad absoluta",": los tres (Hetzner no, DigitalOcean no, Magalu sí) emiten NF-e, pero algunos contratos B2B exigen proveedor brasileño reconocido públicamente.",[70,14667,14668,14671],{},[27,14669,14670],{},"Cliente exige soporte 24\u002F7 en portugués vía teléfono",": pocos proveedores cloud ofrecen eso. Locaweb tiene.",[12,14673,14674],{},"Para cualquier caso fuera de esos tres, la combinación Hetzner \u002F DigitalOcean \u002F Magalu Cloud cubre mejor con infra más moderna y pricing más previsible.",[19,14676,14678],{"id":14677},"escenarios-practicos-tres-perfiles-con-recomendacion","Escenarios prácticos: tres perfiles con recomendación",[368,14680,14682],{"id":14681},"perfil-1-hobby-project-1-vps-r0-de-ingresos","Perfil 1: hobby project \u002F 1 VPS \u002F R$0 de ingresos",[2735,14684,14685,14691,14699],{},[70,14686,14687,14690],{},[27,14688,14689],{},"Recomendación",": Hetzner CX11 o CAX11.",[70,14692,14693,14696,14697,101],{},[27,14694,14695],{},"Costo",": € 4,09\u002Fmes = ",[27,14698,13892],{},[70,14700,14701,14704],{},[27,14702,14703],{},"Por qué",": el público de un hobby project generalmente no es el cliente final exigiendo SLA. 200ms de latencia es tolerable. R$22\u002Fmes es el límite que un proyecto sin ingresos aguanta sin volverse peso. Instalas un orquestador ligero encima — HeroCtl Community Edition o Coolify — y corres decenas de apps en el mismo servidor.",[368,14706,14708],{"id":14707},"perfil-2-indie-hacker-cluster-de-4-vps-r10k-50k-mrr","Perfil 2: indie hacker \u002F cluster de 4 VPS \u002F R$10k-50k MRR",[2735,14710,14711,14716,14721],{},[70,14712,14713,14715],{},[27,14714,14689],{},": Hetzner CPX21 (4×) si público es global o B2B; DigitalOcean Basic 4 GB (4×) si público es B2C brasileño.",[70,14717,14718,14720],{},[27,14719,14695],{},": R$155\u002Fmes (Hetzner) o R$480\u002Fmes (DigitalOcean).",[70,14722,14723,14725],{},[27,14724,14703],{},": en ese rango de MRR, R$325 de diferencia todavía importa, pero la latencia percibida del usuario empieza a impactar conversión. Para B2C con público BR, la regla es DigitalOcean NYC. Para B2B donde el usuario es dev y clica en un dashboard que recarga cada minuto, Hetzner Falkenstein es más que aceptable.",[368,14727,14729],{"id":14728},"perfil-3-b2b-regulado-data-residency-4-8-vps-r200k-mrr","Perfil 3: B2B regulado \u002F data residency \u002F 4-8 VPS \u002F R$200k+ MRR",[2735,14731,14732,14737,14742],{},[70,14733,14734,14736],{},[27,14735,14689],{},": Magalu Cloud como primario, DigitalOcean NYC como secundario para DR, o AWS São Paulo si compliance exige proveedor con certificaciones específicas.",[70,14738,14739,14741],{},[27,14740,14695],{},": R$320-640\u002Fmes en Magalu, con adicionales por base gestionada y Object Storage.",[70,14743,14744,14746],{},[27,14745,14703],{},": en ese rango, el costo de infra es menor que el costo de cualquier auditoría reprobada. Data residency vale el premium. Magalu Cloud entrega eso con latencia excelente, facturación simple y soporte en portugués. DigitalOcean NYC queda como secundario para failover regional.",[19,14748,14750],{"id":14749},"puedo-usar-dos-proveedores-al-mismo-tiempo","¿Puedo usar dos proveedores al mismo tiempo?",[12,14752,14753],{},"Sí. La pregunta importante es si vale la complejidad.",[12,14755,14756],{},"La configuración que más aparece en la práctica es multi-provider en capas: producción en un proveedor, staging en otro más barato. Por ejemplo, producción en Magalu Cloud Tamboré (latencia BR), staging en Hetzner Falkenstein (costo mínimo). El equipo de dev accede a staging vía VPN para probar features; los clientes nunca ven el staging.",[12,14758,14759],{},"Otra configuración: distribuir un cluster auto-hospedado entre dos proveedores para resiliencia. Tres nodos en Hetzner Ashburn, un nodo en Hetzner Falkenstein — funciona porque la latencia intra-cluster aguanta el cross-region (40ms entre datacenters Hetzner). Mezclar Hetzner con DigitalOcean o Magalu Cloud en el mismo cluster orquestador es técnicamente posible pero malo en la práctica: latencia de 150-200ms entre nodos traba consenso distribuido.",[12,14761,14762],{},"La regla práctica: si no tienes un motivo concreto para múltiples proveedores, quédate en uno. La complejidad operacional se duplica con cada proveedor agregado. DNS, facturación, IAM, claves SSH, monitoreo, backup — todo duplicado.",[19,14764,14766],{"id":14765},"vale-la-pena-correr-cluster-auto-hospedado-en-vps-barato","¿Vale la pena correr cluster auto-hospedado en VPS barato?",[12,14768,14769],{},"Vale la pena, con reservas. La premisa del orquestador moderno es exactamente esa: tomas 3-4 VPS commodity y el software hace el trabajo de plano de control replicado, ruteo, certificados automáticos, rolling update. El costo mensual es una fracción de cualquier plataforma como servicio gestionada equivalente.",[12,14771,14772],{},"La reserva es que VPS barato viene con poca CPU y poca RAM. Hetzner CX11 tiene 1 vCPU y 2 GB de RAM — el plano de control ocupa 200-400 MB, sobra poco para workload real. Si tu aplicación es Node o Go, sobra. Si es Java con JVM glotona, no sobra. Para correr 3-4 nodos de cluster, prefiere CPX21 o CPX31 — 3-4 vCPU y 4-8 GB de RAM por nodo dan holgura para una decena de contenedores por nodo.",[12,14774,14775],{},"La otra reserva es gestión. VPS barato no viene con Managed Postgres del nivel de DigitalOcean. Si necesitas base gestionada, o pagas DigitalOcean para que corra el Postgres ($15\u002Fmes mínimo) o corres tu propio Postgres como contenedor en el cluster — con responsabilidad de backup, replicación y upgrade en tu mano.",[19,14777,3226],{"id":3225},[368,14779,13938],{"id":14780},"hetzner-tiene-datacenter-en-brasil-1",[12,14782,14783],{},"No. Hetzner opera datacenters en Alemania (Falkenstein, Núremberg), Finlandia (Helsinki), Estados Unidos (Ashburn en Virginia, Hillsboro en Oregón) y Singapur. No hay presencia sudamericana en 2026, y la empresa no ha anunciado planes públicos de expansión a la región.",[368,14785,14787],{"id":14786},"cuanto-cuesta-correr-4-vps-en-cada-uno-de-los-tres-proveedores-en-2026","¿Cuánto cuesta correr 4 VPS en cada uno de los tres proveedores en 2026?",[12,14789,14790],{},"En configuración equivalente de 4 GB RAM y 2-3 vCPU por nodo: Hetzner sale por aproximadamente R$155\u002Fmes total (4× CPX21 a € 7,99). DigitalOcean sale por R$480\u002Fmes (4× Basic 4 GB a $24). Magalu Cloud sale por R$320\u002Fmes (4× vCPU 2 \u002F 4 GB a R$80). La diferencia entre el más barato y el más caro es de 3× en valor absoluto.",[368,14792,14794],{"id":14793},"puedo-usar-dos-proveedores-vps-al-mismo-tiempo","¿Puedo usar dos proveedores VPS al mismo tiempo?",[12,14796,14797],{},"Sí, y en algunos escenarios tiene sentido. Configuraciones comunes: producción en un proveedor + staging en otro más barato; cluster distribuido entre regiones del mismo proveedor para resiliencia; primario en un proveedor + DR en otro para failover regional. Mezclar dos proveedores en el mismo cluster orquestador es técnicamente posible pero la latencia cross-provider (generalmente 100-200ms) traba consenso distribuido. La regla práctica es quedarse en un proveedor por carga, a menos que haya razón concreta.",[368,14799,14801],{"id":14800},"magalu-cloud-es-confiable-en-2026","¿Magalu Cloud es confiable en 2026?",[12,14803,14804],{},"Sí, con la reserva de que el historial todavía es corto. La operación inició en 2023, en 2026 tiene tres años de producción pública. Los incidentes que ocurrieron en ese período fueron comunicados públicamente y resueltos dentro de SLA típico. El ecosistema de servicios gestionados es menor que el de DigitalOcean o AWS, pero la oferta básica (VPS, Object Storage, Load Balancer, Kubernetes gestionado) está estable. Para workload que exige data residency brasileña, es la opción viable en 2026.",[368,14806,14808],{"id":14807},"digitalocean-tiene-soporte-en-portugues","¿DigitalOcean tiene soporte en portugués?",[12,14810,14811],{},"Limitado. La documentación oficial está en inglés con algunas secciones traducidas. El soporte por ticket acepta portugués, pero la primera respuesta viene generalmente en inglés. La comunidad brasileña (foros, Discord, tutoriales) es grande y cubre bien preguntas comunes en portugués. Para soporte enterprise, hay contratos pagados que incluyen atención en portugués, pero solo tienen sentido a partir de gasto mensual arriba de US$1.000.",[368,14813,14815],{"id":14814},"cual-es-la-latencia-aproximada-para-sao-paulo-en-cada-proveedor","¿Cuál es la latencia aproximada para São Paulo en cada proveedor?",[12,14817,14818],{},"Magalu Cloud (Tamboré y Curitiba): 5-15ms. DigitalOcean (NYC): 120ms. DigitalOcean (Toronto): 140ms. Hetzner (Ashburn, US East): 140-160ms. Hetzner (Hillsboro, US West): 170-190ms. Hetzner (Falkenstein, Alemania): 200-220ms. Hetzner (Singapur): 300ms+. Para B2C con público brasileño exigiendo respuesta inmediata, Magalu Cloud o DigitalOcean NYC. Para B2B asíncrono u hobby, cualquiera sirve.",[368,14820,14822],{"id":14821},"que-proveedor-acepta-pago-en-real-con-nf-e","¿Qué proveedor acepta pago en real con NF-e?",[12,14824,14825],{},"Solo Magalu Cloud entre los tres. Hetzner factura en euro con tarjeta de crédito internacional (más IOF de 4,38% y spread cambiario). DigitalOcean factura en dólar, también con tarjeta internacional, con checkout que acepta tarjeta BR sin fricción pero sin emisión de NF-e. Para quien necesita NF-e por exigencia fiscal o contable, Magalu Cloud es la única opción de las tres. Proveedores brasileños tradicionales (Locaweb, KingHost) también emiten NF-e pero tienen pricing menos competitivo.",[368,14827,14829],{"id":14828},"hetzner-acepta-tarjeta-brasilena","¿Hetzner acepta tarjeta brasileña?",[12,14831,14832],{},"Sí, pero con fricción. Tarjetas de crédito brasileñas internacionales (Visa, Mastercard) son aceptadas. La primera cobranza suele pasar por verificación adicional — Hetzner puede pedir comprobante de identidad, y en algunos casos selfie con documento. El proceso de registro puede tardar 24-48 horas hasta la primera liberación de servidor. Después de eso, las cobranzas mensuales pasan normalmente. Tarjetas prepagadas y tarjetas virtuales generalmente no son aceptadas.",[368,14834,14766],{"id":14835},"vale-la-pena-correr-cluster-auto-hospedado-en-vps-barato-1",[12,14837,14838],{},"Vale la pena, y es el caso de uso central para orquestadores ligeros como HeroCtl. Cuatro VPS Hetzner CPX21 totalizan 12 vCPU y 16 GB de RAM por R$155\u002Fmes — capacidad equivalente a un único servidor mediano en proveedores caros, por el costo de un almuerzo. El plano de control ocupa 200-400 MB de RAM por servidor, sobra holgura para hospedar decenas de contenedores. Las reservas son: prefiere instancias con al menos 3 vCPU y 4 GB de RAM (CPX21+ o equivalente); base gestionada fuera del cluster o base como contenedor con backup manual; y ten un plan de monitoreo propio — VPS barato no viene con observabilidad lista.",[19,14840,3310],{"id":3309},[12,14842,14843],{},"No existe ganador universal entre Hetzner, DigitalOcean y Magalu Cloud. Existe ganador por perfil de uso. Hetzner para costo absoluto. DigitalOcean para UX y latencia razonable para público brasileño. Magalu Cloud para data residency y facturación en real.",[12,14845,14846],{},"La mayoría de los equipos indie empieza en Hetzner, migra parte de la carga a DigitalOcean cuando el producto exige menor latencia para B2C, y considera Magalu Cloud cuando aparece el primer contrato con cláusula de data residency. Los tres coexisten en la cartera de muchas startups maduras — cada uno cumpliendo un papel.",[12,14848,14849],{},"Para cualquiera de los tres, un cluster auto-hospedado de 3-4 nodos con un orquestador ligero te da la fundación para correr decenas de aplicaciones sin pagar plataforma como servicio para cada una. HeroCtl Community Edition es gratuito e instala en un comando:",[224,14851,14852],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,14853,14854],{"__ignoreMap":229},[234,14855,14856,14858,14860,14862,14864],{"class":236,"line":237},[234,14857,1220],{"class":247},[234,14859,2958],{"class":251},[234,14861,2961],{"class":255},[234,14863,2964],{"class":383},[234,14865,2967],{"class":247},[12,14867,14868],{},"Los primeros tres servidores forman un plano de control replicado, certificados Let's Encrypt automáticos, rolling update sin ventana de mantenimiento, panel web embebido. El cluster público de demostración corre en cuatro servidores totalizando 5 vCPU y 10 GB de RAM, hospedando cinco sitios en producción.",[12,14870,14871],{},"Para los próximos pasos, dos posts relacionados que profundizan tópicos adyacentes:",[2735,14873,14874,14879],{},[70,14875,14876,14878],{},[3337,14877,6338],{"href":6337}," — análisis detallado de TCO incluyendo banda, base, monitoreo.",[70,14880,14881,14885],{},[3337,14882,14884],{"href":14883},"\u002Fes\u002Fblog\u002Falternativa-kubernetes-paas-auto-hospedado","Alternativa Kubernetes \u002F PaaS auto-hospedado"," — comparación entre orquestadores ligeros para equipos pequeños.",[12,14887,14888],{},"La elección de proveedor es importante, pero es una decisión reversible. La elección de orquestador es más difícil de revertir — empieza por el software que va a sostener tu stack durante los próximos cinco años, después elige dónde va a correr.",[3351,14890,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":14892},[14893,14894,14900,14906,14912,14913,14914,14915,14916,14917,14922,14923,14924,14935],{"id":13863,"depth":244,"text":13864},{"id":13870,"depth":244,"text":13871,"children":14895},[14896,14897,14898,14899],{"id":13877,"depth":271,"text":13878},{"id":13937,"depth":271,"text":13938},{"id":13982,"depth":271,"text":13983},{"id":14009,"depth":271,"text":14010},{"id":14045,"depth":244,"text":14046,"children":14901},[14902,14903,14904,14905],{"id":14052,"depth":271,"text":14053},{"id":14113,"depth":271,"text":14114},{"id":14149,"depth":271,"text":14150},{"id":14191,"depth":271,"text":14192},{"id":14220,"depth":244,"text":14221,"children":14907},[14908,14909,14910,14911],{"id":14227,"depth":271,"text":14228},{"id":14263,"depth":271,"text":14264},{"id":14281,"depth":271,"text":14282},{"id":14311,"depth":271,"text":14312},{"id":14347,"depth":244,"text":14348},{"id":14517,"depth":244,"text":14518},{"id":14530,"depth":244,"text":14531},{"id":14578,"depth":244,"text":14579},{"id":14644,"depth":244,"text":14645},{"id":14677,"depth":244,"text":14678,"children":14918},[14919,14920,14921],{"id":14681,"depth":271,"text":14682},{"id":14707,"depth":271,"text":14708},{"id":14728,"depth":271,"text":14729},{"id":14749,"depth":244,"text":14750},{"id":14765,"depth":244,"text":14766},{"id":3225,"depth":244,"text":3226,"children":14925},[14926,14927,14928,14929,14930,14931,14932,14933,14934],{"id":14780,"depth":271,"text":13938},{"id":14786,"depth":271,"text":14787},{"id":14793,"depth":271,"text":14794},{"id":14800,"depth":271,"text":14801},{"id":14807,"depth":271,"text":14808},{"id":14814,"depth":271,"text":14815},{"id":14821,"depth":271,"text":14822},{"id":14828,"depth":271,"text":14829},{"id":14835,"depth":271,"text":14766},{"id":3309,"depth":244,"text":3310},"2026-04-29","Hetzner es 3-5× más barato pero sin datacenter en Brasil. DigitalOcean tiene más regiones pero cuesta más. Magalu Cloud es nacional pero en maduración. Análisis honesto con latencia, costo, y cuándo cada uno tiene sentido.",{},"\u002Fes\u002Fblog\u002Fhetzner-vs-digitalocean-vs-magalu-cloud",{"title":13852,"description":14937},{"loc":14939},"es\u002Fblog\u002Fhetzner-vs-digitalocean-vs-magalu-cloud",[14944,14945,14946,14947,14948,14949],"hetzner","digitalocean","magalu-cloud","vps","comparacion","brasil","ZtTtQrMkaOWCjZZ8vACqMsExv6ntj47NlGU4nLc0X8c",{"id":14952,"title":14953,"author":7,"body":14954,"category":6382,"cover":3380,"date":15808,"description":15809,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":15810,"navigation":411,"path":6337,"readingTime":6387,"seo":15811,"sitemap":15812,"stem":15813,"tags":15814,"__hash__":15818},"blog_es\u002Fes\u002Fblog\u002Fcuanto-cuesta-alojar-un-saas-2026.md","Cuánto cuesta alojar un SaaS en 2026: la planilla abierta",{"type":9,"value":14955,"toc":15792},[14956,14959,14962,14966,14969,14972,14979,14986,14989,14993,14996,15000,15003,15009,15014,15136,15139,15145,15148,15152,15155,15160,15164,15249,15256,15261,15265,15268,15273,15342,15353,15358,15361,15365,15368,15372,15419,15422,15427,15434,15437,15441,15444,15450,15456,15465,15471,15477,15483,15487,15493,15615,15618,15621,15625,15628,15634,15640,15646,15652,15656,15659,15665,15671,15677,15683,15687,15690,15697,15704,15711,15718,15725,15727,15733,15739,15745,15751,15757,15763,15769,15771,15774,15777,15782],[12,14957,14958],{},"El primer gasto que mata margen de un SaaS no es nómina. No son impuestos. No es adquisición de cliente. Es infraestructura pagada en dólar mientras el cliente paga en moneda local. Ese desajuste es silencioso el primer año, incómodo el segundo, y compromete la tesis entera del negocio el tercero — cuando el equipo descubre que cada cuenta nueva trajo consigo una porción desproporcionada de proveedor de nube.",[12,14960,14961],{},"Este post es la planilla abierta. Sin buzzword, sin \"depende del caso\", sin economías hipotéticas. Cuatro escenarios de SaaS divididos por etapa de ingreso, con tabla de coste lado a lado, decisión honesta en cada uno y la cuenta total al final. Los números fueron medidos en proveedores reales en abril de 2026, con cambio de referencia de R$5 por dólar — número que puede oscilar, pero que sirve para calibrar el orden de magnitud.",[19,14963,14965],{"id":14964},"la-asimetria-que-nadie-explica-en-pitch-deck","La asimetría que nadie explica en pitch deck",[12,14967,14968],{},"Imagina un SaaS que acaba de pegar US$10k de MRR. Al cambio actual, eso es cerca de R$50k al mes. Parece un número saludable — paga salarios, paga impuesto, sobra capital. El fundador mira el balance y respira aliviado.",[12,14970,14971],{},"Ahora suma un stack típico de SaaS moderno: Vercel para front, base gestionada en un proveedor cloud, Datadog para observabilidad, Sentry para error, Redis Premium para cola y cache. Round number, US$1.500 al mes. Quince por ciento del MRR. ¿Parece mucho? Comparado con el competidor americano, es la misma proporción: él también tiene US$10k de MRR y gasta US$1.500. Empate técnico.",[12,14973,14974,14975,14978],{},"Solo que no es empate. Mira la nómina: un dev brasileño semi-senior cuesta alrededor de R$15k. Un americano equivalente cuesta US$10k, o R$50k. El brasileño paga, ",[27,14976,14977],{},"proporcionalmente, tres veces más por alojamiento en relación con su propio coste de mano de obra",". La planilla del americano cierra gastando 15% en infra y 50% en salarios. La del brasileño cierra gastando 15% en infra y 30% en salarios — quedando, después de impuestos, una fracción estrecha para crecer.",[12,14980,14981,14982,14985],{},"La conclusión es incómoda y la mayoría de los pitch decks la evita: la estrategia de infraestructura que funciona para startup del Valle del Silicio ",[27,14983,14984],{},"no funciona"," para startup de mercado emergente. Las cuentas son distintas desde el día uno. Cobrar en moneda local, pagar en dólar, y aún querer copiar el stack del Sequoia portfolio es una ecuación que solo cierra mientras el inversor esté subsidiando.",[12,14987,14988],{},"La buena noticia: el coste de infraestructura es el gasto con más palanca de reducción en todo el P&L de un SaaS pequeño o mediano. Más incluso que nómina — porque no puedes despedir a un dev y seguir entregando el roadmap, pero puedes cambiar Render por VPS y seguir exactamente con el mismo producto. Lo que falta es ver la planilla abierta.",[19,14990,14992],{"id":14991},"los-cuatro-escenarios-por-etapa-de-ingreso","Los cuatro escenarios por etapa de ingreso",[12,14994,14995],{},"La división por MRR es deliberada. Cada rango tiene necesidades operacionales distintas, exigencias de uptime distintas, y — crucialmente — un coste de oportunidad del tiempo del equipo distinto. Tratar todos los SaaS como si fueran lo mismo es la raíz de la mayoría de las decisiones erradas.",[368,14997,14999],{"id":14998},"escenario-a-pre-revenue-mvp-r0-a-r5k-mrr","Escenario A — Pre-revenue \u002F MVP (R$0 a R$5k MRR)",[12,15001,15002],{},"Esta es la etapa en la que cada centena de reales ahorrada vale como mil. No hay cliente exigiendo SLA, no hay auditoría, no hay equipo grande para coordinar. El objetivo es estar de pie, validar la hipótesis, y hacer entrar el primer real.",[12,15004,15005,15008],{},[27,15006,15007],{},"Stack típico:"," Render free tier, Railway hobby, Vercel pro plan, o un único servidor virtual en proveedor barato con Coolify.",[12,15010,15011],{},[27,15012,15013],{},"Tabla detallada (precio mensual):",[119,15015,15016,15034],{},[122,15017,15018],{},[125,15019,15020,15022,15025,15028,15031],{},[128,15021,11393],{},[128,15023,15024],{},"Render",[128,15026,15027],{},"Railway",[128,15029,15030],{},"Vercel",[128,15032,15033],{},"VPS + Coolify",[141,15035,15036,15053,15069,15083,15109],{},[125,15037,15038,15041,15044,15047,15050],{},[146,15039,15040],{},"Aplicación web",[146,15042,15043],{},"gratis (con límite)",[146,15045,15046],{},"US$5",[146,15048,15049],{},"US$20",[146,15051,15052],{},"incluido en el VPS",[125,15054,15055,15058,15061,15063,15066],{},[146,15056,15057],{},"Base Postgres",[146,15059,15060],{},"US$7",[146,15062,15046],{},[146,15064,15065],{},"KV (US$0,50\u002FM ops)",[146,15067,15068],{},"incluido",[125,15070,15071,15074,15076,15078,15081],{},[146,15072,15073],{},"Redis \u002F cache",[146,15075,15060],{},[146,15077,15046],{},[146,15079,15080],{},"KV US$5",[146,15082,15068],{},[125,15084,15085,15090,15095,15100,15105],{},[146,15086,15087],{},[27,15088,15089],{},"Total mensual USD",[146,15091,15092],{},[27,15093,15094],{},"US$14",[146,15096,15097],{},[27,15098,15099],{},"US$15",[146,15101,15102],{},[27,15103,15104],{},"US$25",[146,15106,15107],{},[27,15108,15046],{},[125,15110,15111,15116,15121,15126,15131],{},[146,15112,15113],{},[27,15114,15115],{},"Total mensual BRL",[146,15117,15118],{},[27,15119,15120],{},"R$70",[146,15122,15123],{},[27,15124,15125],{},"R$75",[146,15127,15128],{},[27,15129,15130],{},"R$125",[146,15132,15133],{},[27,15134,15135],{},"R$25–R$30",[12,15137,15138],{},"La diferencia bruta — VPS corriendo Coolify costando un quinto de la opción más barata gestionada — es el efecto directo de cortar el intermediario. Asumes el trabajo de instalar Postgres en un contenedor, configurar backup, abrir puerto en el firewall. A cambio, pagas R$25 en lugar de R$125.",[12,15140,15141,15144],{},[27,15142,15143],{},"Decisión honesta:"," el VPS con Coolify es cuatro a cinco veces más barato. Pero cuesta entre dos y cuatro horas al mes de mantenimiento (actualización de paquetes, chequeo de backup, ocasional reboot). Para un MVP con R$0 de ingreso real y dos fundadores que aún tienen empleo diurno, la ecuación tiempo-versus-dinero pende hacia el dinero: ahorrar R$100 al mes los primeros doce meses son R$1.200 que pagan el registro de marca, tres meses de dominio, o los primeros R$ de Google Ads cuando se pueda invertir.",[12,15146,15147],{},"Atajo contraintuitivo: si tu única dolencia es \"no quiero aprender Linux\", contrata el VPS gestionado de Locaweb o KingHost. Es más caro que Hetzner, más barato que Vercel, y el soporte habla portugués.",[368,15149,15151],{"id":15150},"escenario-b-indie-hacker-micro-saas-r5k-a-r30k-mrr","Escenario B — Indie hacker \u002F micro-SaaS (R$5k a R$30k MRR)",[12,15153,15154],{},"Aquí ya hay cliente. Hay un poco de imprevisibilidad — pico en horario comercial, caída por la noche, brote estacional a fin de mes cuando sale la factura. Single-server empieza a doler porque una caída tira a todos los clientes al mismo tiempo.",[12,15156,15157,15159],{},[27,15158,15007],{}," Render Pro, Railway escalado, Postgres gestionado en algún lugar, monitoreo básico.",[12,15161,15162],{},[27,15163,15013],{},[119,15165,15166,15180],{},[122,15167,15168],{},[125,15169,15170,15172,15174,15177],{},[128,15171,14591],{},[128,15173,4104],{},[128,15175,15176],{},"USD",[128,15178,15179],{},"BRL",[141,15181,15182,15195,15208,15222,15235],{},[125,15183,15184,15186,15189,15192],{},[146,15185,15024],{},[146,15187,15188],{},"instance Pro US$25 + Postgres US$25 + Redis US$7",[146,15190,15191],{},"US$57",[146,15193,15194],{},"R$285",[125,15196,15197,15199,15202,15205],{},[146,15198,15027],{},[146,15200,15201],{},"tier de uso variable, app + base + Redis",[146,15203,15204],{},"US$30–US$80",[146,15206,15207],{},"R$150–R$400",[125,15209,15210,15213,15216,15219],{},[146,15211,15212],{},"Vercel Team",[146,15214,15215],{},"2 seats + bandwidth + functions",[146,15217,15218],{},"US$80–US$150",[146,15220,15221],{},"R$400–R$750",[125,15223,15224,15226,15229,15232],{},[146,15225,15033],{},[146,15227,15228],{},"1 servidor 4 vCPU 8 GB",[146,15230,15231],{},"US$10",[146,15233,15234],{},"R$50",[125,15236,15237,15240,15243,15246],{},[146,15238,15239],{},"HeroCtl Community + 3 VPS Hetzner",[146,15241,15242],{},"3 nodos con alta disponibilidad real",[146,15244,15245],{},"€15",[146,15247,15248],{},"R$90",[12,15250,15251,15252,15255],{},"La última línea es donde el argumento cambia de naturaleza. Por R$90 al mes — menos que el tier más barato de Render — tienes un cluster con ",[27,15253,15254],{},"tres servidores de verdad",", con plano de control replicado, elección automática de coordinador en cerca de siete segundos cuando un nodo cae, certificado HTTPS automático y router integrado. El coste total del stack es menor que la cena del equipo un viernes. Y el uptime real, una vez configurado, es mejor que el del single-server gestionado, porque la caída de un nodo deja a los otros dos sirviendo tráfico.",[12,15257,15258,15260],{},[27,15259,15143],{}," self-hosted simple en un solo servidor es tres a cinco veces más barato que hospedado, pero cambia disponibilidad por economía. Cluster con alta disponibilidad real (HeroCtl Community en tres VPS) aún cuesta la mitad que el Render Pro single-server, y da garantía operacional que el Render single-server no da. La diferencia mensual de R$200 a R$500 es, a lo largo del año, equivalente a un almuerzo al día del equipo entero. Para un indie hacker, eso es diferencia entre comprar curso nuevo, ir a un evento o simplemente respirar más profundo en el flujo de caja.",[368,15262,15264],{"id":15263},"escenario-c-startup-early-stage-r30k-a-r200k-mrr","Escenario C — Startup early stage (R$30k a R$200k MRR)",[12,15266,15267],{},"Aquí aparecen requisitos reales de SLA. Cliente B2B empieza a preguntar sobre disponibilidad, backup, retención de log. Va a necesitar monitoreo más serio, quizás auditoría, ciertamente backup gestionado y procesos de recuperación.",[12,15269,15270],{},[27,15271,15272],{},"Stack típico gestionado:",[119,15274,15275,15287],{},[122,15276,15277],{},[125,15278,15279,15281,15284],{},[128,15280,4104],{},[128,15282,15283],{},"USD\u002Fmes",[128,15285,15286],{},"BRL\u002Fmes",[141,15288,15289,15300,15309,15320,15331],{},[125,15290,15291,15294,15297],{},[146,15292,15293],{},"AWS gestionado (cluster small + RDS Postgres + ElastiCache + balanceador de carga + NAT + CloudWatch + S3)",[146,15295,15296],{},"US$1.500–US$3.000",[146,15298,15299],{},"R$7.500–R$15.000",[125,15301,15302,15305,15307],{},[146,15303,15304],{},"GCP gestionado equivalente (cluster + CloudSQL + Memorystore)",[146,15306,15296],{},[146,15308,15299],{},[125,15310,15311,15314,15317],{},[146,15312,15313],{},"Render Team plan + escalado",[146,15315,15316],{},"US$300–US$600",[146,15318,15319],{},"R$1.500–R$3.000",[125,15321,15322,15325,15328],{},[146,15323,15324],{},"Cluster auto-hospedado (HeroCtl en 4 VPS Hetzner o DigitalOcean + storage S3-compatible)",[146,15326,15327],{},"US$60–US$120",[146,15329,15330],{},"R$300–R$600",[125,15332,15333,15336,15339],{},[146,15334,15335],{},"Híbrido (auto-hospedado + servicios críticos gestionados como base transaccional)",[146,15337,15338],{},"US$200–US$400",[146,15340,15341],{},"R$1.000–R$2.000",[12,15343,15344,15345,15348,15349,15352],{},"La diferencia entre AWS gestionado y auto-hospedado en esta etapa es la más significativa de toda la planilla. Estamos hablando de ",[27,15346,15347],{},"R$5.000 a R$12.000 al mes de economía recurrente",". Ese delta paga, a lo largo de doce meses, ",[27,15350,15351],{},"un desarrollador semi-senior al año entero",", o dos becarios, o — para startup que aún busca breakeven — seis meses adicionales de runway de capital.",[12,15354,15355,15357],{},[27,15356,15143],{}," auto-hospedar en esta etapa exige que el equipo tenga a alguien con competencia operacional. No necesita ser un especialista en gran escala dedicado a tiempo completo, pero necesita ser alguien que sabe leer log, sabe restaurar backup, sabe diagnosticar latencia. Generalmente es el CTO o el primer dev senior. El coste embebido ahí — cuatro a ocho horas al mes de ese profesional — es pequeño comparado con la economía. Pero existe, e ignorarlo es deshonesto.",[12,15359,15360],{},"Híbrido suele ser la respuesta correcta en esta etapa: aplicación corre en cluster auto-hospedado (porque es fácil), base transaccional queda gestionada (porque restaurar Postgres con replicación síncrona a las tres de la mañana no es trabajo de fin de semana de fundador). La cuenta híbrida queda alrededor de R$1.500 al mes — aún cuatro veces más barata que AWS gestionado completo.",[368,15362,15364],{"id":15363},"escenario-d-scale-up-r200k-mrr-equipo-de-plataforma-establecido","Escenario D — Scale-up (R$200k+ MRR, equipo de plataforma establecido)",[12,15366,15367],{},"Aquí la ecuación se invierte. Equipo tiene dos o tres ingenieros dedicados a infraestructura. Compliance puede estar en el mapa. Cliente exige SLA contractual con penalidad financiera. Multi-tenant con aislamiento serio es prerrequisito, no diferencial.",[12,15369,15370],{},[27,15371,15007],{},[119,15373,15374,15384],{},[122,15375,15376],{},[125,15377,15378,15380,15382],{},[128,15379,4104],{},[128,15381,15283],{},[128,15383,15286],{},[141,15385,15386,15397,15408],{},[125,15387,15388,15391,15394],{},[146,15389,15390],{},"AWS gestionado completo (multi-AZ, multi-region, observabilidad premium, soporte business)",[146,15392,15393],{},"US$5.000–US$15.000",[146,15395,15396],{},"R$25.000–R$75.000",[125,15398,15399,15402,15405],{},[146,15400,15401],{},"HeroCtl Enterprise + 8 a 12 servidores (con licencia Enterprise + soporte 24×7)",[146,15403,15404],{},"servidores R$2k–R$5k + licencia",[146,15406,15407],{},"R$2.000–R$5.000 + licencia",[125,15409,15410,15413,15416],{},[146,15411,15412],{},"Kubernetes auto-gestionado en proveedor cloud (servidores + 2 ingenieros senior en nómina)",[146,15414,15415],{},"US$3.000–US$10.000 servidores + R$60.000 nómina",[146,15417,15418],{},"R$75.000–R$110.000 totales",[12,15420,15421],{},"Nota que la comparación cambia. No es más \"infra pura\": es \"infra + coste del equipo para operar\". Kubernetes auto-gestionado es más barato en servidor, pero cobra dos salarios senior en nómina — es como comprar coche barato y contratar conductor a tiempo completo.",[12,15423,15424,15426],{},[27,15425,15143],{}," en esta etapa, el coste de infraestructura pasa a ser despreciable comparado al coste de equipo. Un equipo de plataforma de tres personas cuesta R$50k a R$80k al mes en nómina. R$20k al mes de servidor más o menos es ruido estadístico.",[12,15428,15429,15430,15433],{},"La optimización en esta etapa no es más sobre USD al mes, es sobre ",[27,15431,15432],{},"tiempo ahorrado por el equipo",". Si tu equipo de plataforma gasta dos días al mes resolviendo problema de operador especializado de Postgres, y la alternativa gestionada cuesta R$5k más — vale pagar. Si gasta media hora al mes porque el stack es simple, la alternativa cara no compra nada más allá de lujo.",[12,15435,15436],{},"AWS gestionado tiene sentido en esa fase cuando compliance pide explícitamente, cuando el cliente B2B serio lista proveedor cloud como prerrequisito de contrato, o cuando una certificación específica exige stack preaprobado. Auto-hospedado tiene sentido cuando el equipo consigue extraer valor de customización — telemetría fina, control de enrutamiento, aislamiento más agresivo de lo que el gestionado ofrece.",[19,15438,15440],{"id":15439},"los-costes-invisibles-que-nadie-calcula","Los costes invisibles que nadie calcula",[12,15442,15443],{},"Toda planilla de proveedor cloud tiene el mismo patrón: el \"precio de estantería\" es solo el comienzo. Los costes que aparecen en la factura al tercer mes — no al primero — son lo que separa a quien hizo la cuenta bien de quien va a descubrir el problema solo cuando el inversor pida el estado financiero.",[12,15445,15446,15449],{},[27,15447,15448],{},"Banda de salida (egress)."," Proveedor cloud americano tradicional cobra cerca de US$0,09 por gigabyte de salida. En reales, eso es R$0,45 por gigabyte. Un SaaS modesto con 100 GB de tráfico de salida al mes paga R$45 solo por dato saliendo del data center — y esa es la categoría más frecuentemente olvidada en proyección de presupuesto. Hetzner incluye 20 TB al mes de banda gratuita por servidor. En escala, la diferencia se vuelve fácilmente miles de reales al mes.",[12,15451,15452,15455],{},[27,15453,15454],{},"Logs."," El servicio de log gestionado de AWS cobra US$0,50 por gigabyte ingerido y US$0,03 por gigabyte almacenado. Aplicación típica genera entre 1 GB y 5 GB de log al mes por instancia. En cinco instancias con retención de seis meses, la cuenta sube a R$50 a R$200 al mes — invisible en la propuesta inicial.",[12,15457,15458,15461,15462,101],{},[27,15459,15460],{},"Monitoreo como servicio."," Datadog cobra US$15 por host al mes en la configuración estándar. New Relic cobra similar. Cinco hosts cuestan R$375 a R$500 al mes. Para startup en etapa early, eso es medio salario de becario ",[27,15463,15464],{},"solo en monitoreo",[12,15466,15467,15470],{},[27,15468,15469],{},"DNS."," El servicio gestionado de DNS de proveedor cloud cobra US$0,50 por zona y US$0,40 por millón de consultas. Es barato en valor absoluto, pero es la categoría que suele quedar fuera del presupuesto porque parece despreciable — hasta el momento en que cinco productos de la empresa cada uno tiene tres zonas y descubres US$30 al mes saliendo escondidos.",[12,15472,15473,15476],{},[27,15474,15475],{},"Retención de backup."," Snapshot diario con siete días de retención. Snapshot semanal con cuatro semanas. Snapshot mensual con doce meses. Política multiplica volumen por seis o siete. Gestión errónea de ciclo de vida puede doblar el coste de almacenamiento de una hora a otra.",[12,15478,15479,15482],{},[27,15480,15481],{},"Free tier que disminuye."," Proveedor cloud americano tradicional incluye 100 GB de salida gratuita al mes en la cuenta entera. Hetzner incluye 20 TB por servidor. La diferencia en escala es dramática — y es una de las razones por las que alojar en Alemania en proveedor europeo suele salir 30 a 50 por ciento más barato que alojar en São Paulo en el proveedor cloud tradicional, incluso contando latencia adicional.",[19,15484,15486],{"id":15485},"tabla-final-agregada-coste-total-ano-1-por-escenario","Tabla final agregada — coste total año 1 por escenario",[12,15488,15489,15490,101],{},"La tabla de abajo ata todo, expresando el coste de infra como porcentaje del MRR. Es la métrica que importa de verdad para el CFO: ",[27,15491,15492],{},"cuánto de cada real de ingreso se va a pagar servidor",[119,15494,15495,15514],{},[122,15496,15497],{},[125,15498,15499,15502,15505,15508,15511],{},[128,15500,15501],{},"Escenario",[128,15503,15504],{},"Stack",[128,15506,15507],{},"Coste año 1",[128,15509,15510],{},"MRR año 1",[128,15512,15513],{},"% del ingreso",[141,15515,15516,15533,15549,15566,15582,15599],{},[125,15517,15518,15521,15524,15527,15530],{},[146,15519,15520],{},"MVP en VPS + Coolify",[146,15522,15523],{},"1 servidor barato",[146,15525,15526],{},"R$360",[146,15528,15529],{},"R$60.000",[146,15531,15532],{},"0,6% — saludable",[125,15534,15535,15538,15541,15544,15546],{},[146,15536,15537],{},"MVP en hospedado caro",[146,15539,15540],{},"Vercel pro",[146,15542,15543],{},"R$1.500",[146,15545,15529],{},[146,15547,15548],{},"2,5% — aún OK",[125,15550,15551,15554,15557,15560,15563],{},[146,15552,15553],{},"Indie hacker en hospedado",[146,15555,15556],{},"Render Pro",[146,15558,15559],{},"R$3.500",[146,15561,15562],{},"R$240.000",[146,15564,15565],{},"1,5% — fine",[125,15567,15568,15571,15574,15577,15579],{},[146,15569,15570],{},"Indie hacker en auto-hospedado HA",[146,15572,15573],{},"HeroCtl Community + 3 VPS",[146,15575,15576],{},"R$1.000",[146,15578,15562],{},[146,15580,15581],{},"0,4% — excelente",[125,15583,15584,15587,15590,15593,15596],{},[146,15585,15586],{},"Startup en AWS gestionado",[146,15588,15589],{},"EKS + RDS + observabilidad",[146,15591,15592],{},"R$120.000 + 2 SREs (R$720k nómina)",[146,15594,15595],{},"R$2.400.000",[146,15597,15598],{},"35% — doliendo",[125,15600,15601,15604,15607,15610,15612],{},[146,15602,15603],{},"Startup en auto-hospedado",[146,15605,15606],{},"HeroCtl + 4 VPS + 1 dev part-time",[146,15608,15609],{},"R$10.000 + medio dev R$70k",[146,15611,15595],{},[146,15613,15614],{},"3% — saludable",[12,15616,15617],{},"La línea que más salta es la quinta. Treinta y cinco por ciento de R$2,4 millones de MRR en infra más equipo de operación dedicado. Para startup en esa etapa, es literalmente el punto que define si el año cierra lucrativo o en rojo.",[12,15619,15620],{},"La línea de abajo, con el mismo ingreso, cierra en tres por ciento de gasto. Treinta y dos puntos porcentuales de margen operacional adicionales. Eso no es optimización: es una decisión de arquitectura que cambia la categoría de negocio en que la empresa está.",[19,15622,15624],{"id":15623},"los-falsos-atajos","Los falsos atajos",[12,15626,15627],{},"En las conversaciones con fundadores, cuatro frases vuelven con frecuencia. Cada una suena razonable y cada una es una trampa específica.",[12,15629,15630,15633],{},[27,15631,15632],{},"\"Voy a empezar con todo gestionado y migro después.\""," La intención es buena: no distraer del producto ahora, optimizar después. Pero la migración de un stack gestionado completo a auto-hospedado lleva típicamente cuatro a seis meses de trabajo concentrado de al menos un senior — porque hay que reescribir automatización, rehacer pipeline de deploy, validar backup, entrenar al resto del equipo. Durante esos seis meses, el gasto sigue subiendo. Típicamente, en el momento de la migración, la empresa ya desperdició entre R$50.000 y R$100.000 más de lo que necesitaba.",[12,15635,15636,15639],{},[27,15637,15638],{},"\"El coste de oportunidad de mi equipo es mayor que el coste de infra.\""," Verdad para equipo grande, con cinco ingenieros senior dedicados a feature de producto. Mentira para equipo de dos o tres personas donde lo operacional real es \"un dev gasta cuatro horas al mes con servidor\". En ese escenario, el coste de oportunidad es ficticio — porque el tiempo gastado en servidor es tiempo que de otra forma sería gastado en reunión, o en revisión de código, o en tarea de producto que no es prioridad real.",[12,15641,15642,15645],{},[27,15643,15644],{},"\"Free tier es suficiente hasta validar.\""," Era verdad en 2018. En 2026, todos los proveedores disminuyeron free tier año tras año — algunos silenciosamente, otros con anuncio formal. Render free tier hibernando en quince minutos tumbó producción de gente que descubrió de la peor forma. Vercel free para proyecto personal se vuelve límite de bandwidth y function execution sorprendentemente pronto. La planilla tiene que hacerse asumiendo tier de pago desde el día uno — si sobra, óptimo, es caja.",[12,15647,15648,15651],{},[27,15649,15650],{},"\"Cloud local es más caro de todos modos.\""," Era verdad en 2020. En 2026, Hetzner Alemania sale 30 a 50 por ciento más barato que proveedor cloud tradicional en São Paulo, y la latencia adicional de 100 a 150 milisegundos es despreciable para la abrumadora mayoría de los workloads SaaS. Magalu Cloud ya compite en precio para cargas pequeñas y medianas. Locaweb y KingHost, aunque ya no son opción para escala, aún tienen tier inicial competitivo. La premisa \"cloud local es caro\" se volvió folclore — vale comprobar el precio actual antes de asumir.",[19,15653,15655],{"id":15654},"cuando-tiene-sentido-gastar-mas-en-infra","Cuándo tiene sentido GASTAR más en infra",[12,15657,15658],{},"Honestidad inversa: existen situaciones en que pagar más es la decisión correcta, y decir lo contrario sería vender ideología en lugar de solución. Cuatro casos en que vale el premium.",[12,15660,15661,15664],{},[27,15662,15663],{},"Equipo de una o dos personas sin nada de tiempo para cuidar de servidor."," Si eres fundador solo y tu propio día es ventas + producto + atención, cualquier hora gastada en servidor es hora no gastada en las actividades que generan ingreso. Vale pagar R$2.000 a R$5.000 al mes más por un stack totalmente gestionado. Estás comprando enfoque, no infraestructura.",[12,15666,15667,15670],{},[27,15668,15669],{},"Cliente B2B serio exige proveedor cloud listado."," Algunas empresas grandes (especialmente bancos, aseguradoras, gobierno) tienen cláusula contractual exigiendo que proveedores alojen en proveedor cloud específico. No es negociable; es prerrequisito de procurement. No hay opción — pagas el premium y sigues.",[12,15672,15673,15676],{},[27,15674,15675],{},"Compliance o auditoría que exige stack preaprobado."," Frameworks específicos (algunos relacionados a salud, pagos, o contratos de gobierno) listan herramientas nominalmente aprobadas. Si el auditor necesita apuntar a un certificado existente, y tu producto auto-hospedado no está en esa lista, la respuesta correcta es el gestionado tradicional. Argumentar con auditor es trabajo perdido.",[12,15678,15679,15682],{},[27,15680,15681],{},"Latencia crítica y red de borde es diferenciador real."," Si tu producto es juego, subasta en tiempo real, o trading, y cada milisegundo cuenta, la infraestructura de borde del proveedor americano tradicional o de Cloudflare es genuinamente distinta. Vale el premium. Pero nota: el 99 por ciento de los SaaS B2B no están en esa categoría, y decir que están es generalmente justificación post-facto para una elección que se hizo por hábito.",[19,15684,15686],{"id":15685},"heroctl-en-el-presupuesto-especificamente","HeroCtl en el presupuesto específicamente",[12,15688,15689],{},"Cinco hechos relevantes para el contexto:",[12,15691,15692,15693,15696],{},"Primero, el plan ",[27,15694,15695],{},"Community es gratuito permanente",", sin feature gate artificial. No hay versión limitada con asterisco — es el producto entero, alta disponibilidad real, router, certificado automático, métrica, log centralizado. Indie hacker y startup early stage pueden correr todo aquí para siempre.",[12,15698,15699,15700,15703],{},"Segundo, ",[27,15701,15702],{},"corre en cualquier cloud",": Hetzner Alemania, DigitalOcean, proveedor cloud tradicional, Magalu Cloud, KingHost, VPS de proveedor local pequeño. El cluster es el mismo binario en cualquier Linux con Docker. No hay dependencia de servicio gestionado de proveedor específico — cambias de proveedor sin rehacer nada.",[12,15705,15706,15707,15710],{},"Tercero, ",[27,15708,15709],{},"plan Business se cobra en moneda local",", sin volatilidad cambiaria repasada al cliente. Variación del dólar es nuestro problema, no el tuyo. Empresa pagando empresa en moneda local, contra contrato en moneda local.",[12,15712,15713,15714,15717],{},"Cuarto, ",[27,15715,15716],{},"precio está congelado para contratos existentes",". Lo que firmas hoy sigue valiendo en el aniversario del contrato. Cambio de tabla solo vale para contrato nuevo. No hay cláusula que permita reajuste retroactivo.",[12,15719,15720,15721,15724],{},"Quinto, ",[27,15722,15723],{},"soporte en portugués\u002Fespañol"," en los planes Business y Enterprise. Equipo hablando tu idioma, en tu huso, con contexto de mercado local.",[19,15726,4245],{"id":4244},[12,15728,15729,15732],{},[27,15730,15731],{},"¿Es más barato alojar fuera del país?"," En 2026, sí — Hetzner Alemania cuesta la mitad del proveedor tradicional en São Paulo para cargas equivalentes. La latencia adicional de cien a ciento cincuenta milisegundos es imperceptible para app web, API REST, dashboard, herramienta interna. Es perceptible para streaming, juego, voz en tiempo real. Para la abrumadora mayoría de SaaS B2B, alojar fuera es decisión financiera pura.",[12,15734,15735,15738],{},[27,15736,15737],{},"¿Magalu Cloud ya vale la pena en 2026?"," Para cargas pequeñas y medianas, sí. El precio es competitivo, la estabilidad está aceptable, y el soporte en portugués ayuda. Para cargas que exigen ecosistema profundo (cinco servicios gestionados orquestados), aún existen lagunas. Vale como proveedor primario para startup que valora proveedor local; vale menos para empresa que necesita catálogo completo de servicios.",[12,15740,15741,15744],{},[27,15742,15743],{},"¿Cuándo tiene sentido pagar proveedor cloud tradicional gestionado incluso siendo caro?"," Cuando compliance lista nombres específicos. Cuando cliente B2B exige en el contrato. Cuando el equipo tiene un especialista de gran escala en nómina por otras razones. Cuando latencia de borde es diferencial real del producto. Fuera de esos casos, es hábito más que decisión.",[12,15746,15747,15750],{},[27,15748,15749],{},"¿En cuánto tiempo compensa el coste de migración?"," Migración típica de proveedor gestionado caro a auto-hospedado cuesta entre R$30.000 y R$80.000 en tiempo de ingeniería (una o dos personas por dos a cuatro meses). La economía mensual post-migración paga esa inversión en tres a ocho meses en el rango del Escenario C. En horizonte de doce meses, la migración se paga ella misma y aún genera caja positiva.",[12,15752,15753,15756],{},[27,15754,15755],{},"¿Free tier aún existe en 2026?"," Existe, pero más restringido que en 2020. Render mantiene tier hibernante (no sirve producción). Railway tiene créditos iniciales. Vercel tiene hobby plan con límite. Hetzner no tiene free tier pero tiene servidor desde €4. La regla práctica actualizada: planea siempre tier de pago — si sobra tier gratuito, es bono.",[12,15758,15759,15762],{},[27,15760,15761],{},"¿Y si vendo a cliente que exige proveedor cloud específico en la arquitectura?"," Tienes dos opciones. Primera: aloja el producto principal donde sea mejor para el coste, y mantén un deploy separado en el proveedor exigido para atender a ese cliente específico. Segunda: HeroCtl corre dentro de proveedor cloud tradicional también — ganas el nombre del proveedor en el contrato, pero sin pagar el premium del servicio de cluster gestionado. Es un término medio que sirve auditoría sin destruir margen.",[12,15764,15765,15768],{},[27,15766,15767],{},"¿HeroCtl funciona en proveedor local pequeño?"," Sí. El requisito es Linux con Docker. Funciona en Locaweb, KingHost, Hostinger, Magalu Cloud, cualquier VPS razonable. Los clusters de demostración corren en cuatro servidores totalizando cinco vCPUs y diez gigabytes de RAM — cualquier proveedor local entrega configuración equivalente por valor competitivo.",[19,15770,3310],{"id":3309},[12,15772,15773],{},"La planilla abierta dice una cosa: la estrategia de infra que tiene sentido para startup de mercado emergente es distinta de la que tiene sentido para startup americana, y esa diferencia se vuelve punto de margen que separa a quien llega a la próxima ronda de quien quema caja contra proveedor.",[12,15775,15776],{},"Para empezar ahora — tres servidores baratos, alta disponibilidad real, certificado automático, panel web, sin coste recurrente de licencia:",[224,15778,15780],{"className":15779,"code":5318,"language":2530},[2528],[231,15781,5318],{"__ignoreMap":229},[12,15783,15784,15785,2403,15788,101],{},"Lectura relacionada: ",[3337,15786,15787],{"href":14883},"Alternativa a Kubernetes y PaaS auto-hospedado",[3337,15789,15791],{"href":15790},"\u002Fes\u002Fblog\u002Fkubernetes-overkill-cuando-no-lo-necesitas","Kubernetes overkill: cuándo no lo necesitas",{"title":229,"searchDepth":244,"depth":244,"links":15793},[15794,15795,15801,15802,15803,15804,15805,15806,15807],{"id":14964,"depth":244,"text":14965},{"id":14991,"depth":244,"text":14992,"children":15796},[15797,15798,15799,15800],{"id":14998,"depth":271,"text":14999},{"id":15150,"depth":271,"text":15151},{"id":15263,"depth":271,"text":15264},{"id":15363,"depth":271,"text":15364},{"id":15439,"depth":244,"text":15440},{"id":15485,"depth":244,"text":15486},{"id":15623,"depth":244,"text":15624},{"id":15654,"depth":244,"text":15655},{"id":15685,"depth":244,"text":15686},{"id":4244,"depth":244,"text":4245},{"id":3309,"depth":244,"text":3310},"2026-04-26","Ingreso en moneda local, coste en dólar. Para una startup, la infra es el primer gasto que mata margen. Comparación detallada de escenarios de alojamiento con números medidos.",{},{"title":14953,"description":15809},{"loc":6337},"es\u002Fblog\u002Fcuanto-cuesta-alojar-un-saas-2026",[13848,15815,15816,15817],"saas","infraestructura","presupuesto","hGKBybs_bpQSTNz_0_1NmpCE0CLkigUSRQr-py-nF3E",{"id":15820,"title":15821,"author":7,"body":15822,"category":3379,"cover":3380,"date":16732,"description":16733,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":16734,"navigation":411,"path":3344,"readingTime":3387,"seo":16735,"sitemap":16736,"stem":16737,"tags":16738,"__hash__":16742},"blog_es\u002Fes\u002Fblog\u002Fdeploy-docker-produccion-de-compose-a-cluster.md","Deploy de Docker en producción: de compose a cluster con alta disponibilidad",{"type":9,"value":15823,"toc":16718},[15824,15833,15836,15839,15843,15846,15849,15866,15869,15886,15889,15895,15899,15909,15914,15941,15946,15949,15954,15974,15979,15982,15987,16061,16064,16068,16071,16076,16093,16097,16100,16105,16112,16117,16120,16124,16127,16131,16134,16138,16169,16173,16176,16181,16184,16187,16191,16194,16199,16202,16206,16209,16213,16230,16234,16237,16242,16245,16250,16253,16257,16260,16264,16439,16442,16446,16449,16455,16461,16467,16473,16477,16480,16489,16495,16501,16505,16508,16525,16534,16548,16553,16562,16566,16569,16595,16602,16604,16616,16622,16628,16634,16654,16660,16670,16674,16677,16680,16696,16699,16712,16715],[12,15825,15826,15827,15829,15830,15832],{},"El flujo es familiar para cualquier dev que creció en los últimos cinco años. Escribes un ",[231,15828,9011],{}," con tres servicios, ejecutas ",[231,15831,12708],{}," en tu máquina, funciona. Lo subes a un VPS de staging, funciona. Lo mueves a producción apuntando el DNS, y funciona — hasta el primer viernes a las cinco de la tarde en que deja de funcionar.",[12,15834,15835],{},"El punto exacto en el que \"funciona en producción\" deja de ser verdad depende mucho menos de qué herramienta elegiste, y mucho más de qué estadio de madurez ha alcanzado tu producto. Este post mapea los cuatro estadios por los que casi todo equipo pasa, muestra las señales prácticas de que necesitas subir el escalón, y deja explícito cuándo aún no lo necesitas.",[12,15837,15838],{},"No es un post anti-compose, ni un post pro-cluster. Es un post sobre cuándo cabe cada cosa.",[19,15840,15842],{"id":15841},"por-que-docker-compose-funciono-tan-bien-en-desarrollo","Por qué Docker Compose funcionó tan bien en desarrollo",[12,15844,15845],{},"Antes de hablar de los estadios, vale la pena entender para qué fue diseñado Compose. Resuelve un problema muy específico y lo resuelve bien: orquestar múltiples contenedores en la misma máquina, declarando dependencias, redes, volúmenes y variables de entorno en un único archivo legible.",[12,15847,15848],{},"Las premisas embebidas en ese diseño son las premisas de quien está desarrollando:",[2735,15850,15851,15854,15857,15860,15863],{},[70,15852,15853],{},"Una sola máquina. La tuya.",[70,15855,15856],{},"Un solo usuario. Tú.",[70,15858,15859],{},"Restart manual. Cuando hay problema, abres el terminal y escribes.",[70,15861,15862],{},"Datos efímeros. Si la base se pone a cero, ejecutas el seed de nuevo.",[70,15864,15865],{},"Nadie depende de que esto esté de pie. Si se cae a las tres de la mañana, el mundo sigue.",[12,15867,15868],{},"En producción, las cinco premisas se invierten:",[2735,15870,15871,15874,15877,15880,15883],{},[70,15872,15873],{},"N máquinas. Ya no estás solo.",[70,15875,15876],{},"N usuarios. No te conocen.",[70,15878,15879],{},"Restart automático es exigencia mínima. Nadie va a despertarte a las cuatro de la mañana. Idealmente, nadie va a despertar a nadie.",[70,15881,15882],{},"Los datos importan. Perder la base se convierte en incidente reportable.",[70,15884,15885],{},"Alguien duerme con esto activo. Posiblemente un cliente, posiblemente un contrato con multa.",[12,15887,15888],{},"Docker Compose sigue funcionando fuera de las premisas originales. Hace que funcione — solo lo hace mal. Los atajos que parecen inocentes en desarrollo (red compartida entre servicios, volume montado directo en el host, log saliendo en el terminal) se convierten en trampas cuando el entorno cambia de \"una máquina donde sé todo lo que está corriendo\" a \"tres máquinas donde algo necesita estar corriendo veinticuatro horas al día\".",[12,15890,15891,15892,15894],{},"Los cuatro estadios a continuación muestran la curva natural de quien lleva el mismo ",[231,15893,9011],{}," desde el hobby hasta el SaaS con SLA contractual.",[19,15896,15898],{"id":15897},"estadio-1-compose-en-un-unico-vps","Estadio 1: Compose en un único VPS",[12,15900,15901,15902,15904,15905,15908],{},"El punto de entrada más honesto de Docker en producción. Un VPS barato, un archivo ",[231,15903,9011],{},", y ",[231,15906,15907],{},"docker compose up -d"," resolviendo la vida.",[12,15910,15911],{},[27,15912,15913],{},"Setup mínimo viable:",[2735,15915,15916,15919,15922,15929,15935],{},[70,15917,15918],{},"1 VPS con 1–2 vCPUs y 2 GB de RAM (cuesta unos 5 € al mes en proveedor decente).",[70,15920,15921],{},"Docker y Docker Compose instalados vía script oficial.",[70,15923,15924,15925,15928],{},"Todos los servicios con ",[231,15926,15927],{},"restart: always"," en el compose.",[70,15930,15931,15932,622],{},"Volúmenes nombrados para datos (no bind mounts apuntando a ",[231,15933,15934],{},"\u002Fopt\u002Fapp\u002Fdata",[70,15936,15937,15938,15940],{},"Un cron diario ejecutando ",[231,15939,5736],{}," y enviando a S3 o a un Backblaze B2.",[12,15942,15943],{},[27,15944,15945],{},"Para quién funciona:",[12,15947,15948],{},"Hobby projects, MVPs validando product-market fit, herramientas internas para el equipo, paneles administrativos privados, blogs personales. Cualquier aplicación donde la frase \"si está fuera cinco minutos, nadie muere\" es literalmente verdadera.",[12,15950,15951],{},[27,15952,15953],{},"Riesgos que estás aceptando explícitamente:",[2735,15955,15956,15959,15962,15971],{},[70,15957,15958],{},"El VPS se cae (mantenimiento del proveedor, pico de noisy neighbor, hardware) y tu servicio se cae con él. No hay fail-over.",[70,15960,15961],{},"El disco muere, y si no estás haciendo backup, perdiste los datos. Los SSDs de proveedor cloud fallan menos que los del data center antiguo, pero fallan. Sucede.",[70,15963,15964,15965,2403,15968,15970],{},"Cada deploy tiene una ventana de unos 30 segundos entre ",[231,15966,15967],{},"docker compose down",[231,15969,12708],{}," en la que el servicio queda fuera.",[70,15972,15973],{},"Tú eres el sysadmin. Patch de kernel, actualización de Docker, rotación de log, monitoreo de disco — todo en tu mano.",[12,15975,15976],{},[27,15977,15978],{},"Límites prácticos:",[12,15980,15981],{},"Aguanta cómodamente 1 a 3 aplicaciones pequeñas, tráfico del orden de 100 requests por segundo, y tolerancia de 5 a 30 minutos de downtime mensual. Si alguno de esos números se fuerza hacia arriba, estás abusando del estadio.",[12,15983,15984],{},[27,15985,15986],{},"El backup que nadie hace y debería hacer:",[224,15988,15990],{"className":226,"code":15989,"language":228,"meta":229,"style":229},"# \u002Fetc\u002Fcron.daily\u002Fdb-backup\ndocker exec postgres pg_dump -U app app \\\n  | gzip \\\n  | aws s3 cp - s3:\u002F\u002Fmeu-bucket\u002Fbackups\u002F$(date +%F).sql.gz\n",[231,15991,15992,15997,16019,16029],{"__ignoreMap":229},[234,15993,15994],{"class":236,"line":237},[234,15995,15996],{"class":240},"# \u002Fetc\u002Fcron.daily\u002Fdb-backup\n",[234,15998,15999,16001,16004,16007,16010,16013,16015,16017],{"class":236,"line":244},[234,16000,1118],{"class":247},[234,16002,16003],{"class":255}," exec",[234,16005,16006],{"class":255}," postgres",[234,16008,16009],{"class":255}," pg_dump",[234,16011,16012],{"class":251}," -U",[234,16014,421],{"class":255},[234,16016,421],{"class":255},[234,16018,9798],{"class":383},[234,16020,16021,16024,16027],{"class":236,"line":271},[234,16022,16023],{"class":383},"  |",[234,16025,16026],{"class":247}," gzip",[234,16028,9798],{"class":383},[234,16030,16031,16033,16036,16039,16042,16045,16048,16050,16052,16055,16058],{"class":236,"line":415},[234,16032,16023],{"class":383},[234,16034,16035],{"class":247}," aws",[234,16037,16038],{"class":255}," s3",[234,16040,16041],{"class":255}," cp",[234,16043,16044],{"class":255}," -",[234,16046,16047],{"class":255}," s3:\u002F\u002Fmeu-bucket\u002Fbackups\u002F",[234,16049,1708],{"class":387},[234,16051,1866],{"class":247},[234,16053,16054],{"class":255}," +%F",[234,16056,16057],{"class":387},")",[234,16059,16060],{"class":255},".sql.gz\n",[12,16062,16063],{},"Sin esto, no estás en producción. Estás en \"desarrollo expuesto en internet\". La diferencia entre uno y otro es exactamente este cron.",[19,16065,16067],{"id":16066},"estadio-2-compose-con-auto-update-y-router-por-delante","Estadio 2: Compose con auto-update y router por delante",[12,16069,16070],{},"La primera evolución natural. Sigues teniendo un VPS, pero ahora tiene dos pisos: un router que termina TLS y distribuye las peticiones, y los contenedores de la aplicación detrás de él.",[12,16072,16073],{},[27,16074,16075],{},"Setup:",[2735,16077,16078,16081,16084,16087,16090],{},[70,16079,16080],{},"1 VPS un poco más robusto (2–4 vCPUs, 4–8 GB), girando alrededor de 8 a 12 € al mes.",[70,16082,16083],{},"Misma stack del estadio anterior, más un reverse proxy (Caddy o un Traefik standalone) terminando TLS automáticamente vía Let's Encrypt.",[70,16085,16086],{},"Watchtower (o equivalente) tirando imágenes nuevas del registry periódicamente.",[70,16088,16089],{},"Pipeline simple en GitHub Actions o GitLab CI que builda la imagen, la manda al registry, y deja que Watchtower la descubra.",[70,16091,16092],{},"Backup automatizado igual al estadio 1, ahora con retención más larga.",[12,16094,16095],{},[27,16096,15945],{},[12,16098,16099],{},"Indie hackers con 2 a 5 aplicaciones pequeñas, primer cliente pagante en un producto SaaS lateral, agencia hospedando sitios para clientes sin SLA contractual, herramientas internas que crecieron más allá de la fase \"tres personas la usan\".",[12,16101,16102],{},[27,16103,16104],{},"Lo que mejoró respecto al estadio 1:",[12,16106,16107,16108,16111],{},"El deploy se volvió seamless desde el punto de vista del desarrollador. Haces ",[231,16109,16110],{},"git push",", el CI builda y publica, y dos minutos después la versión nueva está al aire sin que hayas hecho SSH a ningún servidor. TLS automático resuelve un dolor que solía consumir una tarde por trimestre. Múltiples aplicaciones comparten el mismo certificado wildcard vía router.",[12,16113,16114],{},[27,16115,16116],{},"Lo que aún duele:",[12,16118,16119],{},"Watchtower tira cualquier imagen nueva sin pensarlo dos veces. No hay rolling update — durante el swap, la aplicación queda indisponible por algo entre 10 y 30 segundos. No hay health check de verdad antes de promover la versión nueva; si publicaste una imagen rota, el servicio queda fuera hasta que lo notes y lo revertas manualmente. Y el punto único de fallo continúa: el VPS que se cae lo tira todo.",[12,16121,16122],{},[27,16123,15978],{},[12,16125,16126],{},"5 a 10 aplicaciones en el mismo servidor, tráfico de hasta 500 requests por segundo (depende mucho del tipo de carga), tolerancia de 5 a 15 minutos de downtime mensual. Si empezaste a perder noches de sueño porque Watchtower actualizó algo a las tres de la mañana y rompió, pasaste del estadio.",[19,16128,16130],{"id":16129},"estadio-3-multi-server-con-docker-swarm","Estadio 3: Multi-server con Docker Swarm",[12,16132,16133],{},"Aquí la conversación cambia. Sales de \"una máquina robusta\" para \"tres máquinas arreglándoselas juntas\". Docker Swarm es el escalón natural para quien ya está cómodo con Compose: el archivo es prácticamente el mismo, el vocabulario es el mismo, y el salto conceptual es menor que saltar directo a Kubernetes.",[12,16135,16136],{},[27,16137,16075],{},[2735,16139,16140,16143,16153,16163,16166],{},[70,16141,16142],{},"3 o más VPS de tamaño medio. Tres es el mínimo práctico para que el cluster sobreviva a la pérdida de una máquina.",[70,16144,16145,16148,16149,16152],{},[231,16146,16147],{},"docker swarm init"," en el primer nodo, ",[231,16150,16151],{},"docker swarm join"," en los otros dos.",[70,16154,16155,16156,16159,16160,101],{},"Stack file (",[231,16157,16158],{},"docker stack deploy -c stack.yml meuapp",") en lugar de ",[231,16161,16162],{},"docker-compose up",[70,16164,16165],{},"Router integrado al cluster (Traefik tiene modo Swarm nativo) escuchando los eventos del daemon y rebalanceando automáticamente.",[70,16167,16168],{},"¿Logs y métricas centralizados? Los montas por fuera. No vienen en la caja.",[12,16170,16171],{},[27,16172,15945],{},[12,16174,16175],{},"SaaS B2B con primer contrato exigiendo \"best-effort 99%\", el equipo ya tiene un dev cómodo con terminal y dispuesto a aprender, aplicación creció más allá de lo que cabe en un VPS único sin dolor.",[12,16177,16178],{},[27,16179,16180],{},"El elefante en la sala:",[12,16182,16183],{},"Docker Swarm está en modo de mantenimiento desde 2019. Docker Inc. no invierte activamente en features nuevas. Bugs críticos siguen siendo corregidos, pero el ecosistema de plugins se estancó, y la evolución del scheduler prácticamente paró. Funciona — miles de empresas ejecutan Swarm en producción sin problemas hoy. Pero estás apostando en una tecnología cuya trayectoria de inversión se cortó hace más de cinco años.",[12,16185,16186],{},"La versión honesta de esto: si adoptas Swarm en 2026, lo estás adoptando con la expectativa de eventualmente migrar a otra cosa. No es un problema inmediato — es un problema que aparece cuando necesites algo que Swarm nunca va a ganar.",[12,16188,16189],{},[27,16190,15978],{},[12,16192,16193],{},"3 a 30 servidores, tráfico del orden de 5 mil requests por segundo agregadas, tolerancia de 5 a 30 segundos de failover cuando una máquina se cae. Por encima de eso, o complementas con piezas externas (observability stack, autoscaler manual, DNS GSLB), o subes al siguiente escalón.",[12,16195,16196],{},[27,16197,16198],{},"Dónde más duele en el día a día:",[12,16200,16201],{},"La overlay network bajo carga alta tiene edge cases conocidos, principalmente en redes de proveedor cloud con MTU no estándar. Recovery tras split-brain en algunos escenarios necesita intervención manual — el cluster no se recompone solo en el 100% de los casos. Y cualquier cosa que involucre observabilidad detallada (métricas persistidas, logs estructurados, tracing distribuido) la montas por separado, manteniendo dos o tres productos más.",[19,16203,16205],{"id":16204},"estadio-4-cluster-con-plano-de-control-replicado","Estadio 4: Cluster con plano de control replicado",[12,16207,16208],{},"El escalón donde \"producción\" empieza a tener el mismo significado que tiene en empresas de plataforma maduras. Ya no estás ejecutando un orquestador legacy en mantenimiento, ni dependiendo de un único servidor para la continuidad.",[12,16210,16211],{},[27,16212,16075],{},[2735,16214,16215,16218,16221,16224,16227],{},[70,16216,16217],{},"3 a 5 servidores en la configuración mínima, con el plano de control replicado entre los tres primeros. Los demás entran como agentes.",[70,16219,16220],{},"Elección automática de coordinador. Si el actual se cae, en pocos segundos otro asume y el cluster sigue aceptando deploys y atendiendo tráfico.",[70,16222,16223],{},"Router integrado, certificados automáticos, health check antes de promover versión nueva, rolling update con ventanas configurables.",[70,16225,16226],{},"Métricas y logs como servicios internos del propio cluster — no montas cinco productos para tener observabilidad básica.",[70,16228,16229],{},"Submisión de jobs vía CLI, API o panel web. El cluster decide en qué servidor va a correr cada réplica.",[12,16231,16232],{},[27,16233,15945],{},[12,16235,16236],{},"SaaS con SLA contractual de 99,9%, multi-tenant con requisitos formales de aislamiento, equipo de plataforma de 1 a 3 personas, contratos B2B en los que uptime es parte del SOW, cualquier empresa en la que \"estar fuera veinte minutos\" genera reembolso.",[12,16238,16239],{},[27,16240,16241],{},"Riesgos que cambian de naturaleza:",[12,16243,16244],{},"La complejidad no desaparece — cambia de forma. En lugar de operar tres VPS a mano, operas un cluster que resuelve la mayor parte de los problemas solo pero tiene más piezas. Curva de aprendizaje para quien nunca operó cluster antes existe y es real. Y es genuinamente overkill si nunca vas más allá del estadio 2: tres servidores ejecutando una app de hobby es desperdicio.",[12,16246,16247],{},[27,16248,16249],{},"Números concretos para calibrar:",[12,16251,16252],{},"Un cluster pequeño bien configurado corre cómodamente en 4 servidores totalizando 5 vCPUs y 10 GB de RAM, con el plano de control ocupando entre 200 y 400 MB por servidor. La elección de coordinador, cuando el actual se cae, lleva unos 7 segundos hasta que el cluster vuelve a aceptar deploys. Comparativamente, la configuración equivalente en Kubernetes empieza en cientos de líneas de manifiesto para una app \"hello world\" — y HeroCtl resuelve lo mismo en unas 50.",[12,16254,16255],{},[27,16256,15978],{},[12,16258,16259],{},"3 a 500 servidores. Por encima de eso, el ecosistema de Kubernetes gestionado tiene herramientas que cluster pequeño no necesita: federación multi-región, scheduler avanzado para workloads heterogéneas, biblioteca profunda de operadores especializados para databases stateful. No es que cluster pequeño no escale — es que por encima de 500 nodos estás en un mercado en el que otras herramientas tienen cinco años de ventaja.",[19,16261,16263],{"id":16262},"los-cuatro-estadios-lado-a-lado","Los cuatro estadios lado a lado",[119,16265,16266,16284],{},[122,16267,16268],{},[125,16269,16270,16272,16275,16278,16281],{},[128,16271,2983],{},[128,16273,16274],{},"Estadio 1 (compose 1 VPS)",[128,16276,16277],{},"Estadio 2 (compose + auto-update)",[128,16279,16280],{},"Estadio 3 (Docker Swarm)",[128,16282,16283],{},"Estadio 4 (cluster replicado)",[141,16285,16286,16303,16317,16332,16346,16363,16377,16393,16406,16422],{},[125,16287,16288,16291,16294,16297,16300],{},[146,16289,16290],{},"Coste mensual mínimo (ES, 2026)",[146,16292,16293],{},"5 €",[146,16295,16296],{},"10 €",[146,16298,16299],{},"25 € (3 VPS)",[146,16301,16302],{},"35 € (4 VPS)",[125,16304,16305,16308,16310,16312,16314],{},[146,16306,16307],{},"Complejidad operacional",[146,16309,4890],{},[146,16311,3155],{},[146,16313,3160],{},[146,16315,16316],{},"Media-alta",[125,16318,16319,16322,16324,16327,16330],{},[146,16320,16321],{},"Tiempo hasta primer deploy",[146,16323,9776],{},[146,16325,16326],{},"1 hora",[146,16328,16329],{},"1 día",[146,16331,16329],{},[125,16333,16334,16337,16339,16341,16344],{},[146,16335,16336],{},"Alta disponibilidad real",[146,16338,3059],{},[146,16340,3059],{},[146,16342,16343],{},"Sí, con matices",[146,16345,3065],{},[125,16347,16348,16351,16354,16357,16360],{},[146,16349,16350],{},"Escala máxima realista",[146,16352,16353],{},"1–3 apps",[146,16355,16356],{},"5–10 apps",[146,16358,16359],{},"30 servidores",[146,16361,16362],{},"500 servidores",[125,16364,16365,16368,16370,16373,16375],{},[146,16366,16367],{},"Deploys sin downtime",[146,16369,3059],{},[146,16371,16372],{},"Casi",[146,16374,3065],{},[146,16376,3065],{},[125,16378,16379,16382,16385,16388,16391],{},[146,16380,16381],{},"TLS automático",[146,16383,16384],{},"Manual o plugin",[146,16386,16387],{},"Sí, embebido",[146,16389,16390],{},"Sí, vía router",[146,16392,16387],{},[125,16394,16395,16398,16400,16402,16404],{},[146,16396,16397],{},"Observabilidad en la caja",[146,16399,3059],{},[146,16401,3059],{},[146,16403,3059],{},[146,16405,3065],{},[125,16407,16408,16411,16414,16416,16419],{},[146,16409,16410],{},"Equipo mínimo para operar",[146,16412,16413],{},"1 dev (parcial)",[146,16415,16413],{},[146,16417,16418],{},"1 dev (dedicado)",[146,16420,16421],{},"1 dev (parcial) o 2 (parciales)",[125,16423,16424,16427,16430,16433,16436],{},[146,16425,16426],{},"Franja de aplicación ideal",[146,16428,16429],{},"Hobby, MVP",[146,16431,16432],{},"Indie hacker, primer cliente",[146,16434,16435],{},"SaaS B2B early-stage",[146,16437,16438],{},"SaaS con SLA, multi-tenant",[12,16440,16441],{},"La columna que suele sorprender es la de \"equipo mínimo para operar\". El estadio 4 con la herramienta correcta no exige más gente que el estadio 3 — exige gente que piensa diferente. El salto cognitivo es mayor que el salto operacional.",[19,16443,16445],{"id":16444},"las-senales-de-que-es-hora-de-subir-el-escalon","Las señales de que es hora de subir el escalón",[12,16447,16448],{},"Subir antes de necesitarlo es desperdicio; quedarse por debajo de lo necesario es dolor. Las señales prácticas de cada transición:",[12,16450,16451,16454],{},[27,16452,16453],{},"Estadio 1 → Estadio 2."," Descubriste que necesitas ejecutar más de una aplicación en el mismo VPS, los deploys manuales empezaron a ponerse tensos (miedo de tirar producción a las nueve de la noche de un viernes), apareció el primer cliente pagante y tiene expectativas — aunque no estén escritas — de que no vas a desaparecer por treinta minutos en mitad del día laboral.",[12,16456,16457,16460],{},[27,16458,16459],{},"Estadio 2 → Estadio 3."," Un cliente pidió SLA por primera vez, aunque sea informalmente (\"¿cuánto tiempo máximo puede estar esto fuera?\"). O el VPS único se cayó una vez y aprendiste en carne propia que necesitabas redundancia. O el equipo creció a tres o más personas y ya no quieres ser la única que sabe hacer deploy. O estás pagando 50 € al mes en un VPS gigante cuando tres VPS medianos resolverían lo mismo con fail-over.",[12,16462,16463,16466],{},[27,16464,16465],{},"Estadio 3 → Estadio 4."," Contrato B2B exige uptime medible y auditable (palabras como \"99.9%\" y \"ventana de mantenimiento\" empezaron a aparecer en propuesta comercial). Compliance pidió auditoría detallada y necesitas mostrar trail de quién hizo qué. O — la señal más común hoy — estás cansado de los patches del Swarm y quieres una herramienta con roadmap claro para los próximos cinco años.",[12,16468,16469,16472],{},[27,16470,16471],{},"La señal universal de \"subiste demasiado pronto\"."," Estás gastando más tiempo configurando infraestructura que escribiendo features de producto. Vuelve un escalón. En serio. La infra existe para soportar el producto, no al revés, y la mayor parte de las startups que mueren temprano mueren porque construyeron plataforma sin cliente en lugar de cliente sin plataforma.",[19,16474,16476],{"id":16475},"la-trayectoria-que-no-funciona","La trayectoria que no funciona",[12,16478,16479],{},"Tres trampas comunes en las que los equipos caen al intentar acelerar el salto:",[12,16481,16482,16485,16486,16488],{},[27,16483,16484],{},"Saltar de compose directo a Kubernetes."," La tentación es genuina: \"si voy a tener que migrar una vez, mejor migrar a la herramienta líder de mercado y nunca más\". La realidad es más cruel. Seis meses después sigues luchando con manifiestos de 300 líneas, operadores especializados, operadores de operadores, y gastando la mitad del tiempo de ingeniería en problemas que ni siquiera existían cuando ejecutabas ",[231,16487,12708],{},". Mientras tanto, el competidor más simple shipeó doce features. K8s vale la pena en un momento muy específico — cuando ya sabes que vas a escalar a 50+ servidores, tienes equipo para operar, y los problemas que resuelve son problemas que de hecho tienes. Antes de eso, es capital quemado.",[12,16490,16491,16494],{},[27,16492,16493],{},"Quedarse en compose por orgullo."," El otro extremo. \"DevOps complicado es overkill, no lo necesito, siempre ejecuté todo en un VPS y nunca tuve problema\". La realidad llega el primer viernes a las cinco de la tarde en que el disco del VPS muere, el backup del mes pasado tiene tres semanas, y descubres simultáneamente que (a) necesitabas HA y (b) necesitabas procedimiento de recuperación testeado. Los dos aprendizajes en un único fin de semana son caros.",[12,16496,16497,16500],{},[27,16498,16499],{},"Comprar la stack porque está hype."," Service mesh, observability stack completa con cinco productos, GitOps con dos repositorios y tres pipelines, autoscaler con policies sofisticadas — para una aplicación de tres contenedores sirviendo 200 usuarios activos. Estás construyendo plataforma sin tener usuario para la plataforma. La misma energía invertida en features de producto habría generado diez veces más retorno. Si estás en un estadio anterior, no importa cuán bonita sea la herramienta del estadio siguiente.",[19,16502,16504],{"id":16503},"detalles-tecnicos-que-valen-en-cualquier-estadio","Detalles técnicos que valen en cualquier estadio",[12,16506,16507],{},"Algunas decisiones valen desde el estadio 1 y siguen valiendo en el estadio 4. Vale la pena gastar tres párrafos en ellas porque cada una ya causó dolor en producción a mucha gente.",[12,16509,16510,16513,16514,16516,16517,16520,16521,16524],{},[27,16511,16512],{},"Restart policies."," En Compose, ",[231,16515,15927],{}," es el camino correcto para quien quiere que el contenedor vuelva solo después de cualquier fallo. ",[231,16518,16519],{},"on-failure"," es más económico pero te va a morder cuando el proceso haga exit 0 por equivocación. En Swarm, ",[231,16522,16523],{},"restart_policy.condition: any"," hace papel similar. En cualquier estadio, pensar en la política de restart es parte de pensar en el diseño de la aplicación — no es detalle.",[12,16526,16527,16530,16531,16533],{},[27,16528,16529],{},"Health checks."," Toda aplicación que acepta HTTP necesita exponer un endpoint ",[231,16532,355],{}," retornando 200 cuando está saludable. Sin esto, ningún orquestador por encima del estadio 1 logra distinguir \"contenedor subió\" de \"contenedor subió y está realmente atendiendo tráfico\". Timeout razonable: 5 segundos. Retry razonable: 3 veces antes de marcar como unhealthy. Sin esto, vas a entrar en restart loops y tardar horas en entender qué está pasando.",[12,16535,16536,16539,16540,16543,16544,16547],{},[27,16537,16538],{},"Volúmenes nombrados versus bind mounts."," Volúmenes nombrados (",[231,16541,16542],{},"volumes: [meudata:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata]",") sobreviven a recreación del contenedor, son gestionados por Docker, y funcionan consistentemente entre estadios. Bind mounts (",[231,16545,16546],{},".\u002Fdata:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata",") dependen del filesystem del host, tienen comportamiento extraño con SELinux y AppArmor, y se rompen cuando el contenedor cambia de máquina (estadio 3 y 4). Usa bind mount solo para desarrollo y para archivos de configuración read-only.",[12,16549,16550,16552],{},[27,16551,15454],{}," Stdout y stderr es el camino correcto, siempre. Aplicación que escribe log en archivo dentro del contenedor es aplicación que te va a dar dolor de cabeza. El orquestador captura stdout, lo enruta hacia donde tiene que ir (driver syslog, agregador externo, servicio interno), y nunca más necesitas exec dentro del contenedor para ver qué pasó.",[12,16554,16555,16558,16559,16561],{},[27,16556,16557],{},"Secretos."," Variables de entorno en archivo ",[231,16560,9374],{}," son cómodas y peligrosas — se filtran en log, en backup, en snapshot. Para estadio 1 y 2, puedes vivir con ellas si eres cuidadoso. Para estadio 3 en adelante, usa el mecanismo nativo de secretos del orquestador. En herramientas más nuevas (HeroCtl incluido), el cofre es parte del cluster — no montas un producto separado solo para guardar contraseña.",[19,16563,16565],{"id":16564},"coste-concreto-de-cada-estadio-espana-2026","Coste concreto de cada estadio (España, 2026)",[12,16567,16568],{},"La matemática cruda, sin florituras:",[2735,16570,16571,16577,16583,16589],{},[70,16572,16573,16576],{},[27,16574,16575],{},"Estadio 1."," 1 VPS de 5 €\u002Fmes = 60 €\u002Faño. Tiempo de setup inicial: una tarde. Tiempo de operación continua: cerca de 1 hora al mes.",[70,16578,16579,16582],{},[27,16580,16581],{},"Estadio 2."," 1 VPS de 10 €\u002Fmes = 120 €\u002Faño. Tiempo de setup: un día. Tiempo de operación: cerca de 2 horas al mes, principalmente lidiando con Watchtower actualizando algo que no debía.",[70,16584,16585,16588],{},[27,16586,16587],{},"Estadio 3."," 3 VPS de 10 € = 30 €\u002Fmes = 360 €\u002Faño. Tiempo de setup: cerca de 3 días hasta estar cómodo. Tiempo de operación: 4 a 8 horas al mes, dependiendo de cuántos jobs ejecutas.",[70,16590,16591,16594],{},[27,16592,16593],{},"Estadio 4 (HeroCtl Community)."," 4 VPS de 10 € = 40 €\u002Fmes = 480 €\u002Faño. Tiempo de setup: 1 a 2 días hasta estar cómodo. Tiempo de operación: comparable al estadio 3, pero sin los patches manuales y con observabilidad en la caja.",[12,16596,16597,16598,16601],{},"Y para calibrar la comparación que mucha gente hace demasiado pronto: ",[27,16599,16600],{},"Kubernetes gestionado para la misma escala"," cuesta entre 140 € y 300 € al mes de plano de control y load balancers, así que 1.700 € a 3.600 € al año solo de infraestructura — sin contar los 1 a 2 SREs (5.000 € a 7.000 € al mes cada uno) que ese estadio empieza a exigir. La diferencia entre estadio 4 y Kubernetes gestionado, en cuanto a coste total, suele ser de un orden de magnitud entero.",[19,16603,7352],{"id":7351},[12,16605,16606,16612,16613,16615],{},[27,16607,16608,16609,16611],{},"¿Compose con ",[231,16610,15927],{}," no es suficiente?","\nEs suficiente hasta la primera cosa que ",[231,16614,15927],{}," no cubre: el VPS entero indisponible, el disco corrupto, el fallo de red del proveedor, o un deploy que sube imagen rota y entra en loop sin alguien para notarlo. Para hobby project, suficiente; para cliente pagante, es el punto de inicio, no el punto de llegada.",[12,16617,16618,16621],{},[27,16619,16620],{},"¿Docker Swarm está realmente deprecated?","\nNo en el sentido oficial — Docker Inc. no anunció discontinuación. Pero está en mantenimiento, sin features nuevas relevantes desde 2019, y el ecosistema de plugins paró de crecer. Funciona en producción hoy. Una elección defendible para quien ya está en él. Una elección cuestionable para quien lo está adoptando ahora en 2026.",[12,16623,16624,16627],{},[27,16625,16626],{},"¿Cuándo vale la pena subir a Kubernetes gestionado?","\nCuando tienes más de 50 servidores, equipo de plataforma con 3+ personas dedicadas, y problemas específicos que el ecosistema de K8s resuelve mejor (federación multi-región, autoscaling sofisticado, biblioteca profunda de operadores stateful). Antes de eso, estás pagando el coste sin usar el beneficio.",[12,16629,16630,16633],{},[27,16631,16632],{},"¿Watchtower es seguro?","\nRazonablemente, con matices. Tira cualquier imagen nueva publicada en el tag al que estás apuntando, sin distinguir entre \"actualización que publicaste\" y \"imagen comprometida que alguien empujó vía cadena de suministro\". Para estadio 2, el trade-off vale: la ganancia operacional supera el riesgo. Para estadios mayores, prefiere mecanismos que validan imagen antes de promover.",[12,16635,16636,16639,16640,16643,16644,571,16646,16649,16650,16653],{},[27,16637,16638],{},"¿Cómo hago backup de volume Docker en el estadio 1?","\nCron diario ejecutando ",[231,16641,16642],{},"docker exec"," en el contenedor de la base con la utilidad de dump nativa (",[231,16645,5736],{},[231,16647,16648],{},"mysqldump",", etc.), pipe a ",[231,16651,16652],{},"gzip",", y upload a storage objeto fuera del mismo proveedor. La regla de oro: el backup tiene que vivir lejos del dato primario. Si el data center se cae, el backup necesita estar en otro data center.",[12,16655,16656,16659],{},[27,16657,16658],{},"¿Puedo saltar del estadio 1 directo al 4?","\nTécnicamente sí, especialmente con herramientas que hacen el salto suave (HeroCtl es una de ellas, instala en minutos y corre cómodamente en 3 servidores). Recomendado, solo si ya sabes que vas a necesitar el estadio 4 en los próximos seis meses. Caso contrario, el estadio 2 te enseña cosas (deploy automatizado, TLS, registry de imágenes) que vas a usar de cualquier manera más tarde.",[12,16661,16662,16665,16666,16669],{},[27,16663,16664],{},"¿Y si no sé Linux profundamente?","\nEstadio 1 y 2 son muy accesibles con conocimiento básico. Estadio 3 empieza a exigir entendimiento de red (overlay networks, MTU, iptables ocasional). Estadio 4, con la herramienta correcta, abstrae la mayor parte de la complejidad — pero debug de incidente aún exige saber leer log de systemd, entender qué está diciendo ",[231,16667,16668],{},"dmesg",", y diagnosticar disco lleno. No hay magia que sustituya los fundamentos cuando algo sale mal a las tres de la mañana.",[19,16671,16673],{"id":16672},"cerrando","Cerrando",[12,16675,16676],{},"La madurez no es virtud moral. No es \"mejor\" estar en el estadio 4 que en el estadio 1 — es mejor estar en el estadio que combina con el tamaño del problema que estás resolviendo. Hobby project en el estadio 4 es desperdicio de capital y atención; SaaS con cincuenta clientes pagantes en el estadio 1 es negligencia operacional.",[12,16678,16679],{},"HeroCtl existe para hacer accesible el estadio 4 a quien antes necesitaba elegir entre la incomodidad de Swarm y el coste de Kubernetes. Si sientes que pasaste del estadio 2 y estás pesando entre las opciones:",[224,16681,16682],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,16683,16684],{"__ignoreMap":229},[234,16685,16686,16688,16690,16692,16694],{"class":236,"line":237},[234,16687,1220],{"class":247},[234,16689,2958],{"class":251},[234,16691,2961],{"class":255},[234,16693,2964],{"class":383},[234,16695,2967],{"class":247},[12,16697,16698],{},"Instala en minutos, corre cómodamente en 3 a 5 servidores, y tiene plan Community gratuito permanente — sin feature gate artificial, sin límite de servidores, sin amarre contractual. Los planes Business y Enterprise existen para empresas con requisitos formales de SSO, auditoría detallada y soporte con SLA, y los precios están publicados sin \"habla con ventas\" obligatorio.",[12,16700,16701,16702,16706,16707,16711],{},"Para quien está comparando herramientas en el mismo nicho, dos posts complementarios: ",[3337,16703,16705],{"href":16704},"\u002Fes\u002Fblog\u002Fheroctl-vs-coolify","HeroCtl vs Coolify"," cubre el trade-off de adoptar una herramienta con HA real versus un panel single-server elegante; ",[3337,16708,16710],{"href":16709},"\u002Fes\u002Fblog\u002Fheroctl-vs-dokploy","HeroCtl vs Dokploy"," cubre la diferencia de adoptar un cluster con plano de control replicado versus un panel que internamente ejecuta Swarm.",[12,16713,16714],{},"Y si la pregunta es \"¿qué estadio combina conmigo ahora?\", la respuesta honesta casi siempre es: el anterior al que crees que necesitas. Vuelve uno, quédate hasta que duela, sube cuando duela de verdad.",[3351,16716,16717],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":229,"searchDepth":244,"depth":244,"links":16719},[16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,16730,16731],{"id":15841,"depth":244,"text":15842},{"id":15897,"depth":244,"text":15898},{"id":16066,"depth":244,"text":16067},{"id":16129,"depth":244,"text":16130},{"id":16204,"depth":244,"text":16205},{"id":16262,"depth":244,"text":16263},{"id":16444,"depth":244,"text":16445},{"id":16475,"depth":244,"text":16476},{"id":16503,"depth":244,"text":16504},{"id":16564,"depth":244,"text":16565},{"id":7351,"depth":244,"text":7352},{"id":16672,"depth":244,"text":16673},"2026-04-21","Docker Compose resuelve el dev. En producción basta hasta un servidor sin SLA. Por encima de eso, necesitas cluster real. Trayectoria honesta de los cuatro estadios de madurez.",{},{"title":15821,"description":16733},{"loc":3344},"es\u002Fblog\u002Fdeploy-docker-produccion-de-compose-a-cluster",[1118,1526,16739,16740,16741,3394],"produccion","cluster","ha","vkebO2m6tc99eq-HYqQL1Z9MfNe4XOQiPBhmJT8n058",{"id":16744,"title":16745,"author":7,"body":16746,"category":3379,"cover":3380,"date":17811,"description":17812,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":17813,"navigation":411,"path":7466,"readingTime":8766,"seo":17814,"sitemap":17815,"stem":17816,"tags":17817,"__hash__":17820},"blog_es\u002Fes\u002Fblog\u002Fpostgres-en-produccion-gestionado-vs-auto-hospedado.md","Postgres en producción: gestionado vs auto-hospedado, la cuenta honesta",{"type":9,"value":16747,"toc":17794},[16748,16751,16754,16758,16761,16767,16773,16779,16785,16791,16797,16803,16806,16810,16813,16819,16825,16831,16837,16843,16849,16853,16859,16863,16941,16944,16948,17040,17047,17051,17167,17174,17178,17181,17194,17200,17206,17209,17213,17216,17222,17232,17248,17254,17264,17270,17274,17277,17283,17304,17314,17324,17330,17334,17337,17351,17357,17363,17369,17378,17383,17386,17390,17653,17656,17660,17666,17672,17678,17684,17688,17697,17706,17721,17730,17736,17746,17752,17754,17757,17760,17763,17779,17789,17792],[12,16749,16750],{},"La decisión \"RDS o corro Postgres en mi cluster\" es la que más posterga el SaaS. Aparece en un documento de arquitectura el mes uno, se vuelve un TODO el mes tres, se vuelve una pelea interna el mes seis cuando la factura de AWS llega en tres cifras altas. Y mientras tanto, nadie quiere elegir — porque cada blog post sobre el tema está escrito por alguien con sesgo. Quien trabaja en proveedor gestionado dice que self-hosted te rompe. Quien mantiene Postgres desde hace quince años dice que RDS es robo. Los dos lados omiten cosas.",[12,16752,16753],{},"Este post abre la planilla de verdad. Sin adornos, sin vender un lado. Cuándo RDS tiene sentido, cuándo no, cuánto cuesta cada escenario, cuánto cuesta en hora de ingeniero, y cuáles son los cinco errores que hacen que self-hosted se vuelva accidente.",[19,16755,16757],{"id":16756},"lo-que-los-servicios-gestionados-hacen-por-ti-sin-ironia","Lo que los servicios gestionados hacen por ti (sin ironía)",[12,16759,16760],{},"Antes de cualquier comparación, es honesto reconocer lo que RDS, Cloud SQL, Aurora y los Postgres-as-a-Service modernos (Supabase, Neon, Crunchy) entregan de hecho. La propaganda infló — pero el producto es real.",[12,16762,16763,16766],{},[27,16764,16765],{},"Backup automático con retención configurable."," Le dices \"guarda siete días\" y está hecho. Snapshot incremental, sin ventana de mantenimiento visible, sin cron, sin niñera. Para muchos equipos, ese ítem solo justifica el cheque.",[12,16768,16769,16772],{},[27,16770,16771],{},"Recuperación point-in-time (PITR)."," Descubres a las once de la mañana que un deploy a las nueve borró un campo importante. En RDS, restauras a 08:55. Sin leer manual de WAL archiving, sin rezar para que un log de transacciones esté íntegro en un bucket. Solo consola y botón.",[12,16774,16775,16778],{},[27,16776,16777],{},"Patches de seguridad automáticos."," Postgres minor releases salen cada tres meses, y cada uno tiene CVE razonable. En gestionado, eso aplica en una ventana que tú defines. En self-hosted, descubres que estás retrasado cuando un check de compliance pega.",[12,16780,16781,16784],{},[27,16782,16783],{},"Réplica de lectura en un clic."," ¿Quieres escalar lectura? Enciendes la réplica, esperas replicar, apuntas tu aplicación. En self-hosted, configuras streaming replication manualmente, gestionas slot de replicación, monitoreas retraso, defines qué pasa si la conexión cae.",[12,16786,16787,16790],{},[27,16788,16789],{},"Failover Multi-AZ automático."," En RDS Multi-AZ, la instancia secundaria asume en 60–120 segundos cuando la primaria muere, y el endpoint DNS rutea solo. Es la feature más cara y la más útil del producto.",[12,16792,16793,16796],{},[27,16794,16795],{},"Métricas integradas, logs centralizados."," CloudWatch ya tiene todo allí. Slow queries, cache hit ratio, conexiones activas, IO. Abres la consola y ves.",[12,16798,16799,16802],{},[27,16800,16801],{},"Horas de operación que no pasas."," Ese es el ítem invisible. Cada una de las features de arriba es una tarde que no gastaste. Veinte tardes a lo largo del año se convierten en un ingeniero entero de dedicación parcial.",[12,16804,16805],{},"Reconocer esto es el punto de partida honesto. RDS es un producto serio. No es viento.",[19,16807,16809],{"id":16808},"lo-que-los-servicios-gestionados-no-hacen-y-nadie-cuenta","Lo que los servicios gestionados NO hacen (y nadie cuenta)",[12,16811,16812],{},"Aquí vive el asterisco. Las limitaciones de abajo no están en la primera página de la documentación.",[12,16814,16815,16818],{},[27,16816,16817],{},"Migrar a otra plataforma se vuelve un proyecto."," Cuando estás en Aurora, salir de Aurora es un proyecto de dos a doce semanas dependiendo del tamaño. El dialecto no es Postgres puro — Aurora tiene extensiones y comportamientos propios. Salir de Cloud SQL a otra nube exige dump-restore, downtime planificado, reescritura de scripts, ajuste de IAM, rehacer monitoreo. El coste de salida es lo que financia el descuento de la entrada.",[12,16820,16821,16824],{},[27,16822,16823],{},"Algunas extensiones populares simplemente no existen."," TimescaleDB no corre en RDS (AWS ofrece un equivalente propio que no es compatible). pg_partman tiene versión antigua. pgvector llegó tarde. Si tu arquitectura depende de una extensión específica, puedes descubrir tres meses después que no está disponible en tu región, en tu versión, o en general.",[12,16826,16827,16830],{},[27,16828,16829],{},"Tráfico de salida entre regiones cuesta."," Decides poner una réplica en otra región para disaster recovery. Cada gigabyte saliendo de la región principal a la secundaria paga peaje. En workloads pequeños es despreciable. En workloads de 200 GB de write por día, se vuelve una factura paralela.",[12,16832,16833,16836],{},[27,16834,16835],{},"Latencia entre app y base si están en VPCs distintas."," Ese es el error silencioso. Subes la app en una red y la base en otra, con peering. La latencia mínima va de 0,3 ms (misma red) a 2–4 ms (peering). No parece mucho hasta que tu aplicación hace ciento veinte queries por request — ahí se vuelven 350 ms de latencia fantasma.",[12,16838,16839,16842],{},[27,16840,16841],{},"Auditoría detallada cuesta extra."," ¿Quién hizo DROP TABLE? En RDS eso pide Performance Insights en el rango avanzado (US$7 por vCPU al mes) más un logging plugin. No viene activado.",[12,16844,16845,16848],{},[27,16846,16847],{},"No controlas la ventana de mantenimiento de verdad."," \"Configuras\" una ventana, pero en incidentes graves AWS aplica patches fuera de ella. Ya pasó, pasará.",[19,16850,16852],{"id":16851},"la-cuenta-financiera-honesta","La cuenta financiera honesta",[12,16854,16855,16856,16858],{},"Cambio de referencia: R$5 por dólar. Precios de RDS en región São Paulo (",[231,16857,6936],{},"), abril\u002F2026, on-demand. Self-hosted asume VPS DigitalOcean \u002F Vultr \u002F Hetzner en São Paulo o Miami.",[368,16860,16862],{"id":16861},"escenario-pequeno-base-por-debajo-de-10-gb-hasta-100-conexionesseg","Escenario pequeño: base por debajo de 10 GB, hasta 100 conexiones\u002Fseg",[119,16864,16865,16876],{},[122,16866,16867],{},[125,16868,16869,16871,16873],{},[128,16870,11393],{},[128,16872,5439],{},[128,16874,16875],{},"Self-hosted",[141,16877,16878,16889,16905,16915,16926],{},[125,16879,16880,16883,16886],{},[146,16881,16882],{},"Instancia",[146,16884,16885],{},"db.t4g.micro (2 vCPU burst, 1 GB RAM)",[146,16887,16888],{},"VPS 2 vCPU 4 GB ya existente de la app",[125,16890,16891,16894,16899],{},[146,16892,16893],{},"Coste mensual",[146,16895,16896,16897],{},"US$15 = ",[27,16898,15125],{},[146,16900,16901,16904],{},[27,16902,16903],{},"R$0"," (cabe junto con la app)",[125,16906,16907,16910,16913],{},[146,16908,16909],{},"Storage 10 GB gp3",[146,16911,16912],{},"US$1,15",[146,16914,15068],{},[125,16916,16917,16920,16923],{},[146,16918,16919],{},"Backup 10 GB",[146,16921,16922],{},"US$0,95",[146,16924,16925],{},"R$0,50 (S3-compatible)",[125,16927,16928,16931,16936],{},[146,16929,16930],{},"Total",[146,16932,16933],{},[27,16934,16935],{},"R$85\u002Fmes",[146,16937,16938],{},[27,16939,16940],{},"R$0,50\u002Fmes",[12,16942,16943],{},"Diferencia: R$84\u002Fmes. En un año, R$1 mil. No le cambia la vida a nadie. Para un MVP, RDS es defendible solo por el backup automático.",[368,16945,16947],{"id":16946},"escenario-medio-50-gb-1-mil-conexionesseg-1-replica-de-lectura","Escenario medio: 50 GB, 1 mil conexiones\u002Fseg, 1 réplica de lectura",[119,16949,16950,16960],{},[122,16951,16952],{},[125,16953,16954,16956,16958],{},[128,16955,11393],{},[128,16957,5439],{},[128,16959,16875],{},[141,16961,16962,16973,16984,16994,17004,17015,17024],{},[125,16963,16964,16967,16970],{},[146,16965,16966],{},"Primaria",[146,16968,16969],{},"db.r6g.large (2 vCPU, 16 GB)",[146,16971,16972],{},"VPS dedicado 4 vCPU, 8 GB — R$120",[125,16974,16975,16978,16981],{},[146,16976,16977],{},"Réplica lectura",[146,16979,16980],{},"db.r6g.large",[146,16982,16983],{},"VPS 4 vCPU, 8 GB — R$120",[125,16985,16986,16989,16992],{},[146,16987,16988],{},"Storage 50 GB gp3",[146,16990,16991],{},"US$5,75",[146,16993,15068],{},[125,16995,16996,16999,17002],{},[146,16997,16998],{},"IOPS provisionado 3000",[146,17000,17001],{},"US$60",[146,17003,15068],{},[125,17005,17006,17009,17012],{},[146,17007,17008],{},"Backup 50 GB",[146,17010,17011],{},"US$4,75",[146,17013,17014],{},"R$5 (objeto compatible)",[125,17016,17017,17020,17022],{},[146,17018,17019],{},"Bandwidth",[146,17021,15231],{},[146,17023,15068],{},[125,17025,17026,17030,17035],{},[146,17027,17028],{},[27,17029,16930],{},[146,17031,17032],{},[27,17033,17034],{},"US$280 = R$1.400\u002Fmes",[146,17036,17037],{},[27,17038,17039],{},"R$245\u002Fmes",[12,17041,17042,17043,17046],{},"Diferencia: R$1.155\u002Fmes = ",[27,17044,17045],{},"R$13,8 mil\u002Faño",". Aquí la conversación empieza. ¿Vale R$14 mil para no pensar en backup? Para un equipo de dos ingenieros, es un mes de trabajo de uno de ellos. Para un equipo de ocho, es despreciable.",[368,17048,17050],{"id":17049},"escenario-grande-500-gb-10-mil-conexionesseg-alta-disponibilidad-real","Escenario grande: 500 GB, 10 mil conexiones\u002Fseg, alta disponibilidad real",[119,17052,17053,17065],{},[122,17054,17055],{},[125,17056,17057,17059,17062],{},[128,17058,11393],{},[128,17060,17061],{},"RDS Multi-AZ",[128,17063,17064],{},"Cluster self-hosted",[141,17066,17067,17077,17087,17098,17107,17118,17129,17140,17151],{},[125,17068,17069,17071,17074],{},[146,17070,16966],{},[146,17072,17073],{},"db.r6g.4xlarge (16 vCPU, 128 GB) Multi-AZ",[146,17075,17076],{},"VPS dedicado 16 vCPU, 64 GB — R$650",[125,17078,17079,17082,17085],{},[146,17080,17081],{},"Réplica síncrona Multi-AZ",[146,17083,17084],{},"incluida",[146,17086,17076],{},[125,17088,17089,17092,17095],{},[146,17090,17091],{},"Réplica de lectura",[146,17093,17094],{},"db.r6g.2xlarge",[146,17096,17097],{},"VPS 8 vCPU, 32 GB — R$320",[125,17099,17100,17103,17105],{},[146,17101,17102],{},"Storage 500 GB io1",[146,17104,17001],{},[146,17106,15068],{},[125,17108,17109,17112,17115],{},[146,17110,17111],{},"IOPS provisionado 10 mil",[146,17113,17114],{},"US$650",[146,17116,17117],{},"NVMe local incluido",[125,17119,17120,17123,17126],{},[146,17121,17122],{},"Backup automático 500 GB",[146,17124,17125],{},"US$48",[146,17127,17128],{},"R$80 (WAL archiving)",[125,17130,17131,17134,17137],{},[146,17132,17133],{},"Performance Insights avanzado",[146,17135,17136],{},"US$112",[146,17138,17139],{},"gratis (Prometheus)",[125,17141,17142,17145,17148],{},[146,17143,17144],{},"Bandwidth salida",[146,17146,17147],{},"US$100",[146,17149,17150],{},"incluido hasta 20 TB",[125,17152,17153,17157,17162],{},[146,17154,17155],{},[27,17156,16930],{},[146,17158,17159],{},[27,17160,17161],{},"US$2.100 = R$10,5 mil\u002Fmes",[146,17163,17164],{},[27,17165,17166],{},"R$1.700\u002Fmes",[12,17168,17169,17170,17173],{},"Diferencia: R$8,8 mil\u002Fmes = ",[27,17171,17172],{},"R$105 mil\u002Faño",". Aquí es donde el gestionado se vuelve difícil de defender financieramente. Pero la cuenta financiera es solo la mitad. La otra mitad es tiempo.",[19,17175,17177],{"id":17176},"la-cuenta-de-tiempo-mas-importante-que-la-financiera","La cuenta de tiempo (más importante que la financiera)",[12,17179,17180],{},"Tiempo de ingeniero en São Paulo cuesta entre R$80 y R$250 por hora útil dependiendo del nivel. Considera R$150\u002Fhora como media ponderada. Ese es el multiplicador que necesitas cruzar con cada ítem de abajo.",[12,17182,17183,17186,17187,1523,17190,17193],{},[27,17184,17185],{},"Setup inicial."," RDS vía consola: treinta minutos. Defines instancia, storage, security group, parameter group, y está corriendo. Self-hosted bien hecho: cuatro a ocho horas. Postgres + PgBouncer + pgBackRest para S3 + monitoring + tuning de ",[231,17188,17189],{},"shared_buffers",[231,17191,17192],{},"work_mem"," + script de restore + test de restore. Hacer eso en medio día exige experiencia previa. Sin experiencia, se vuelve un sprint entero.",[12,17195,17196,17199],{},[27,17197,17198],{},"Operación continua mensual."," RDS: cero. Abres la consola cuando algo grita. Self-hosted bien hecho: dos a cuatro horas. Revisar slow queries, ajustar parámetro que quedó apretado, verificar que el backup se hizo, restore test mensual, actualizar versión menor. Eso es el régimen de crucero. Si gastas más que eso, hay problema.",[12,17201,17202,17205],{},[27,17203,17204],{},"Cuando da pau a las tres de la mañana."," En RDS, abres ticket. Plan Business de AWS responde en cuatro horas para severidad alta, una hora para crítica. Te vas a dormir y te despiertas con workaround. En self-hosted, tú eres el soporte. Si tu sistema de monitoreo no te despertó, el cliente te despertó. Si tu plan de DR está en un documento que nadie leyó hace seis meses, estás improvisando.",[12,17207,17208],{},"La regla clara: tener monitoreo, plan de recuperación de desastre escrito, y test mensual de restore — no es opcional en self-hosted. Es lo que separa \"self-hosted profesional\" de \"accidente esperando suceder\".",[19,17210,17212],{"id":17211},"stack-minimo-para-postgres-self-hosted-production-grade","Stack mínimo para Postgres self-hosted production-grade",[12,17214,17215],{},"No se puede correr Postgres en producción sin esa base. Cada componente de abajo resuelve un modo de fallo conocido.",[12,17217,17218,17221],{},[27,17219,17220],{},"Postgres principal en servidor dedicado."," No compartas disco con la aplicación. El motor depende de IOPS predecibles, y un log de la app creciendo descontroladamente puede llenar el volumen y parar la base. Asigna un VPS solo para la base, o un volumen separado si es el mismo VPS al inicio.",[12,17223,17224,17227,17228,17231],{},[27,17225,17226],{},"Pool de conexiones con PgBouncer o Pgpool."," Postgres asigna un proceso por conexión. En doscientas conexiones directas, consume más memoria que tu aplicación. PgBouncer en modo ",[231,17229,17230],{},"transaction"," resuelve: decenas de conexiones reales a la base sirviendo miles de conexiones de la aplicación. Sin eso, mueres en la primera hora pico.",[12,17233,17234,17237,17238,17240,17241,17243,17244,17247],{},[27,17235,17236],{},"Backup con pgBackRest o WAL-E."," No uses ",[231,17239,5736],{}," en cron como estrategia única. ",[231,17242,5736],{}," es dump lógico — bueno para migrar versión, malo para recuperar base grande en el minuto correcto. Quieres ",[231,17245,17246],{},"pg_basebackup"," semanal más archivado continuo de WAL para un bucket compatible con S3 (R2 de Cloudflare, B2 de Backblaze, Wasabi, o el propio S3). pgBackRest hace eso y además valida integridad.",[12,17249,17250,17253],{},[27,17251,17252],{},"Réplica en hot standby por replicación en streaming."," Un segundo servidor recibiendo el WAL en tiempo real, listo para promover si el primario cae. Bono: usas ese mismo servidor para queries de lectura pesada, descargando el primario.",[12,17255,17256,17263],{},[27,17257,17258,17259,17262],{},"Monitoreo con ",[231,17260,17261],{},"postgres_exporter"," + Prometheus + Grafana",", o un plug-in equivalente del orquestador que uses. Quieres ver: conexiones activas, ratio de cache, tasa de transacciones, lag de replicación, espacio en disco, slow queries. Sin eso, conduces con los ojos cerrados.",[12,17265,17266,17269],{},[27,17267,17268],{},"Test de restore mensual automatizado."," Cron que toma el backup más reciente, restaura en un servidor temporal, valida que algunas tablas tienen filas. Si eso falla, alerta al equipo. Backup que nunca fue restaurado es placebo. Ya vimos equipos perder semana entera de datos porque el \"backup\" estaba corrupto desde hace tres meses y nadie testeó.",[19,17271,17273],{"id":17272},"los-cinco-errores-que-rompen-postgres-self-hosted","Los cinco errores que rompen Postgres self-hosted",[12,17275,17276],{},"Son los mismos cinco desde hace quince años. No innovan.",[12,17278,17279,17282],{},[27,17280,17281],{},"No testear restore."," Repetimos porque es el ítem más común. Backup que nunca fue restaurado no es backup, es archivo. Restore mensual automatizado es el mínimo civilizado.",[12,17284,17285,17293,17294,17296,17297,17300,17301,17303],{},[27,17286,17287,17288,2403,17290,17292],{},"Mantener ",[231,17289,17189],{},[231,17291,17192],{}," en el por defecto."," El por defecto de Postgres está diseñado para correr en un servidor pequeño sin asumir nada. En producción, ",[231,17295,17189],{}," debe ser 25% de la RAM, ",[231,17298,17299],{},"effective_cache_size"," 50–75%, ",[231,17302,17192],{}," calculado por conexión simultánea. Sin eso, tienes 64 MB de cache en un servidor con 16 GB de RAM y el rendimiento está dejado en la mesa.",[12,17305,17306,17309,17310,17313],{},[27,17307,17308],{},"No monitorear consultas lentas."," Una query mal escrita por un desarrollador distraído puede trabar la base entera. ",[231,17311,17312],{},"pg_stat_statements"," activado, alerta para cualquier query pasando de 500 ms en producción. Sin eso, descubres el problema cuando el cliente abre ticket.",[12,17315,17316,17319,17320,17323],{},[27,17317,17318],{},"Disco compartido con el sistema operativo."," El log del sistema llena, el ",[231,17321,17322],{},"\u002Fvar"," de la base comparte el mismo volumen, y la base deja de aceptar escritura. Postgres tiene que estar en volumen dedicado. NVMe si es posible.",[12,17325,17326,17329],{},[27,17327,17328],{},"Un solo servidor sin réplica."," Servidor cae — y cae, antes o después, hardware falla — y estás con downtime de una a tres horas restaurando del backup. Réplica síncrona en otro servidor reduce eso a segundos.",[19,17331,17333],{"id":17332},"postgres-en-un-orquestador-como-heroctl","Postgres en un orquestador como HeroCtl",[12,17335,17336],{},"Aquí es donde la complejidad operacional cae. No porque Postgres se haya vuelto más simple — sigue siendo complejo — sino porque el orquestador absorbe la parte de plumbing que normalmente escribes a mano.",[12,17338,17339,17342,17343,17346,17347,17350],{},[27,17340,17341],{},"Postgres como tarea del cluster."," La descripción del servicio es un archivo de configuración de aproximadamente treinta líneas: imagen oficial de Postgres, volumen nombrado para datos, variables de entorno para credenciales, recurso reservado de CPU y memoria, política de reinicio. Sin ",[231,17344,17345],{},"systemd unit",", sin ",[231,17348,17349],{},"apt install",", sin firewall manual.",[12,17352,17353,17356],{},[27,17354,17355],{},"Persistencia vía volumen nombrado replicado."," Le dices \"este volumen es replicado entre dos servidores\", y el orquestador garantiza que los datos existen en los dos. Si el servidor que está corriendo Postgres cae, el cluster reagenda en el segundo servidor con los datos ya presentes. Tiempo de recuperación en el orden de segundos, no horas.",[12,17358,17359,17362],{},[27,17360,17361],{},"Backup automático integrado"," en el plan Business: archivado continuo de WAL para objeto compatible con S3, snapshot semanal, retención configurable. La misma feature de RDS, sin cheque a AWS.",[12,17364,17365,17368],{},[27,17366,17367],{},"Réplica de lectura como tarea adicional."," Describes un segundo servicio que apunta al primero como upstream de replicación. Cinco líneas extra en el manifiesto. Sin consola, sin clic, sin paso manual.",[12,17370,17371,17374,17375,17377],{},[27,17372,17373],{},"Métricas embebidas."," El orquestador ya está colectando CPU, memoria, IO de cada contenedor. Añadir ",[231,17376,17261],{}," es una tarea más de quince líneas. Sin montar Prometheus separado, sin provisionar Grafana, sin reventar otro servidor.",[12,17379,17380,17382],{},[27,17381,7112],{}," si el servidor que coordina cae: el cluster elige otro coordinador en torno de siete segundos y sigue agendando. Postgres en sí vuelve en los servidores que sobraron en seguida.",[12,17384,17385],{},"La descripción completa de un Postgres con réplica + backup + métricas en HeroCtl es alrededor de cien líneas. En Kubernetes, el equivalente es un operador externo (CloudNativePG o Zalando) más 300 líneas de manifiesto, más un stack de monitoreo separado, más cert-manager para TLS interno entre nodos. Para el equipo de cinco personas, la diferencia es entre una tarde y un sprint.",[19,17387,17389],{"id":17388},"tabla-comparativa","Tabla comparativa",[119,17391,17392,17416],{},[122,17393,17394],{},[125,17395,17396,17398,17401,17404,17407,17410,17413],{},[128,17397,2983],{},[128,17399,17400],{},"RDS São Paulo",[128,17402,17403],{},"Cloud SQL",[128,17405,17406],{},"Supabase",[128,17408,17409],{},"Neon",[128,17411,17412],{},"Postgres VPS simple",[128,17414,17415],{},"Postgres en HeroCtl",[141,17417,17418,17440,17460,17478,17496,17515,17534,17554,17573,17593,17614,17635],{},[125,17419,17420,17423,17426,17429,17432,17435,17438],{},[146,17421,17422],{},"Coste mínimo (50 GB medio)",[146,17424,17425],{},"R$1.400\u002Fmes",[146,17427,17428],{},"R$1.300\u002Fmes",[146,17430,17431],{},"R$125\u002Fmes (Pro)",[146,17433,17434],{},"R$95\u002Fmes (Launch)",[146,17436,17437],{},"R$240\u002Fmes",[146,17439,17039],{},[125,17441,17442,17445,17448,17450,17452,17454,17457],{},[146,17443,17444],{},"Backup automático",[146,17446,17447],{},"sí",[146,17449,17447],{},[146,17451,17447],{},[146,17453,17447],{},[146,17455,17456],{},"configuras tú",[146,17458,17459],{},"sí (Business)",[125,17461,17462,17465,17467,17469,17472,17474,17476],{},[146,17463,17464],{},"Recuperación point-in-time",[146,17466,17447],{},[146,17468,17447],{},[146,17470,17471],{},"sí (Pro)",[146,17473,17447],{},[146,17475,17456],{},[146,17477,17459],{},[125,17479,17480,17482,17485,17487,17490,17492,17494],{},[146,17481,16336],{},[146,17483,17484],{},"sí (Multi-AZ pago)",[146,17486,17447],{},[146,17488,17489],{},"parcial",[146,17491,17447],{},[146,17493,17456],{},[146,17495,17447],{},[125,17497,17498,17501,17504,17506,17508,17510,17513],{},[146,17499,17500],{},"Extensiones customizadas",[146,17502,17503],{},"restringido",[146,17505,17503],{},[146,17507,17503],{},[146,17509,17503],{},[146,17511,17512],{},"total",[146,17514,17512],{},[125,17516,17517,17519,17522,17524,17527,17529,17532],{},[146,17518,7156],{},[146,17520,17521],{},"alto",[146,17523,17521],{},[146,17525,17526],{},"medio",[146,17528,17526],{},[146,17530,17531],{},"ninguno",[146,17533,17531],{},[125,17535,17536,17539,17542,17544,17547,17549,17552],{},[146,17537,17538],{},"Migración de salida",[146,17540,17541],{},"semanas",[146,17543,17541],{},[146,17545,17546],{},"días",[146,17548,17546],{},[146,17550,17551],{},"horas",[146,17553,17551],{},[125,17555,17556,17559,17561,17563,17565,17567,17570],{},[146,17557,17558],{},"Monitoreo incluido",[146,17560,17489],{},[146,17562,17447],{},[146,17564,17447],{},[146,17566,17447],{},[146,17568,17569],{},"montas tú",[146,17571,17572],{},"embebido",[125,17574,17575,17578,17581,17583,17585,17587,17590],{},[146,17576,17577],{},"Expertise mínima",[146,17579,17580],{},"ninguna",[146,17582,17580],{},[146,17584,17580],{},[146,17586,17580],{},[146,17588,17589],{},"senior",[146,17591,17592],{},"semi-senior",[125,17594,17595,17598,17601,17603,17606,17609,17612],{},[146,17596,17597],{},"Latencia app↔base",[146,17599,17600],{},"1–4 ms",[146,17602,17600],{},[146,17604,17605],{},"5–30 ms",[146,17607,17608],{},"10–50 ms",[146,17610,17611],{},"0,3 ms",[146,17613,17611],{},[125,17615,17616,17618,17621,17623,17626,17629,17632],{},[146,17617,13540],{},[146,17619,17620],{},"cualquier",[146,17622,17620],{},[146,17624,17625],{},"hasta 50 GB",[146,17627,17628],{},"hasta 100 GB",[146,17630,17631],{},"indie",[146,17633,17634],{},"startup a porte medio",[125,17636,17637,17640,17642,17644,17646,17648,17651],{},[146,17638,17639],{},"Compliance LGPD vía proveedor",[146,17641,17447],{},[146,17643,17447],{},[146,17645,17489],{},[146,17647,17489],{},[146,17649,17650],{},"documentas tú",[146,17652,17650],{},[12,17654,17655],{},"Ninguna columna gana en todo. Cada una es un conjunto coherente de tradeoffs. Quien intenta vender una columna como \"la mejor\" está vendiendo.",[19,17657,17659],{"id":17658},"decision-honesta-por-perfil","Decisión honesta por perfil",[12,17661,17662,17665],{},[27,17663,17664],{},"MVP hasta 10 GB y hasta cien conexiones\u002Fseg."," Postgres como contenedor al lado de la aplicación, en un único VPS. Backup diario para objeto compatible con S3. Coste total, base y todo, en el rango de R$10\u002Fmes por encima de lo que ya pagas por el VPS. En algún momento migras — y migrar con 10 GB es una noche de domingo, no un proyecto. Empieza simple.",[12,17667,17668,17671],{},[27,17669,17670],{},"Indie hacker entre 10 y 100 GB."," Postgres en VPS dedicado, réplica asíncrona en segundo VPS, backup horario para objeto S3-compatible (Cloudflare R2 o Backblaze B2 sale en céntimos). Algo entre R$120 y R$200 al mes total. Si tienes hora para dedicar, ese es el punto donde self-hosted compensa mucho.",[12,17673,17674,17677],{},[27,17675,17676],{},"Startup early entre 100 y 500 GB."," Aquí la decisión queda de verdad. Evalúa RDS São Paulo por el argumento de compliance LGPD (AWS ya tiene el cuaderno de certificaciones del datacenter) — saldrá en el rango de R$1,5 a R$3 mil al mes. O evalúa Postgres en cluster gestionado por el orquestador, en tres VPS dedicados, en el rango de R$400 al mes — pero exige disciplina operacional real. No es \"self-hosted descomplicado\". Es self-hosted con orquestador absorbiendo la parte de plumbing.",[12,17679,17680,17683],{},[27,17681,17682],{},"Compliance pesada o Enterprise."," Gestionado tiene sentido cuando el framework de auditoría pide proveedor con certificación específica. Pero lee el contrato — algunas regiones de RDS en Brasil aún no tienen todas las certificaciones (HIPAA, FedRAMP, PCI nivel 1) que la región americana tiene. Si tu auditor pide un certificado específico, confirma que la región lo tiene antes de firmar.",[19,17685,17687],{"id":17686},"preguntas-que-equipo-inexperto-hace","Preguntas que equipo inexperto hace",[12,17689,17690,17693,17694,17696],{},[27,17691,17692],{},"¿Puedo empezar con self-hosted y migrar a RDS después?"," Puedes, y es una estrategia válida. Postgres es Postgres. Haces ",[231,17695,5736],{}," de la base, restauras en RDS, ajustas endpoint de la aplicación, decomisionas el servidor antiguo. Para hasta 50 GB, es una operación de algunas horas con ventana corta. El camino contrario (salir de RDS a self-hosted) también funciona, pero herramientas como AWS DMS facilitan más el ingreso que la salida.",[12,17698,17699,17702,17703,17705],{},[27,17700,17701],{},"¿RDS São Paulo es confiable?"," La región ",[231,17704,6936],{}," es una de las más antiguas de AWS fuera de Estados Unidos, opera desde 2011, y tiene tres zonas de disponibilidad independientes. En incidentes globales de AWS, São Paulo suele ser tomada también. En incidentes regionales, cae sola — lo que pasó dos veces en los últimos cinco años por algunas horas. Confiable lo suficiente para producción, no confiable lo suficiente para prescindir de plan B.",[12,17707,17708,17714,17715,17717,17718,17720],{},[27,17709,17710,17711,17713],{},"¿Backup con ",[231,17712,5736],{}," en cron resuelve?"," Resuelve para MVP, no resuelve para producción seria. ",[231,17716,5736],{}," es dump lógico — no preserva el estado exacto, pierde en el tiempo de restore (lento para bases grandes), y no permite recuperar al minuto X. La combinación correcta es ",[231,17719,17246],{}," físico semanal más archivado continuo de WAL. Herramienta: pgBackRest.",[12,17722,17723,17726,17727,17729],{},[27,17724,17725],{},"¿Cuándo vale la pena comprar Performance Insights en el rango avanzado?"," Cuando estás en RDS, tienes más de cinco ingenieros tocando el schema, y necesitas rastrear \"¿quién corrió esa query?\". En equipos pequeños, el ",[231,17728,17312],{}," nativo ya entrega 80% del valor — actívalo primero y mira si necesitas más.",[12,17731,17732,17735],{},[27,17733,17734],{},"¿Y Supabase, Neon, Crunchy?"," Son productos diferentes encima de Postgres. Supabase es Postgres + autenticación + API REST generada + storage de archivos — bueno para proyecto que necesita todo eso integrado, malo para quien quiere solo base. Neon separa storage y compute, duerme cuando ocioso, óptimo para ambiente de staging y workload spiky. Crunchy es Postgres puro con foco enterprise y operador para Kubernetes. Los tres tienen capas gratis razonables para MVP — vale testear antes de cerrar con RDS.",[12,17737,17738,17741,17742,17745],{},[27,17739,17740],{},"¿Cómo hago HA real sin RDS Multi-AZ?"," Réplica síncrona en segundo servidor (",[231,17743,17744],{},"synchronous_standby_names"," configurado) garantiza que cada commit fue escrito en los dos antes de retornar OK a la aplicación. Failover vía Patroni, o vía orquestador como HeroCtl. El punto sensible es el split-brain: la réplica no puede promover sola sin confirmación externa. Patroni resuelve con etcd como árbitro. HeroCtl resuelve con el propio plano de control distribuido haciendo el papel de árbitro — sin montar servicio extra.",[12,17747,17748,17751],{},[27,17749,17750],{},"¿HeroCtl corre Postgres pesado en producción de verdad?"," Corre. El cluster público de la propia documentación sirve este blog a través de un stack que incluye un Postgres self-hosted como tarea del cluster, con réplica y backup. Para workloads por encima de 500 GB o con requisitos de IOPS en el orden de 50 mil, recomendamos evaluar gestionado — no porque el orquestador no aguante, sino porque el IOPS provisionado y el control de I\u002FO de AWS en ese rango empiezan a hacer diferencia operacional real.",[19,17753,3310],{"id":3309},[12,17755,17756],{},"No existe respuesta única para \"Postgres gestionado o auto-hospedado\". Existe tu planilla. Si abriste este post buscando confirmación, lo que encontraste fueron números — úsalos.",[12,17758,17759],{},"Para los perfiles en que self-hosted compensa pero la operación asusta, HeroCtl es la capa que reduce el roce. Backup, réplica, monitoreo y failover descritos en cien líneas de configuración, corriendo en tu cluster, sin cheque a proveedor, sin lock-in.",[12,17761,17762],{},"Instala con:",[224,17764,17765],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,17766,17767],{"__ignoreMap":229},[234,17768,17769,17771,17773,17775,17777],{"class":236,"line":237},[234,17770,1220],{"class":247},[234,17772,2958],{"class":251},[234,17774,5329],{"class":255},[234,17776,2964],{"class":383},[234,17778,2967],{"class":247},[12,17780,17781,17782,17785,17786,101],{},"Para más sobre el coste total de alojar SaaS en 2026, lee ",[3337,17783,17784],{"href":6337},"cuánto cuesta alojar un SaaS",". Para la transición práctica de Docker Compose a cluster con alta disponibilidad real, lee ",[3337,17787,17788],{"href":3344},"deploy Docker en producción, del Compose al cluster",[12,17790,17791],{},"La cuenta honesta es la que cabe en tu planilla. Haz los números antes de decidir.",[3351,17793,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":17795},[17796,17797,17798,17803,17804,17805,17806,17807,17808,17809,17810],{"id":16756,"depth":244,"text":16757},{"id":16808,"depth":244,"text":16809},{"id":16851,"depth":244,"text":16852,"children":17799},[17800,17801,17802],{"id":16861,"depth":271,"text":16862},{"id":16946,"depth":271,"text":16947},{"id":17049,"depth":271,"text":17050},{"id":17176,"depth":244,"text":17177},{"id":17211,"depth":244,"text":17212},{"id":17272,"depth":244,"text":17273},{"id":17332,"depth":244,"text":17333},{"id":17388,"depth":244,"text":17389},{"id":17658,"depth":244,"text":17659},{"id":17686,"depth":244,"text":17687},{"id":3309,"depth":244,"text":3310},"2026-04-15","RDS empieza en US$15\u002Fmes — termina en US$500. Auto-hospedar empieza en $0 — termina despertándote a las 3 de la mañana. Cómo decidir entre los dos sin engañarte.",{},{"title":16745,"description":17812},{"loc":7466},"es\u002Fblog\u002Fpostgres-en-produccion-gestionado-vs-auto-hospedado",[13022,17818,17819,7512,3394],"base-de-datos","rds","bAVvBcP1TKuFb6Y_hxxzymp2Fo5YHDRVNBLYyiT4TtI",{"id":17822,"title":17823,"author":7,"body":17824,"category":3379,"cover":3380,"date":18369,"description":18370,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":18371,"navigation":411,"path":11725,"readingTime":8766,"seo":18372,"sitemap":18373,"stem":18374,"tags":18375,"__hash__":18379},"blog_es\u002Fes\u002Fblog\u002Fobservabilidad-sin-datadog-stack-startup.md","Observabilidad sin Datadog: la stack alternativa que cabe en el presupuesto",{"type":9,"value":17825,"toc":18354},[17826,17829,17832,17835,17839,17842,17845,17848,17851,17854,17857,17861,17864,17870,17876,17882,17888,17891,17895,17898,17904,17910,17916,17922,17928,17934,17940,17943,17947,17950,17953,17956,17959,17963,17966,17972,17978,17984,17990,17994,17997,18003,18009,18015,18021,18027,18030,18034,18037,18043,18049,18055,18061,18064,18068,18071,18074,18077,18080,18083,18087,18090,18093,18096,18099,18103,18252,18255,18259,18262,18268,18274,18280,18286,18288,18294,18300,18306,18312,18318,18324,18330,18332,18335,18338,18341,18346],[12,17827,17828],{},"La primera factura de Datadog que supera los cuatro dígitos en real suele llegar en un momento previsible. El equipo deploya un par de servicios más, el auto-discovery del agente pasa a contar containers como hosts facturables, alguien activa APM en el backend Node, otro alguien activa RUM en el frontend para investigar lentitud de página, y al cierre del mes la tarjeta de la empresa es debitada en casi R$2 mil. El fundador mira la planilla, suma con Vercel, suma con base gestionada, suma con S3, y descubre que la infraestructura — antes una línea discreta en el presupuesto — ahora come el equivalente a medio salario sénior por mes.",[12,17830,17831],{},"La reacción dominante es apretar los dientes y pagar. Datadog es, sin ironía, el mejor producto del mercado en observabilidad. Los dashboards son bonitos, las integraciones funcionan de primera, el APM muestra la query lenta con profundidad que pocos competidores alcanzan, el alerting es flexible lo suficiente para modelar políticas de SLO sin volverse proyecto interno. Para empresa Series B con ingresos arriba de US$5 millones anuales, la cuenta de US$2 mil o US$5 mil es despreciable frente al tiempo de ingeniería que ella compra. La elección es racional.",[12,17833,17834],{},"Para startup brasileña de cinco a diez servidores, facturando entre R$30 mil y R$500 mil al mes, la misma elección es financieramente devastadora. Este post mapea la alternativa concreta — qué herramientas usar, en qué servidor correr, cuánto consume de RAM, cuánto cuesta en almacenamiento — para entregar el 95% del mismo resultado por cerca del 10% del precio.",[19,17836,17838],{"id":17837},"por-que-datadog-gano-el-mercado","Por qué Datadog ganó el mercado",[12,17840,17841],{},"No se puede hablar honestamente sobre alternativas sin explicar primero por qué el líder está donde está. Quien ya operó observabilidad en alguna escala lo sabe: la versión \"móntalo tú mismo\" siempre existió, y aun así Datadog creció a US$2 mil millones de ingresos anuales. Hay razones reales para eso.",[12,17843,17844],{},"La primera es que la UX clavó un estándar. Cuando abres un dashboard de Datadog por primera vez, la jerarquía de información tiene sentido al instante — host map, service map, traces, logs, todo conectado por enlaces que cruzan los contextos sin fricción. Quien operó observabilidad en los años 2010 con Nagios, Cacti y Munin sabe que eso no es gratuito. Fue ingeniería de producto cara, durante una década.",[12,17846,17847],{},"La segunda es la biblioteca de integraciones. Postgres, MySQL, Redis, Kafka, RabbitMQ, ElasticSearch, Mongo, Cassandra, decenas de proveedores cloud, más de seiscientos targets listos. Cada integración viene con dashboard estándar razonable, alertas sugeridas, métricas relevantes recolectadas sin que tengas que leer documentación oscura.",[12,17849,17850],{},"La tercera es el APM accurate. Los tracers oficiales para los lenguajes populares hacen instrumentación automática que captura el nivel correcto de detalle. La query lenta en Postgres aparece con plan de ejecución. El endpoint p99 lento aparece con la stack trace que causó la lentitud. Ese nivel de visibilidad exige inversión continua en cada runtime.",[12,17852,17853],{},"La cuarta es el alerting flexible. Threshold simple es fácil en cualquier herramienta. Alerting que entiende estacionalidad, que cruza múltiples series, que aplica anomaly detection en series escasas — eso Datadog lo hace bien porque invirtió una década calibrando.",[12,17855,17856],{},"Para empresa que puede pagar, contratar Datadog es la decisión correcta. Para ti que no puedes, vale la pena entender exactamente dónde la factura explota antes de buscar alternativa.",[19,17858,17860],{"id":17859},"los-cuatro-vectores-donde-la-factura-explota","Los cuatro vectores donde la factura explota",[12,17862,17863],{},"La página de precios de Datadog parece civilizada cuando la miras de lejos. US$15 por host por mes en la entrada, US$23 en el plan profesional, US$31 en el plan empresa. Cinco hosts por US$23 da US$115 — barato. El problema es que esa no es la factura que llega.",[12,17865,17866,17869],{},[27,17867,17868],{},"Cobranza por host con containers contando como hosts."," En algunos planes, cada container cuenta como host adicional para fines de billing. La startup que corre cuatro servicios en tres réplicas en tres servidores piensa que tiene tres hosts — pero la factura cuenta treinta y seis puntos de telemetría. La política cambió varias veces en los últimos años e incluso quien lee la documentación atenta yerra la estimación.",[12,17871,17872,17875],{},[27,17873,17874],{},"Custom metrics cobradas por métrica por minuto."," Cada métrica customizada por encima del límite incluido tiene costo individual. Un equipo bien intencionado agrega métricas de negocio — pedidos por minuto, valor promedio del carrito, conversión por embudo — y la factura sube US$50, US$100, US$300 dependiendo de la cardinalidad de los tags. Cardinalidad alta en métricas customizadas es la tarifa silenciosa que nadie prevé.",[12,17877,17878,17881],{},[27,17879,17880],{},"APM Pro como upsell."," El APM básico viene incluido, pero las features que efectivamente quieres usar — continuous profiler, code-level visibility, deployment tracking, retención extendida de traces — están en el APM Pro, con precio adicional por host.",[12,17883,17884,17887],{},[27,17885,17886],{},"Logs ingestion más retention extra."," El precio de logs es en dos dimensiones: ingesta (cuánto entra) y retención (por cuánto tiempo queda). Cinco servidores generando 1 GB de log por día ingieren 150 GB por mes. Retener 30 días es una franja de precio; retener 90 días es otra; retener un año es otra. Y búsqueda en logs antiguos cuesta por consulta en algunos planes.",[12,17889,17890],{},"Suma Network Performance Monitoring, Real User Monitoring, Database Monitoring, Synthetics, CI Visibility — cada uno es upsell encima de upsell. La cuenta final de una startup con cinco a diez servidores típicamente queda entre US$200 y US$400 al mes, o sea, R$1 mil a R$2 mil al cambio de R$5 por dólar. R$24 mil al año es el equivalente a un mes de salario de persona sénior.",[19,17892,17894],{"id":17893},"la-stack-alternativa-con-nombres-especificos","La stack alternativa, con nombres específicos",[12,17896,17897],{},"La buena noticia: la industria open-source de observabilidad está madura hace tiempos. No es escenario de 2015 con Nagios y Munin. Las herramientas hoy cubren cada vertical con calidad real.",[12,17899,17900,17903],{},[27,17901,17902],{},"Métricas",": Prometheus para recolección y almacenamiento, Grafana para visualización. La combinación tiene quince años de producción en miles de empresas, es el estándar de hecho, y la mayoría de las aplicaciones modernas ya expone métricas en formato compatible.",[12,17905,17906,17909],{},[27,17907,17908],{},"Logs",": Loki, del mismo equipo que mantiene a Grafana. La sintaxis de consulta es parecida a la de Prometheus, lo que reduce la carga cognitiva de quien ya usa uno. Por GB almacenado, es típicamente 90% más barato que Datadog Logs porque indexa solo labels, no el contenido completo.",[12,17911,17912,17915],{},[27,17913,17914],{},"Traces",": Tempo (Grafana) o Jaeger o SigNoz. Los tres hablan OpenTelemetry, así que la aplicación no queda acoplada a la elección. Tempo se integra más limpiamente a Grafana; Jaeger es el veterano con UI propia; SigNoz combina traces, métricas y logs en un producto único.",[12,17917,17918,17921],{},[27,17919,17920],{},"APM",": SigNoz es el competidor directo más maduro hoy, con instrumentación OpenTelemetry-native. OpenObserve es alternativa más nueva con arquitectura moderna. Pyroscope cubre continuous profiling — el tipo de visibilidad de CPU y memoria que el APM Pro de Datadog vende caro.",[12,17923,17924,17927],{},[27,17925,17926],{},"Errores y excepciones",": Sentry self-hosted es la opción robusta — misma herramienta que la versión SaaS, sin el costo. GlitchTip es alternativa más liviana, drop-in compatible con SDKs de Sentry, óptima para equipos pequeños.",[12,17929,17930,17933],{},[27,17931,17932],{},"Uptime monitoring",": Uptime Kuma cubre el 95% de los casos con instalación de cinco minutos. Statping es alternativa similar.",[12,17935,17936,17939],{},[27,17937,17938],{},"Synthetic checks",": Checkly tiene free tier generoso y cubre el caso \"correr test en navegador de varias regiones\" sin que necesites mantener infra de checks. Para quien prefiere homegrown, scripts Playwright en GitHub Actions resuelven.",[12,17941,17942],{},"La stack arriba cubre todos los verticales que Datadog vende. La pregunta honesta es dónde cada pieza queda debiendo en la comparación.",[19,17944,17946],{"id":17945},"que-hace-cada-componente-y-que-no-hace","Qué hace cada componente y qué no hace",[12,17948,17949],{},"Prometheus y Grafana cubren el 90% de lo que dashboards de Datadog cubren. La diferencia real está en las integraciones: Datadog tiene integración de un clic para seiscientos targets, mientras que Prometheus típicamente exige escribir exporter o usar un exporter común — postgres_exporter, redis_exporter, blackbox_exporter, node_exporter. Para targets populares, esos exporters existen y son bien mantenidos. Para targets exóticos, escribes.",[12,17951,17952],{},"Loki cubre logs en el 95% de los casos web. El trade-off es la indexación: Loki indexa solo labels, no el contenido completo. Para búsqueda rica en logs con términos full-text complejos, ELK u OpenSearch entran mejor. Para búsqueda por servicio, host, nivel de log, status code — que es lo que el 95% de los equipos realmente hace — Loki es más barato y más simple.",[12,17954,17955],{},"SigNoz y Tempo cubren APM con calidad. El trade-off es pulido. El profile de query lenta en el Datadog APM tiene más shine — años de UX en las vistas que importan. SigNoz está cerca y mejora a cada release; en casos de uso comunes (endpoint lento, query lenta, error spike) cubre tranquilamente. Para investigación forense de profile de una transacción rara, Datadog todavía gana en refinamiento.",[12,17957,17958],{},"Sentry self-hosted es prácticamente idéntico a Sentry SaaS — mismo equipo mantiene los dos. Instalas el stack vía Docker Compose, pasas quince minutos configurando, y tienes rastreo de errores en producción. Cuesta cero en licencia y dos a cuatro horas al mes de mantenimiento.",[19,17960,17962],{"id":17961},"la-arquitectura-concreta-en-una-stack-pequena","La arquitectura concreta en una stack pequeña",[12,17964,17965],{},"Para una startup operando cinco a diez servidores, la arquitectura cabe en un único servidor de observabilidad dedicado. Cuatro gigabytes de RAM resuelven.",[12,17967,17968,17971],{},[27,17969,17970],{},"Servidor de observabilidad (4 GB RAM)",": Prometheus consume en torno a 1,5 GB con series de cinco a diez nodes. Grafana queda en 200 MB. Loki en 1 GB con retención razonable. Tempo en 500 MB. Sobra espacio para Alertmanager (50 MB) y algún exporter o collector adicional.",[12,17973,17974,17977],{},[27,17975,17976],{},"Storage para métricas",": cinco servidores exponiendo cerca de 100 métricas por segundo cada uno, retenidas por 30 días, generan aproximadamente 10 GB de banco de series temporales. Disco SSD común da cuenta — típicamente R$30 al mes de almacenamiento adicional en la mayoría de los proveedores.",[12,17979,17980,17983],{},[27,17981,17982],{},"Storage para logs",": cinco servidores produciendo 1 GB de log por día, retenidos por 30 días, son 150 GB. La solución barata es apuntar Loki a un backend compatible con S3 — Cloudflare R2 cobra US$0,015 por GB por mes sin tarifa de egress, o sea, US$2,25 al mes para 150 GB. Backblaze B2 es equivalente. AWS S3 funciona pero tiene egress que duele si vas a leer mucho; para observability, R2 o B2 son elección obvia.",[12,17985,17986,17989],{},[27,17987,17988],{},"Sampling en traces",": trace de 100% suele ser desperdicio. Sampling de 1% a 5% para traces normales, 100% para traces que contienen error, 100% para endpoints específicos críticos. Reduce volumen en orden de magnitud sin perder la señal que importa.",[19,17991,17993],{"id":17992},"setup-honesto-pasos-sin-copy-paste","Setup honesto: pasos sin copy-paste",[12,17995,17996],{},"La diferencia entre tutorial de blog y operación real es el conocimiento de dónde los pasos se rompen. Aquí va la secuencia que funciona, con las trampas reales.",[12,17998,17999,18002],{},[27,18000,18001],{},"Paso 1: Prometheus en container."," Sube Prometheus apuntando el scrape config a los nodes que corren node_exporter. Cada nodo necesita node_exporter corriendo — también en container, puerto 9100. Configuración inicial son veinte líneas de YAML. Trampa: service discovery dinámico exige integración con la fuente verdadera de hosts. Para cluster pequeño, lista estática resuelve; para cluster que crece, integración con la API del orquestador.",[12,18004,18005,18008],{},[27,18006,18007],{},"Paso 2: Grafana en container."," Agrega Prometheus como datasource, importa tres a cinco dashboards listos del Grafana Marketplace — node_exporter full, container metrics, blackbox uptime son buenos puntos de partida. En quince minutos tienes dashboards mejores que mucho setup de Datadog que vi en producción.",[12,18010,18011,18014],{},[27,18012,18013],{},"Paso 3: Loki más Promtail (o Grafana Agent unificado) en cada nodo."," Promtail lee logs locales y empuja a Loki. Configuración mínima son cerca de treinta líneas — definir paths de log, labels, y endpoint de Loki. Trampa: log de aplicación que sale en formato libre te fuerza a escribir regex de parsing. Vale la inversión de una tarde para estandarizar logs en JSON estructurado antes de configurar parsing.",[12,18016,18017,18020],{},[27,18018,18019],{},"Paso 4: OpenTelemetry SDK en la aplicación."," Cada lenguaje tiene su SDK oficial. Inicializas en el bootstrap de la aplicación, defines el endpoint de Tempo (o SigNoz collector), y ganas tracing distribuido automático para HTTP, database, cache. Agregar spans customizados en puntos críticos es trivial.",[12,18022,18023,18026],{},[27,18024,18025],{},"Paso 5: Alertmanager."," Recibe reglas de alerta de Prometheus y rutea a Slack, email, PagerDuty o webhook de Discord. Trampa clásica: el primer mes vas a tener alert fatigue por threshold mal calibrado. Reserva una hora por semana en los primeros dos meses para refinar reglas.",[12,18028,18029],{},"Tiempo total para alguien sin experiencia previa: cuatro a ocho horas para tener el stack completo funcional, más dos a tres tardes refinando dashboards y alertas en las dos semanas siguientes. Al cambio de R$200 por hora de ingeniería, la inversión total es R$1,2 mil a R$2,5 mil. Sustituye R$1 mil a R$2 mil al mes de Datadog indefinidamente. Payback en uno a dos meses.",[19,18031,18033],{"id":18032},"donde-el-auto-hospedado-queda-debiendo","Donde el auto-hospedado queda debiendo",[12,18035,18036],{},"La honestidad aquí es la prueba de quién está vendiendo la alternativa de buena fe versus quien está vendiendo la versión simplificada de la realidad.",[12,18038,18039,18042],{},[27,18040,18041],{},"Database Monitoring profundo."," Datadog DBM tiene visibilidad detallada en Postgres y Redis, con plan de ejecución por query, lock waits, slow query analysis. El postgres_exporter cubre métricas de salud básicas — conexiones, transacciones, replicación, cache hit ratio. Slow query analysis profunda en open source exige pgBadger o raspado manual de pg_stat_statements, con bastante más trabajo que clicar en \"Enable DBM\" en Datadog.",[12,18044,18045,18048],{},[27,18046,18047],{},"Real User Monitoring."," Datadog RUM mide tiempo de carga percibido por el usuario real, distribuido por geografía, navegador, dispositivo. La combinación de Sentry con Plausible cubre parte del espacio, pero con gaps. Si RUM detallado es parte central de la estrategia de producto, Datadog gana hoy.",[12,18050,18051,18054],{},[27,18052,18053],{},"Network Performance Monitoring."," Datadog NPM tiene visibilidad de paquete en redes complejas, especialmente útil en arquitecturas que cruzan múltiples zonas. No hay equivalente self-hosted práctico para el caso general.",[12,18056,18057,18060],{},[27,18058,18059],{},"Synthetic monitoring global."," Datadog corre checks de más de treinta regiones. Self-hosted exige que corras checks de regiones múltiples — viable pero trabajoso. Checkly cubre el vacío con tier intermedio accesible.",[12,18062,18063],{},"Resumen: el 95% de los casos de observabilidad que startup necesita están cubiertos. El 5% que queda fuera son features enterprise raramente usadas en startup.",[19,18065,18067],{"id":18066},"costo-concreto-comparado","Costo concreto comparado",[12,18069,18070],{},"Vale la pena hacer la planilla en real, con números que puedes reproducir.",[12,18072,18073],{},"Datadog en cinco hosts, con APM Pro, 100 GB de logs por mes, 30 métricas customizadas y RUM activo: cerca de US$400 al mes, o R$2 mil al cambio de R$5 por dólar.",[12,18075,18076],{},"Stack auto-hospedada en una VPS dedicada con 4 GB de RAM (R$80 al mes en la mayoría de los proveedores brasileños), más almacenamiento de logs en S3-compatible (R$30 al mes para 150 GB en R2 o B2), más valor estimado de tiempo de mantenimiento (dos horas al mes a R$200 por hora, R$400 al mes): R$510 al mes.",[12,18078,18079],{},"Diferencia mensual: R$1.490. Diferencia anual: R$17.880. En tres años, R$53 mil — equivalente al salario de dos meses de persona sénior, o al costo de adquirir un cliente medio en ventas B2B.",[12,18081,18082],{},"Importante: el tiempo de mantenimiento es estimación pesimista. Equipos que estandarizan el setup típicamente gastan menos de una hora al mes después de la inversión inicial. En tres años, el mantenimiento compone pero no se vuelve proyecto continuo.",[19,18084,18086],{"id":18085},"como-heroctl-encaja","Cómo HeroCtl encaja",[12,18088,18089],{},"El orquestador expone métricas del cluster en formato Prometheus por default. No hay agente propietario que instalar en cada servidor — el cluster expone agregado en endpoint único, y Prometheus raspa directo.",[12,18091,18092],{},"Logs siguen arquitectura de escritor único embebida. En lugar de cada container producir log que necesita ser recolectado por un agente en cada nodo, el cluster centraliza la captura y expone interfaz de consulta. Eso reduce overhead operacional — no montas un agente en cada servidor.",[12,18094,18095],{},"La stack OSS (Prometheus, Grafana, Loki, Tempo, Sentry) corre como jobs en el propio cluster. Sometes el manifiesto de Prometheus como cualquier otro servicio, y el orquestador cuida de health check, restart, rolling update y ruteo. Overhead operacional adicional: cero.",[12,18097,18098],{},"Para startup que ya corre HeroCtl, activar observabilidad completa es una tarde. El cluster ya da todo de plumbing — falta solo decidir los dashboards.",[19,18100,18102],{"id":18101},"comparativo-datadog-vs-new-relic-vs-stack-oss-auto-hospedada","Comparativo: Datadog vs New Relic vs Stack OSS auto-hospedada",[119,18104,18105,18120],{},[122,18106,18107],{},[125,18108,18109,18111,18114,18117],{},[128,18110,2983],{},[128,18112,18113],{},"Datadog",[128,18115,18116],{},"New Relic",[128,18118,18119],{},"Stack OSS auto-hospedada",[141,18121,18122,18136,18149,18162,18175,18187,18201,18215,18227,18239],{},[125,18123,18124,18127,18130,18133],{},[146,18125,18126],{},"Costo mensual para 5 hosts",[146,18128,18129],{},"R$1k-2k",[146,18131,18132],{},"R$800-1.5k",[146,18134,18135],{},"R$80-510",[125,18137,18138,18140,18143,18146],{},[146,18139,17902],{},[146,18141,18142],{},"Excelente, integraciones de 1 clic",[146,18144,18145],{},"Buena, integraciones fuertes",[146,18147,18148],{},"Prometheus + Grafana, exporters por target",[125,18150,18151,18153,18156,18159],{},[146,18152,17908],{},[146,18154,18155],{},"Excelente, búsqueda rica",[146,18157,18158],{},"Buena, búsqueda rica",[146,18160,18161],{},"Loki, búsqueda por label",[125,18163,18164,18166,18169,18172],{},[146,18165,17920],{},[146,18167,18168],{},"Profundidad líder de mercado",[146,18170,18171],{},"Próximo de Datadog",[146,18173,18174],{},"SigNoz\u002FTempo, 80% del shine",[125,18176,18177,18179,18182,18184],{},[146,18178,17914],{},[146,18180,18181],{},"Sampling avanzado",[146,18183,18181],{},[146,18185,18186],{},"OpenTelemetry, sampling configurable",[125,18188,18189,18192,18195,18198],{},[146,18190,18191],{},"Alerting",[146,18193,18194],{},"Anomaly detection, estacionalidad",[146,18196,18197],{},"Anomaly detection",[146,18199,18200],{},"Threshold + Alertmanager (sin AI)",[125,18202,18203,18206,18209,18212],{},[146,18204,18205],{},"Integraciones",[146,18207,18208],{},"600+ listas",[146,18210,18211],{},"400+ listas",[146,18213,18214],{},"100+ exporters comunitarios",[125,18216,18217,18219,18222,18224],{},[146,18218,17577],{},[146,18220,18221],{},"Baja (botón conecta)",[146,18223,18221],{},[146,18225,18226],{},"Media (config + mantenimiento)",[125,18228,18229,18231,18234,18236],{},[146,18230,7156],{},[146,18232,18233],{},"Alto (formato propietario)",[146,18235,18233],{},[146,18237,18238],{},"Cero (formatos abiertos)",[125,18240,18241,18243,18246,18249],{},[146,18242,13540],{},[146,18244,18245],{},"Series B+ con ingresos",[146,18247,18248],{},"Series A-B con ingresos",[146,18250,18251],{},"Bootstrapped, seed, Series A",[12,18253,18254],{},"La última columna es la que importa para startup brasileña. El lock-in cero significa que si la stack OSS deja de servir, migras los dashboards y reglas con inversión contenida — formato abierto corre en cualquier lugar.",[19,18256,18258],{"id":18257},"cuando-quedarse-en-datadog","Cuándo quedarse en Datadog",[12,18260,18261],{},"La honestidad obliga a apuntar cuándo la alternativa no compensa.",[12,18263,18264,18267],{},[27,18265,18266],{},"Empresa Series B o mayor con ingresos justificando."," Por encima de US$5 millones de ARR, R$2 mil al mes desaparece en el presupuesto. El tiempo que ahorras no montando stack vale más que el caja.",[12,18269,18270,18273],{},[27,18271,18272],{},"Compliance que exige proveedor SOC2 o ISO certificado nominalmente."," Algunos frameworks listan herramientas pre-aprobadas. Si necesitas el nombre Datadog o New Relic en una lista de auditoría, la alternativa no cabe.",[12,18275,18276,18279],{},[27,18277,18278],{},"Equipo sin capacidad para montar stack."," Si el equipo de ingeniería tiene tres personas enfocadas en producto y cero en infra, montar Prometheus más Grafana más Loki es distracción de cuatro a ocho horas que el equipo no tiene. Datadog free tier o New Relic free tier resuelven el inicio.",[12,18281,18282,18285],{},[27,18283,18284],{},"Necesidad de NPM o DBM grado enterprise."," Para los 5% de los casos donde Datadog tiene feature insustituible, quedarse en él es decisión técnica correcta.",[19,18287,4245],{"id":4244},[12,18289,18290,18293],{},[27,18291,18292],{},"¿Puedo usar Datadog free tier?","\nSí, y tiene sentido para empezar. Cinco hosts, retención corta, sin APM, sin logs avanzados. Funciona para equipo de dos personas validando idea. La migración empieza cuando el tier gratuito se acaba y la estimación de costo aparece — generalmente entre seis y doce meses después.",[12,18295,18296,18299],{},[27,18297,18298],{},"¿Grafana Cloud es una buena alternativa intermedia?","\nLo es. Grafana Cloud free tier ofrece 10k series, 50 GB de logs, 50 GB de traces. Pago empieza en US$8 al mes con volumen razonable. Cubre la franja entre \"Datadog es muy caro\" y \"auto-hospedar da trabajo\". Trade-off es el lock-in moderado — formatos son abiertos, pero no controlas retención y costos quedan en otra planilla.",[12,18301,18302,18305],{},[27,18303,18304],{},"¿Cuánto cuesta storage de logs en S3-compatible en Brasil?","\nCloudflare R2 cobra US$0,015 por GB por mes, sin tarifa de egress. Backblaze B2 cobra US$0,005 por GB por mes con US$0,01 por GB de egress. Para 150 GB en R2: US$2,25 al mes, o R$11. Para 1 TB en B2: US$5 al mes más egress según uso. En ambos casos, el costo es despreciable.",[12,18307,18308,18311],{},[27,18309,18310],{},"¿OpenTelemetry vs StatsD?","\nOpenTelemetry es el estándar actual y cubre métricas, traces y logs. StatsD fue el estándar de los años 2010 para métricas, todavía existe, pero es narrow. Si estás empezando, ve directo en OpenTelemetry — todos los SDKs modernos soportan, todos los backends modernos soportan, y la inversión de aprender vale por años.",[12,18313,18314,18317],{},[27,18315,18316],{},"¿Sentry vale la pena auto-hospedar?","\nPara equipo pequeño, GlitchTip resuelve con menos overhead — instalación simple, misma API que Sentry, drop-in compatible con SDKs. Para equipo que necesita las features avanzadas (Performance, Profiling, Replay), Sentry self-hosted vale el trabajo de montar Docker Compose. Free tier de Sentry SaaS es generoso y cubre el inicio.",[12,18319,18320,18323],{},[27,18321,18322],{},"¿Cuánto consume la stack OSS en RAM y CPU?","\nPara cinco a diez nodes monitoreados: Prometheus 1,5 GB de RAM, Grafana 200 MB, Loki 1 GB, Tempo 500 MB. Total en torno a 3,5 GB. CPU promedio es bajo — pico en los scrapes de 5 a 10% de una vCPU. Cabe en VPS de 4 GB con holgura.",[12,18325,18326,18329],{},[27,18327,18328],{},"¿HeroCtl tiene dashboards listos?","\nSí. El cluster expone métricas en formato Prometheus, y el panel de administración embebido incluye dashboards básicos por job — uso de CPU, memoria, status de réplicas, latencia de health check. Para dashboards más elaborados, sube Grafana como job en el propio cluster y apunta al endpoint de métricas del plano de control.",[19,18331,3310],{"id":3309},[12,18333,18334],{},"La diferencia entre R$2 mil y R$500 al mes no es detalle — es R$18 mil al año. Para startup en etapa de validación, es lo que separa contratar persona adicional y quedarse en el equipo actual. Para startup en etapa de crecimiento, es el margen que justifica invertir en producto en lugar de en proveedor.",[12,18336,18337],{},"La elección no es \"Datadog o nada\". Es \"qué herramienta sirve a la fase actual de la empresa\". En fase early, la stack OSS auto-hospedada gana en costo con paridad funcional. En fase late, Datadog gana en productividad con costo absorbido. El error común es seguir pagando Datadog porque nunca fue reevaluado — auditoría anual de stack es práctica de empresa madura, incluso entre las que eligen seguir pagando.",[12,18339,18340],{},"Si corres HeroCtl, la stack OSS sube como job común en el cluster. Sin agente extra, sin provisioner de infra, sin tercer proveedor. El presupuesto que sobra va al próximo ingeniero contratado.",[224,18342,18344],{"className":18343,"code":5318,"language":2530},[2528],[231,18345,5318],{"__ignoreMap":229},[12,18347,18348,18349,2403,18351,101],{},"Para continuar la lectura: ",[3337,18350,6338],{"href":6337},[3337,18352,18353],{"href":7466},"Postgres en producción: gestionado vs self-hosted",{"title":229,"searchDepth":244,"depth":244,"links":18355},[18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,18368],{"id":17837,"depth":244,"text":17838},{"id":17859,"depth":244,"text":17860},{"id":17893,"depth":244,"text":17894},{"id":17945,"depth":244,"text":17946},{"id":17961,"depth":244,"text":17962},{"id":17992,"depth":244,"text":17993},{"id":18032,"depth":244,"text":18033},{"id":18066,"depth":244,"text":18067},{"id":18085,"depth":244,"text":18086},{"id":18101,"depth":244,"text":18102},{"id":18257,"depth":244,"text":18258},{"id":4244,"depth":244,"text":4245},{"id":3309,"depth":244,"text":3310},"2026-04-08","Datadog cobra US$15-31\u002Fhost\u002Fmes. Para startup con 5 servidores, eso se vuelve R$1k\u002Fmes solo de monitoring. La stack auto-hospedada llega al mismo lugar por R$50.",{},{"title":17823,"description":18370},{"loc":11725},"es\u002Fblog\u002Fobservabilidad-sin-datadog-stack-startup",[18376,18377,11788,18378,6394],"observabilidad","datadog","open-source","bID7qFQiQQ2xElKDQratH8aFgucCG4LlqznPPVaol2s",{"id":18381,"title":18382,"author":7,"body":18383,"category":3379,"cover":3380,"date":19109,"description":19110,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":19111,"navigation":411,"path":4369,"readingTime":4402,"seo":19112,"sitemap":19113,"stem":19114,"tags":19115,"__hash__":19118},"blog_es\u002Fes\u002Fblog\u002Fmulti-tenant-saas-aislamiento-real.md","Multi-tenant SaaS: aislamiento real — 3 patrones y cuándo cada uno se vuelve pesadilla",{"type":9,"value":18384,"toc":19096},[18385,18392,18395,18399,18402,18408,18414,18420,18426,18433,18437,18444,18455,18460,18485,18490,18519,18525,18529,18532,18550,18555,18580,18585,18609,18615,18619,18629,18636,18639,18644,18669,18674,18691,18697,18699,18860,18863,18867,18870,18876,18882,18888,18894,18897,18901,18904,18910,18922,18931,18937,18940,18944,18947,18953,18959,18965,18971,18980,18984,18987,18993,19003,19009,19012,19014,19020,19030,19036,19042,19058,19064,19070,19072,19075,19078,19081,19086,19089],[12,18386,18387,18388,18391],{},"La primera pregunta de un comprador B2B serio, después de que el producto pasa por la demo y antes de que el jurídico entre a la sala, es siempre la misma: \"¿mis datos están aislados de los otros clientes?\". Si tu respuesta es \"ah, filtramos por ",[231,18389,18390],{},"tenant_id"," en cada query\", el contrato acaba de volverse humo. El comprador no está pidiendo una justificación técnica — está pidiendo una garantía que sobreviva a una auditoría, a un incidente, y a una rotación de dev júnior.",[12,18393,18394],{},"Existen tres patrones reales de aislamiento multi-tenant en SaaS B2B. Cada uno tiene beneficios obvios en la presentación y costos invisibles en la operación. Este post mapea los tres, muestra exactamente cuándo cada uno se vuelve pesadilla, y explica el viaje típico de una startup brasileña que empieza con cincuenta clientes pequeños y termina atendiendo a un banco regulado.",[19,18396,18398],{"id":18397},"por-que-eso-importa-ahora-no-el-ano-que-viene","Por qué eso importa ahora — no el año que viene",[12,18400,18401],{},"Multi-tenancy es una decisión arquitectural que parece postergable hasta el exacto momento en que deja de serlo. Cuatro fuerzas están empujando esa decisión al frente del roadmap de las startups B2B brasileñas en 2026:",[12,18403,18404,18407],{},[27,18405,18406],{},"LGPD se volvió exigencia práctica, no solo legal."," La ley está en vigor desde 2020, pero los DPOs corporativos empezaron a pedir evidencia operacional solo en los últimos dos años. La pregunta dejó de ser \"¿están en conformidad?\" y se volvió \"¿cómo demuestran tratamiento adecuado de datos personales?\". Demostración exige separación visible, log de acceso, y proceso claro de exclusión. Pool puro vuelve todo eso más difícil — no imposible, pero más difícil de justificar a un auditor que nunca vio tu arquitectura.",[12,18409,18410,18413],{},[27,18411,18412],{},"Cliente B2B grande exige aislamiento como prerrequisito de contrato."," Ese es el punto del párrafo de apertura. Si tu pipeline tiene una propuesta de R$ 50 mil al mes con una operación de logística regional, es prácticamente seguro que el departamento de seguridad de la información de ellos va a mandar un cuestionario de ciento ochenta preguntas. Casi la mitad de las preguntas es sobre aislamiento. Responder \"compartimos una base con filtros lógicos\" entrega la cuenta al competidor que respondió \"schema dedicado por cliente\" — aunque la diferencia real, en términos de riesgo, sea pequeña.",[12,18415,18416,18419],{},[27,18417,18418],{},"Compliance sectorial puede exigir aislamiento físico."," Salud (LGPD + CFM), financiero (Bacen, CVM), educación básica privada (LGPD + ECA), seguros (SUSEP). Sectores regulados ocasionalmente listan \"segregación de datos por cliente en capa física\" como control exigido. Cuando eso aparece, schema-per-tenant resuelve con algún esfuerzo; pool no resuelve.",[12,18421,18422,18425],{},[27,18423,18424],{},"Un cliente va a volverse diez veces mayor que los otros."," La distribución de uso en SaaS B2B sigue ley de potencia. Tu mayor cliente va a consumir más recursos que los cincuenta menores sumados. En el pool puro, ese cliente degrada la experiencia de todos los demás — y no logras cobrar más por eso sin un modelo de cobranza que precise uso, lo que nadie quiere construir antes de lo necesario.",[12,18427,18428,18429,18432],{},"Y la quinta fuerza, tal vez la más importante: ",[27,18430,18431],{},"migrar de un patrón a otro después de tener clientes en producción es proyecto de meses, no de días."," Vas a elegir mal en algún eje — todo el mundo elige — pero elegir conscientemente hace la diferencia entre \"refactorización de seis semanas\" y \"reescritura de seis meses\".",[19,18434,18436],{"id":18435},"patron-1-pool-comparte-todo","Patrón 1 — Pool (comparte todo)",[12,18438,18439,18440,18443],{},"Setup más simple posible. Una base de datos, una instancia de la aplicación, una stack de infraestructura. Todos los clientes viven en las mismas tablas. Cada query de la aplicación tiene un filtro adicional ",[231,18441,18442],{},"WHERE tenant_id = ?"," inyectado por un middleware antes de llegar a la base. Postgres Row-Level Security (RLS) refuerza ese filtro en el nivel de la base — una segunda capa que dispara incluso si el middleware de la aplicación olvida.",[12,18445,18446,18447,18450,18451,18454],{},"Onboarding de nuevo cliente es literalmente un ",[231,18448,18449],{},"INSERT"," en la tabla ",[231,18452,18453],{},"tenants",". Treinta milisegundos después el cliente ya tiene ambiente funcional. El costo marginal de agregar tenant es prácticamente cero — solo estás usando más líneas en la misma base, más bytes en el mismo cache.",[12,18456,18457],{},[27,18458,18459],{},"Puntos fuertes del pool:",[2735,18461,18462,18465,18468,18471,18478],{},[70,18463,18464],{},"Costo operacional bajo. Una base para hacer backup, una stack para monitorear, una versión de aplicación corriendo.",[70,18466,18467],{},"Onboarding instantáneo. Flujo de signup con tarjeta de crédito es trivial.",[70,18469,18470],{},"Escala sublineal. Mil clientes no cuestan mil veces más que uno.",[70,18472,18473,18474,18477],{},"Cross-tenant analytics son naturales. Dashboard interno de \"cuántos usuarios activos en el mes\" es un ",[231,18475,18476],{},"SELECT COUNT(*)"," sin gimnasia.",[70,18479,18480,18481,18484],{},"Migrations son simples. Un ",[231,18482,18483],{},"ALTER TABLE"," aplica para todos los clientes al mismo tiempo.",[12,18486,18487],{},[27,18488,18489],{},"Puntos débiles del pool:",[2735,18491,18492,18503,18506,18509,18512],{},[70,18493,18494,18495,18498,18499,18502],{},"Bug de SQL es incidente crítico. Un ",[231,18496,18497],{},"WHERE"," olvidado, un ",[231,18500,18501],{},"JOIN"," que filtra a otro contexto, una migration mal escrita — y datos del cliente A aparecen en la pantalla del cliente B. Ese incidente ya mató empresas (literalmente: contratos cancelados en masa, pérdida de confianza irreversible). RLS en Postgres es el cinturón de seguridad que reduce drásticamente ese riesgo, pero exige disciplina para configurar bien y probar todas las roles.",[70,18504,18505],{},"Vecino ruidoso. Un cliente que dispara un reporte pesado a las catorce horas del martes consume el pool de conexiones y degrada la latencia de todos los demás. Puedes agregar límites de query por tenant, pero eso es trabajo adicional.",[70,18507,18508],{},"Backup es todo-o-nada. Restaurar un cliente específico después de una operación destructiva exige snapshot de la base entera, restore en ambiente paralelo, y export-import selectivo. Operación pesada de una a cuatro horas.",[70,18510,18511],{},"Compliance que exige separación física no atiende. Si el cliente pregunta \"¿dónde físicamente moran mis datos?\", la respuesta es \"en el mismo archivo de datos que los de todos los demás clientes\" — verdad que aleja perfiles específicos.",[70,18513,18514,18515,18518],{},"Customización se vuelve columna nullable. Cliente Y necesita un campo extra. Lo agregas. Otro cliente no usa ese campo. En seis meses nadie recuerda para qué sirve aquella columna ",[231,18516,18517],{},"extra_data_3",". Esa acumulación es uno de los síntomas más previsibles del pool maduro.",[12,18520,18521,18524],{},[27,18522,18523],{},"Cuándo el pool tiene sentido:"," SaaS B2B SMB (clientes pequeños y medianos), tenants relativamente similares en uso, bajo riesgo regulatorio, equipo de ingeniería pequeño (tres a ocho personas), producto todavía buscando product-market fit. Prácticamente todo SaaS empieza aquí — y está correcto. El error no es empezar con pool; es no saber cuándo salir.",[19,18526,18528],{"id":18527},"patron-2-schema-per-tenant-base-compartida-schemas-separados","Patrón 2 — Schema-per-tenant (base compartida, schemas separados)",[12,18530,18531],{},"Medio término arquitectural. Todavía tienes una instancia de base — una instancia de Postgres corriendo, con sus parámetros, conexiones, replicación. Pero dentro de ella, cada cliente tiene su propio schema. Postgres llama de schema; MySQL llama de database; el concepto es el mismo: namespace nombrado dentro del servidor, con tablas propias, índices propios, y privilegios propios.",[12,18533,18534,18535,18538,18539,18542,18543,571,18546,18549],{},"La aplicación selecciona el schema correcto vía ",[231,18536,18537],{},"SET search_path TO tenant_acme"," (o equivalente) al inicio de cada conexión, basado en qué tenant está haciendo la request. Las tablas existen con la misma estructura en todos los schemas, pero son físicamente separadas: schema ",[231,18540,18541],{},"tenant_acme"," tiene sus propias filas de ",[231,18544,18545],{},"users",[231,18547,18548],{},"tenant_xyz"," tiene las suyas, y queries dentro de un schema no ven el otro sin privilegio explícito.",[12,18551,18552],{},[27,18553,18554],{},"Puntos fuertes del schema-per-tenant:",[2735,18556,18557,18564,18571,18574,18577],{},[70,18558,18559,18560,18563],{},"Aislamiento de datos fuerte por default. Sin ",[231,18561,18562],{},"WHERE tenant_id"," en ningún lugar — las tablas están físicamente separadas. Bug de SQL queda circunscrito al schema actual.",[70,18565,18566,18567,18570],{},"Backup por tenant es práctico. ",[231,18568,18569],{},"pg_dump --schema=tenant_acme"," exporta solo aquel cliente. Restaurar es lo mismo: subir en un ambiente paralelo, importar el schema, y mover datos específicos.",[70,18572,18573],{},"Cuotas de recurso por schema. Postgres permite limitar conexiones por role, y roles pueden estar atadas a schemas. Puedes garantizar que tenant grande no consume todas las conexiones de la base.",[70,18575,18576],{},"Customización limpia. ¿Cliente Y necesita un campo extra? Agrégalo en el schema de él solamente. Otros clientes ni saben que aquel campo existe. El esquema base sigue limpio.",[70,18578,18579],{},"Demostración de separación queda obvia para auditoría. \"Cada cliente tiene su propio namespace de base con privilegios aislados\" es respuesta que satisface la mayor parte de los cuestionarios de seguridad.",[12,18581,18582],{},[27,18583,18584],{},"Puntos débiles del schema-per-tenant:",[2735,18586,18587,18590,18597,18603,18606],{},[70,18588,18589],{},"Migrations multiplican por N. Una migration de diez minutos con mil schemas se vuelve ciento sesenta horas de trabajo de base si corre en serie. Necesitas paralelismo cuidadoso, scripts de migration que conocen el conjunto de schemas, y ventana de mantenimiento planeada — o estrategia de migrations sin bloqueo que funcione esquema-a-esquema.",[70,18591,18592,18593,18596],{},"Pool de conexiones queda complicado. Si cada conexión necesita ",[231,18594,18595],{},"SET search_path"," por tenant, el pgBouncer simple no funciona — él reusa conexiones entre clientes diferentes. Soluciones: pool por schema (rompe cardinalidad), session-mode pooling (más lento), o middleware de la aplicación que gestiona el reset.",[70,18598,18599,18600,18602],{},"Cross-tenant analytics se vuelven caros. Para responder \"¿cuántos usuarios activos tengo en todos los clientes?\" necesitas unionar mil tablas. Solución real: ETL diario para un warehouse separado (ClickHouse, BigQuery), con ",[231,18601,18390],{}," desnormalizado.",[70,18604,18605],{},"Bug en código de switching todavía es riesgo. Si el middleware selecciona el schema equivocado por bug de session leakage entre requests, tienes el mismo tipo de filtración que el pool tiene. Menos común, pero posible.",[70,18607,18608],{},"Límite práctico de schemas. Postgres aguanta decenas de miles de schemas, pero el catálogo de la base queda pesado en algún punto — listados lentos, autovacuum compitiendo. Empresas que corren más de cinco mil schemas en una instancia única reportan dolor.",[12,18610,18611,18614],{},[27,18612,18613],{},"Cuándo el schema-per-tenant tiene sentido:"," SaaS B2B mid-market, diez a mil clientes, algunos clientes de alto valor que justifican customización, compliance moderada. Es el patrón \"intermedio\" en el sentido literal — cambias un poco de la simplicidad operacional del pool por un aislamiento más fuerte y por flexibilidad de customización.",[19,18616,18618],{"id":18617},"patron-3-app-per-tenant-silo-completo","Patrón 3 — App-per-tenant (silo completo)",[12,18620,18621,18622,571,18625,18628],{},"Cada cliente recibe instancia dedicada de todo: aplicación, base, cache, cola de jobs, agendador. Lo que comparten es solo la infraestructura física — el cluster de máquinas donde los contenedores corren. Pero cada workload tiene su propia base con sus propios datos, su propia URL (",[231,18623,18624],{},"acme.app.com",[231,18626,18627],{},"cliente-xyz.app.com","), y potencialmente su propia versión de la aplicación.",[12,18630,18631,18632,18635],{},"Implementación seria de ese patrón exige orquestador. Sin orquestación, provisionar un nuevo cliente significa crear manualmente máquina virtual, correr setup de base, deploy de la aplicación, configurar DNS, emitir certificado TLS — operación de horas que nadie va a aguantar repetir veinte veces al mes. Con orquestador, eso es un job parametrizado: disparas una definición que dice \"nuevo tenant ",[231,18633,18634],{},"acme",", plan enterprise, base aislada, certificado automático\", el cluster aloca, configura, y dispara en uno a tres minutos.",[12,18637,18638],{},"Kubernetes hace eso con namespaces y Helm. HeroCtl hace con job templates. Otros orquestadores hacen con primitivas propias. Lo que importa es que el tiempo de onboarding de un nuevo cliente en esa arquitectura — minutos, no segundos como en el pool — no se vuelva dolor humano porque está automatizado.",[12,18640,18641],{},[27,18642,18643],{},"Puntos fuertes del app-per-tenant:",[2735,18645,18646,18649,18660,18663,18666],{},[70,18647,18648],{},"Aislamiento máximo. No hay código compartido consultando datos de más de un cliente — físicamente imposible. Bug de SQL afecta solo al cliente de aquella instancia.",[70,18650,18651,18652,18655,18656,18659],{},"Customización total. Cliente A puede correr versión ",[231,18653,18654],{},"2.4"," de la aplicación, cliente B versión ",[231,18657,18658],{},"2.5",". Útil para pruebas graduales de release, o para atender a clientes que pidieron un patch específico.",[70,18661,18662],{},"Falla aislada. Si la base del cliente A se corrompió, cliente B ni percibe. Cliente A tiene outage; cliente B no tiene.",[70,18664,18665],{},"Compliance pesada se vuelve viable. FedRAMP, HIPAA con requisitos multi-tenant rígidos, contratos con cláusula de \"infraestructura dedicada\" — todos pasan.",[70,18667,18668],{},"Deploys regionales por cliente. ¿Cliente brasileño con exigencia de datos en territorio nacional? Corre en el datacenter de São Paulo. ¿Cliente europeo? Frankfurt. La primitiva de \"correr tenant donde necesita estar\" pasa a existir.",[12,18670,18671],{},[27,18672,18673],{},"Puntos débiles del app-per-tenant:",[2735,18675,18676,18679,18682,18685,18688],{},[70,18677,18678],{},"Costo escala lineal. Mil clientes pequeños cuestan aproximadamente mil veces más que un cliente. Sin ganancia de pool. Para clientes de bajo ticket, el margen desaparece.",[70,18680,18681],{},"Onboarding lleva minutos, no segundos. Puede ser inaceptable para modelos self-service con signup por tarjeta de crédito. Funciona para modelos de venta asistida donde el onboarding es proceso, no flujo de compra.",[70,18683,18684],{},"Operación multiplica por N. Cada base necesita backup, cada aplicación necesita monitoreo, cada deploy necesita validación. Sin herramientas de orquestación centralizada, se vuelve inviable en dos decenas de clientes.",[70,18686,18687],{},"Cross-tenant analytics son caros. Peor que schema-per-tenant — tienes que sincronizar datos de bases completamente separadas. ETL para warehouse común es aún más necesario.",[70,18689,18690],{},"Costo de infraestructura mínimo por tenant. Cada Postgres dedicado tiene overhead de doscientos a quinientos megabytes de RAM aun ocioso. Cada aplicación Go o Node más cien a doscientos megabytes. El piso de gasto es real.",[12,18692,18693,18696],{},[27,18694,18695],{},"Cuándo el app-per-tenant tiene sentido:"," SaaS enterprise, ARR alto por cliente (R$ 10 mil\u002Fmes por cliente para arriba es referencia confortable), compliance exigente, customización cliente es diferencial competitivo. Funciona también en contextos de cincuenta a mil clientes donde el ticket promedio sostiene el costo. Empresas que venden self-service en Stripe y cobran R$ 99\u002Fmes por usuario no caben aquí — la economía no cierra.",[19,18698,17389],{"id":17388},[119,18700,18701,18716],{},[122,18702,18703],{},[125,18704,18705,18707,18710,18713],{},[128,18706,2983],{},[128,18708,18709],{},"Pool",[128,18711,18712],{},"Schema-per-tenant",[128,18714,18715],{},"App-per-tenant",[141,18717,18718,18732,18746,18760,18774,18791,18805,18819,18833,18847],{},[125,18719,18720,18723,18726,18729],{},[146,18721,18722],{},"Costo por tenant",[146,18724,18725],{},"Sublineal (casi cero adicional)",[146,18727,18728],{},"Casi lineal (overhead pequeño)",[146,18730,18731],{},"Lineal (instancia dedicada)",[125,18733,18734,18737,18740,18743],{},[146,18735,18736],{},"Tiempo de onboarding",[146,18738,18739],{},"Segundos (INSERT)",[146,18741,18742],{},"Segundos a minutos (CREATE SCHEMA + migrate)",[146,18744,18745],{},"Minutos (provisionar pila)",[125,18747,18748,18751,18754,18757],{},[146,18749,18750],{},"Performance overhead",[146,18752,18753],{},"Ninguno (comparte cache, etc)",[146,18755,18756],{},"Pequeño (más relations en el catálogo)",[146,18758,18759],{},"Alto (overhead por instancia)",[125,18761,18762,18765,18768,18771],{},[146,18763,18764],{},"Riesgo de leak por bug",[146,18766,18767],{},"Alto (mitigado por RLS)",[146,18769,18770],{},"Medio (mitigado por search_path)",[146,18772,18773],{},"Prácticamente nulo",[125,18775,18776,18779,18782,18788],{},[146,18777,18778],{},"Backup por tenant",[146,18780,18781],{},"Difícil (snapshot completo)",[146,18783,18784,18785,16057],{},"Fácil (",[231,18786,18787],{},"pg_dump --schema",[146,18789,18790],{},"Trivial (backup dedicado)",[125,18792,18793,18796,18799,18802],{},[146,18794,18795],{},"Customización cliente",[146,18797,18798],{},"Cara (columnas nullable)",[146,18800,18801],{},"Buena (campos extras en el schema)",[146,18803,18804],{},"Total (versión propia de la app)",[125,18806,18807,18810,18813,18816],{},[146,18808,18809],{},"Compliance enterprise",[146,18811,18812],{},"Difícil de demostrar",[146,18814,18815],{},"Demostrable",[146,18817,18818],{},"Fuerte por construcción",[125,18820,18821,18824,18827,18830],{},[146,18822,18823],{},"Rango de tenants ideal",[146,18825,18826],{},"1 a 10 mil",[146,18828,18829],{},"10 a 5 mil",[146,18831,18832],{},"10 a 1.000",[125,18834,18835,18838,18841,18844],{},[146,18836,18837],{},"Cross-tenant analytics",[146,18839,18840],{},"Trivial (una query)",[146,18842,18843],{},"Pesado (UNION N tablas o ETL)",[146,18845,18846],{},"Pesado (ETL obligatorio)",[125,18848,18849,18851,18854,18857],{},[146,18850,16410],{},[146,18852,18853],{},"2 a 5 devs",[146,18855,18856],{},"4 a 10 devs con infra básica",[146,18858,18859],{},"4 a 10 devs con orquestador",[12,18861,18862],{},"Los límites superiores de rango de tenants son aproximados — empresas excedieron todos ellos con esfuerzo. Los números sirven como referencia de cuándo empieza a doler.",[19,18864,18866],{"id":18865},"el-viaje-tipico-de-saas-brasileno","El viaje típico de SaaS brasileño",[12,18868,18869],{},"La mayoría de los SaaS B2B brasileños sigue un camino previsible, y entender el camino ayuda a elegir la etapa actual sin subdimensionar ni superdimensionar.",[12,18871,18872,18875],{},[27,18873,18874],{},"Etapa 1: cero a cincuenta clientes."," Pool es la elección obvia. Equipo pequeño, costo bajo, nadie pidió compliance todavía, todos los clientes son parecidos en uso. Enfócate en product-market fit — cualquier hora gastada con aislamiento ahora es hora robada al producto. RLS en Postgres desde el día uno es la inversión mínima de defensa.",[12,18877,18878,18881],{},[27,18879,18880],{},"Etapa 2: cincuenta a quinientos clientes, primer cliente B2B mid-market llega."," Aquí empieza a apretar. Aquel cliente con ciento cincuenta usuarios consume seis veces más recursos que los demás. El cuestionario de seguridad llega con la pregunta sobre aislamiento. Evaluar schema-per-tenant queda racional. Híbrido también es opción: pool para los pequeños, schema dedicado para los mayores que pidieron explícitamente. Migración en esa etapa es menos dolorosa porque la base todavía es manejable.",[12,18883,18884,18887],{},[27,18885,18886],{},"Etapa 3: quinientos clientes o primer cliente enterprise."," Ahora la decisión es estructural. ¿Schema-per-tenant para todos? ¿App-per-tenant para los enterprise y schema para el resto? ¿Híbrido con tres capas (pool en los free, schema en los pagados, app en los enterprise)? La respuesta depende del mix de clientes — empresas con pocos clientes muy grandes tienden a app-per-tenant; empresas con mil clientes medianos quedan en schema-per-tenant.",[12,18889,18890,18893],{},[27,18891,18892],{},"Etapa 4: enterprise mode."," App-per-tenant para los high-value, con schema-per-tenant o pool sosteniendo a los menores. Ese es el estado de empresas como Salesforce (que históricamente hizo schema-per-tenant en escala extrema), Notion (pool altamente optimizado), y herramientas enterprise más nuevas que adoptan app-per-tenant desde el nacimiento.",[12,18895,18896],{},"La transición entre etapas es donde mora la ingeniería más cara de la carrera de un SaaS. Quien ya pasó por eso conoce el olor.",[19,18898,18900],{"id":18899},"como-heroctl-ayuda-en-la-etapa-3-y-4","Cómo HeroCtl ayuda en la etapa 3 y 4",[12,18902,18903],{},"El modelo app-per-tenant exige un orquestador competente. No es negociable: sin provisioning automatizado, la complejidad operacional inviabiliza el modelo. Cuatro primitivas que un orquestador necesita entregar para que app-per-tenant funcione, y cómo HeroCtl resuelve cada una:",[12,18905,18906,18909],{},[27,18907,18908],{},"Job templates parametrizados."," Describes \"tenant\" una vez — qué aplicación corre, qué base, qué ingress, qué variables de ambiente, qué cuota de CPU y memoria. Para cada cliente nuevo, solo varías los parámetros (nombre, subdominio, plan). En HeroCtl, eso es un job spec corto con placeholders de variables.",[12,18911,18912,2578,18915,18918,18919,18921],{},[27,18913,18914],{},"API de onboarding.",[231,18916,18917],{},"POST \u002Fv1\u002Fjobs"," con las variables del nuevo cliente. En segundos a pocos minutos, el cluster provisiona contenedores, sube la base, registra en el router interno, emite certificado TLS automático para ",[231,18920,18624],{},". Sin operación manual.",[12,18923,18924,18927,18928,18930],{},[27,18925,18926],{},"Ruteo integrado por subdominio."," Cada tenant gana un subdominio propio con TLS automático. El router interno del orquestador resuelve ",[231,18929,18624],{}," al contenedor correcto sin que configures DNS por cliente — wildcard de DNS apunta al cluster, y el orquestador hace el resto.",[12,18932,18933,18936],{},[27,18934,18935],{},"Cuotas y auditoría por tenant."," Cada job carga límites de recurso (CPU, RAM, disco). Cliente que intente consumir más de lo que el plan permite, satura en su propio límite y no afecta a los vecinos. En el plan Business, log detallado de quién deployó qué versión de qué tenant, cuándo — útil para auditoría interna y para responder cuestionarios de cliente.",[12,18938,18939],{},"El cluster público de HeroCtl corre hoy en cuatro servidores totalizando cinco vCPUs y diez gigabytes de RAM, sosteniendo múltiples sitios con TLS automático. Cuando un nodo coordinador cae, el cluster elige otro coordinador en cerca de siete segundos — ventana corta lo suficiente para que clientes no perciban, y detalle operacional importante para quien opera app-per-tenant en producción. No estamos prometiendo magia: estamos describiendo lo que ya corre.",[19,18941,18943],{"id":18942},"cinco-errores-caros-en-multi-tenant","Cinco errores caros en multi-tenant",[12,18945,18946],{},"Errores que aparecen con frecuencia suficiente para valer un aviso explícito.",[12,18948,18949,18952],{},[27,18950,18951],{},"Compartir schema desde el día uno sin RLS."," Pool sin Row-Level Security es apenas una capa de defensa: el middleware de la aplicación. Una capa falla en algún momento. RLS es la segunda capa — barata de configurar, y diferencia entre incidente vergonzoso e incidente fatal. Configura desde el inicio, aunque el equipo lo encuentre exagerado.",[12,18954,18955,18958],{},[27,18956,18957],{},"Migrar muy tarde de pool a schema."," Empresa que creció a diez mil clientes en pool y descubre que necesita migrar a schema-per-tenant tiene un proyecto de cuatro a ocho meses por delante. Reescritura del middleware, migración de datos en ventanas, validación por cliente. Quien migró en quinientos tenants gastó tres semanas; quien migró en diez mil gastó un trimestre.",[12,18960,18961,18964],{},[27,18962,18963],{},"Customización ad-hoc en el pool."," Cliente Y pide un campo extra. Lo agregas como columna nullable. En tres meses otros clientes pidieron otras tres columnas. En seis meses nadie entiende más la tabla. Lo que parecía atajo se vuelve deuda que paga intereses cada sprint. Resiste a ese patrón; o acepta que necesitas schema-per-tenant para atender a esas customizaciones limpiamente.",[12,18966,18967,18970],{},[27,18968,18969],{},"Backup solo de la base principal."," Cuando sales del pool, backup necesita ser repensado. Schema separado necesita backup separado consciente. App-per-tenant necesita backup por base. Olvidar eso y descubrir en un incidente es catastrófico — empresas perdieron datos de cliente único porque el backup global no cubría las bases por tenant.",[12,18972,18973,18976,18977,18979],{},[27,18974,18975],{},"Cross-tenant analytics en el schema-per-tenant vía UNION."," Funciona en diez clientes, queda pesado en cien, se vuelve inviable en mil. Construye ETL para warehouse separado desde temprano — ClickHouse o BigQuery con ",[231,18978,18390],{}," desnormalizado es la solución estándar. Intentar mantener todo en el transaccional es receta de query de cuarenta minutos.",[19,18981,18983],{"id":18982},"lgpd-y-multi-tenancy","LGPD y multi-tenancy",[12,18985,18986],{},"LGPD no obliga modelo arquitectural específico, pero obliga demostración de tratamiento adecuado. Cada patrón tiene implicaciones diferentes.",[12,18988,18989,18992],{},[27,18990,18991],{},"Pool:"," necesitas demostrar separación lógica robusta (RLS configurado, probado, auditado), log de acceso a datos personales (quién leyó qué, cuándo), y proceso de exclusión que cubre todas las tablas relevantes para el derecho al olvido (artículo 18). Todo viable, pero con más trabajo de demostración.",[12,18994,18995,18998,18999,19002],{},[27,18996,18997],{},"Schema-per-tenant:"," demostración queda más simple. \"Cada cliente tiene su schema aislado, con privilegios propios, y exclusión de datos es ",[231,19000,19001],{},"DROP SCHEMA","\" — frase que satisface al auditor sin dolor. Derecho al olvido es prácticamente trivial en ese modelo.",[12,19004,19005,19008],{},[27,19006,19007],{},"App-per-tenant:"," separación física es demostrable de forma directa. Auditoría queda más simple aún. Derecho al olvido es el destruir de la base del cliente.",[12,19010,19011],{},"En todos los modelos: log de acceso a datos personales (artículo 16, requisito de almacenamiento) es responsabilidad de la capa de aplicación — independe del modelo de aislamiento. Construye ese log desde temprano.",[19,19013,3226],{"id":3225},[12,19015,19016,19019],{},[27,19017,19018],{},"¿Postgres RLS es confiable en producción?","\nSí, y ampliamente usado. Las trampas son dos: garantizar que todas las roles que conectan a la base sean no privilegiadas (super-user ignora RLS), y probar políticas con pruebas automatizadas que corren en CI. Quien configura RLS una vez y no prueba, descubre agujeros después.",[12,19021,19022,19025,19026,19029],{},[27,19023,19024],{},"¿Cómo automatizar migrations en schema-per-tenant?","\nPatrón común: tabla ",[231,19027,19028],{},"tenant_metadata"," con lista de schemas y versión actual de cada uno. Job de migration consulta, aplica en paralelo (con límite de concurrencia para no saturar la base), actualiza versión. Herramientas como Flyway y migrate con wrapper customizado funcionan. Reserva ventana de mantenimiento para migrations grandes incluso con paralelismo.",[12,19031,19032,19035],{},[27,19033,19034],{},"¿App-per-tenant no se vuelve demasiado caro para escalar?","\nSe vuelve, si el ticket promedio es bajo. La regla práctica: ARR de R$ 10 mil\u002Fmes por cliente sostiene confortablemente el costo de infra dedicada. Por debajo de eso, el margen aprieta. Para clientes pequeños, mantén pool o schema. App-per-tenant es arma para clientes que pagan por la exclusividad.",[12,19037,19038,19041],{},[27,19039,19040],{},"¿Puedo mezclar modelos (high-value app-per-tenant, resto pool)?","\nSí, y híbrido es el estado final más común en SaaS maduro. La complejidad operacional aumenta — operas dos arquitecturas, no una — pero la economía compensa cuando los clientes high-value justifican el esfuerzo. Exige equipo con madurez de al menos seis a diez ingenieros.",[12,19043,19044,19050,19051,19053,19054,19057],{},[27,19045,19046,19047,19049],{},"¿",[231,19048,18390],{}," en el path o subdominio?","\nSubdominio (",[231,19052,18624],{},") suele ser mejor para branding y para cookies aisladas. Path (",[231,19055,19056],{},"app.com\u002Facme",") es más simple en DNS y ruteo. Subdominio combina mejor con app-per-tenant; path combina bien con pool. Elige temprano, porque cambiar después rompe integraciones de cliente.",[12,19059,19060,19063],{},[27,19061,19062],{},"¿Encryption per tenant es viable?","\nEn pool, clave por tenant en la capa de aplicación es el camino — overhead razonable, y quedas con claves derivadas de una clave maestra protegida. En schema-per-tenant, misma estrategia. En app-per-tenant, encryption-at-rest de la base ya da aislamiento natural. Encryption per tenant es caro y raramente exigido — solo ve para allá si el cliente lo pide explícitamente en contrato.",[12,19065,19066,19069],{},[27,19067,19068],{},"¿Cuánto tiempo lleva onboarding en cada modelo?","\nPool: treinta a doscientos milisegundos (una transacción en la base). Schema-per-tenant: dos a treinta segundos (CREATE SCHEMA + migrations). App-per-tenant: treinta segundos a tres minutos (provisionar instancias, subir base, registrar TLS). Ese tiempo entra en el flujo de UX de signup — modelos self-service de tarjeta de crédito no soportan tiempo de minutos sin alguna forma de cola o notificación asíncrona.",[19,19071,3310],{"id":3309},[12,19073,19074],{},"La elección de patrón multi-tenant no es técnicamente difícil — es organizacionalmente difícil. Difícil porque exige anticipar tres a cinco años de crecimiento de producto y clientela, y casi nadie anticipa bien. La defensa no es elegir perfecto; es elegir conscientemente, con trilla de migración mapeada para la próxima etapa, e instrumentación que avise cuando el modelo actual está pidiendo jubilación.",[12,19076,19077],{},"Pool es correcto al inicio. Schema-per-tenant es correcto en la transición a mid-market. App-per-tenant es correcto cuando el cliente paga por la exclusividad o cuando el compliance lo exige. Híbrido es el destino común.",[12,19079,19080],{},"Si estás construyendo SaaS B2B brasileño en 2026 y el producto está llegando a la etapa en que multi-tenancy importa, vale la pena conocer un orquestador que vuelve app-per-tenant operacionalmente accesible para equipos pequeños:",[224,19082,19084],{"className":19083,"code":5318,"language":2530},[2528],[231,19085,5318],{"__ignoreMap":229},[12,19087,19088],{},"Cuatro servidores, cinco vCPUs, diez gigabytes de RAM — el cluster público de demostración corre en recursos que caben en cualquier plan de cloud regional. Elección de coordinador en cerca de siete segundos cuando algo cae. Ruteo y TLS embebidos. Es la fundación que falta para mucha arquitectura de tenant aislado en equipo pequeño.",[12,19090,19091,19092,2403,19094,101],{},"Para más sobre infra de SaaS, ve ",[3337,19093,18353],{"href":7466},[3337,19095,6338],{"href":6337},{"title":229,"searchDepth":244,"depth":244,"links":19097},[19098,19099,19100,19101,19102,19103,19104,19105,19106,19107,19108],{"id":18397,"depth":244,"text":18398},{"id":18435,"depth":244,"text":18436},{"id":18527,"depth":244,"text":18528},{"id":18617,"depth":244,"text":18618},{"id":17388,"depth":244,"text":17389},{"id":18865,"depth":244,"text":18866},{"id":18899,"depth":244,"text":18900},{"id":18942,"depth":244,"text":18943},{"id":18982,"depth":244,"text":18983},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"2026-04-01","Pool, schema-per-tenant, app-per-tenant. Cada patrón tiene beneficios obvios y costos invisibles. Cómo decidir antes del primer cliente B2B serio preguntando 'mis datos están aislados?'.",{},{"title":18382,"description":19110},{"loc":4369},"es\u002Fblog\u002Fmulti-tenant-saas-aislamiento-real",[19116,15815,19117,3379,4410],"multi-tenancy","aislamiento","QH_K4j_TM3sS-gzESZCGDOkrC1ykAvn_8vFKnYmn2Os",{"id":19120,"title":19121,"author":7,"body":19122,"category":6382,"cover":3380,"date":19797,"description":19798,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":19799,"navigation":411,"path":19800,"readingTime":4402,"seo":19801,"sitemap":19802,"stem":19803,"tags":19804,"__hash__":19809},"blog_es\u002Fes\u002Fblog\u002Fstrapi-directus-ghost-auto-hospedado-guia.md","Strapi, Directus y Ghost auto-hospedados: guía honesta para agencias e indie hackers",{"type":9,"value":19123,"toc":19782},[19124,19127,19130,19133,19136,19140,19143,19149,19155,19165,19171,19177,19181,19184,19187,19190,19193,19196,19199,19203,19206,19209,19212,19215,19218,19221,19225,19228,19231,19234,19237,19240,19243,19245,19248,19451,19454,19458,19461,19484,19513,19539,19543,19546,19552,19558,19564,19570,19574,19577,19583,19589,19595,19598,19602,19605,19611,19617,19623,19629,19635,19639,19645,19651,19657,19663,19669,19673,19676,19682,19688,19694,19699,19705,19708,19710,19716,19722,19728,19734,19740,19746,19752,19754,19757,19760,19763,19768,19779],[12,19125,19126],{},"Toda agencia que aloja sitio de cliente conoce el dilema. Tienes treinta cuentas activas, cada una con un Wordpress en Wordpress.com Business costando entre US$25 y US$45 al mes — cuando el cliente no exige Wordpress.com VIP, que sube a tres cifras. Suma eso, multiplica por treinta, divide por el dólar del mes, y el margen desaparece. La alternativa más antigua es alquilar un alojamiento compartido barato y apilar treinta sitios en un servidor PHP que cae junto en el primer martes del mes — reputación quemada por economía de quinientos reales.",[12,19128,19129],{},"Hay un camino del medio que se volvió viable los últimos dos años: sustituir el monolito de PHP por un CMS moderno auto-hospedado. Strapi, Directus y Ghost son los tres que más aparecen en proyectos de agencia y en SaaS indie. Cada uno resuelve un problema distinto, cada uno tiene trampa propia, y la documentación oficial de cada uno vende el producto en lugar de comparar honestamente. Este post es la comparación que faltaba.",[12,19131,19132],{},"La audiencia aquí es doble. Por un lado, la agencia de cinco a veinte personas que entrega sitio o plataforma editorial al cliente — ese perfil necesita decidir entre cloud gestionado y auto-alojamiento con base en coste por cliente, no en hype técnico. Por el otro, el desarrollador solo o indie hacker que está eligiendo el stack del propio proyecto y quiere saber cuál CMS escala mejor sin volverse dolor de cabeza los sábados.",[12,19134,19135],{},"Los números son el esqueleto del post. Costes en dólares fueron convertidos a real usando el rango actual de R$5,00 a R$5,30 por dólar — donde el intervalo importa, está marcado. Requisitos de RAM y CPU fueron colectados de las documentaciones oficiales y validados en VPS de test corriendo workload sintético. Si algún número parece optimista, es porque es el piso — producción real suele pedir 30 a 50 por ciento más.",[19,19137,19139],{"id":19138},"por-que-cms-auto-hospedado-se-volvio-viable-en-2026","Por qué CMS auto-hospedado se volvió viable en 2026",[12,19141,19142],{},"Cinco factores combinados destrabaron el escenario. Ninguno de ellos es nuevo aisladamente; lo que cambió es que todos maduraron al mismo tiempo.",[12,19144,19145,19148],{},[27,19146,19147],{},"El coste de máquina virtual cayó cerca del absurdo."," Hetzner, DigitalOcean, OVH e incluso proveedores nacionales como Magalu Cloud y UOL Host venden VPS de 2 vCPU y 4 GB de RAM por menos de R$60 al mes. Hace cinco años, la misma capacidad costaba el triple. Para agencia que históricamente terciarizaba infra a revendedores de hospedaje, ahora tiene más sentido alquilar una máquina dedicada y apilar workloads allí.",[12,19150,19151,19154],{},[27,19152,19153],{},"Paneles de orquestación auto-hospedados cubren lo que faltaba en ops."," Coolify, Dokploy, CapRover y el propio HeroCtl entregan lo que era exclusividad de proveedores caros: deploy a partir de un archivo de configuración, certificado TLS automático, rollback de una versión a otra, métricas básicas. La barrera para correr un Strapi en producción cayó de \"una semana de provisionamiento manual\" a \"cinco minutos después de que el servidor esté de pie\".",[12,19156,19157,19160,19161,19164],{},[27,19158,19159],{},"Los CMS modernos publican imágenes Docker oficiales y maduras."," Hace tres años necesitabas montar Dockerfile propio para Strapi en producción; hoy el equipo oficial publica imagen testeada con receta de docker-compose de referencia. Incluso para Ghost, que históricamente tenía empaquetamiento propio, la imagen ",[231,19162,19163],{},"ghost:5-alpine"," es la forma recomendada por el equipo oficial.",[12,19166,19167,19170],{},[27,19168,19169],{},"Las comunidades dejaron de ser invisibles."," El canal Strapi BR en Discord tiene miles de miembros activos, el foro oficial de Directus responde en inglés pero con alta participación de devs locales, y la documentación de Ghost fue traducida en piezas por contribuidores locales. No es la comunidad WordPress (que es gigante y llena de tutorial), pero es lo suficiente para desbloquear la mayoría de los problemas sin tener que descifrar inglés técnico al cuarto error consecutivo.",[12,19172,19173,19176],{},[27,19174,19175],{},"Wordpress.com aumentó precio de forma agresiva."," Quien acompañó a Heroku volverse de pago en 2022 reconoce el patrón: servicio gratuito o barato se vuelve premium, plan antiguo es descontinuado, cuenta legacy migra o paga más. Wordpress.com hizo el equivalente los últimos dos años — el tier \"Personal\" subió, el tier \"Premium\" subió más, y features que antes venían en el plan medio ahora exigen el tier Business o superior. Cada aumento es un empujón más hacia el auto-alojamiento.",[19,19178,19180],{"id":19179},"strapi-el-cms-api-first","Strapi — el CMS API-first",[12,19182,19183],{},"Strapi es el que más se parece a \"Wordpress moderno para dev\". Defines el tipo de contenido en la interfaz administrativa (post, autor, categoría, producto, cualquier cosa), y Strapi genera automáticamente una API REST y una API GraphQL para leer y escribir ese contenido. No hay frontend en él — es puro backend headless. El frontend es responsabilidad tuya, generalmente un Next.js, Nuxt o Astro consumiendo la API.",[12,19185,19186],{},"El stack es Node.js en el backend, base Postgres o MySQL para persistencia, y un panel administrativo en React que viene embebido. El panel es el punto fuerte del producto: editor no técnico consigue crear contenido sin entrenamiento, organizar media, agendar publicación, gestionar usuarios. Para agencia, eso es venta fácil — el cliente entra en el admin y reconoce el paradigma \"Wordpress pero más limpio\".",[12,19188,19189],{},"El requisito mínimo realista en producción es 2 vCPU, 2 GB de RAM y 10 GB de almacenamiento. La documentación oficial habla en 1 GB, pero con cualquier plugin activo y tráfico más allá de test local, la memoria revienta. En VPS de R$50 a R$80 al mes corres cómodo; en VPS de R$30 (1 GB de RAM) el proceso muere cada vez que un upload de media mayor sucede.",[12,19191,19192],{},"Los puntos fuertes son consistentes. Plugin ecosystem rico — autenticación social, internacionalización, integración con S3 para media, generador de sitemap, todo ya existe. GraphQL nativo sin configuración extra, lo que cierra bien con frontend moderno. Hooks personalizados (lifecycle hooks, middlewares, policies) resuelven regla de negocio sin necesidad de microservicio separado. La interfaz administrativa es genuinamente buena — comparada con Drupal o Wordpress sin plugin de admin, es otro nivel.",[12,19194,19195],{},"Los puntos débiles también son consistentes, y cabe hablar en voz alta. La transición entre versiones majores suele romper — la migración de v4 a v5 fue notoria, con cambios de API incompatibles y necesidad de reescribir plugins personalizados. Si adoptas Strapi para un proyecto de largo plazo, reserva una ventana de upgrade cada doce o dieciocho meses como coste recurrente, no como sorpresa. Migraciones de schema también exigen disciplina — añadir campo es fácil, renombrar o tipar diferente sin perder dato pide script de migración escrito a mano. Y algunas features que aparecen en el marketing solo corren en Strapi Cloud (la versión paga de ellos), como preview en vivo entre ambientes — auto-alojando no tienes eso listo.",[12,19197,19198],{},"Cuándo tiene sentido elegir Strapi: SaaS que necesita blog propio y knowledge base en el mismo CMS, agencia que entrega para cliente acostumbrado con \"Wordpress pero sin PHP\", proyecto headless commerce donde los SKUs son modelados como tipo de contenido, y cualquier escenario en que tener GraphQL listo ahorra días de trabajo.",[19,19200,19202],{"id":19201},"directus-el-cms-para-datos-existentes","Directus — el CMS para datos existentes",[12,19204,19205],{},"Directus es una criatura distinta. En lugar de forzarte a crear tipo de contenido desde cero dentro de él, coloca una interfaz administrativa encima de cualquier base que ya tengas. Apuntarías a un Postgres legacy con veinte tablas existentes, y Directus muestra cada tabla como una colección editable, respetando los tipos de columna, las claves foráneas e incluso las constraints. Es la herramienta que más se aproxima a \"admin universal para cualquier base SQL\".",[12,19207,19208],{},"El stack es Node.js en el backend, soporte oficial a Postgres, MySQL, MariaDB, SQLite, Oracle y SQL Server, y un panel administrativo en Vue. El soporte a base es deliberadamente amplio — el producto fue diseñado para adaptar, no para imponer schema propio. Puedes usar Directus contra una base ceroada y dejar que cree las tablas vía interfaz, o apuntar a una base con diez años de historia y esperar que todo aparezca organizado en el admin.",[12,19210,19211],{},"El requisito mínimo es más ligero que Strapi. 1 vCPU, 1 GB de RAM y 5 GB de almacenamiento corren cómodo para workload pequeño y medio. En VPS de R$30 a R$50 al mes consigues subir un Directus sirviendo decenas de colecciones con tráfico moderado. Para proyectos menores, SQLite como base es suficiente — cabe en un único archivo, simplifica backup, evita tener un Postgres separado para gestionar.",[12,19213,19214],{},"Los puntos fuertes salen del diseño. La capacidad de adoptar base existente sin reformar schema es genuinamente única — ningún CMS popular hace eso tan bien. Real-time updates vía WebSockets vienen listos, lo que abre puerta a dashboards y herramientas internas que reaccionan a cambio en tiempo real sin necesidad de una capa adicional. Permisos granulares por colección, por campo e incluso por línea (con base en condición) cubren escenarios de multi-tenancy sin hack. La documentación es decente, mantenida activa, y el equipo responde duda en foro en plazos razonables.",[12,19216,19217],{},"Los puntos débiles: la curva de aprendizaje para customizaciones avanzadas (extensions, hooks personalizados, panels de dashboard) es más empinada que Strapi. El ecosistema de plugins es menor — donde Strapi tiene diez plugins de SEO, Directus tiene dos o tres. Y para editor no técnico, la interfaz es menos amigable que la de Strapi — Directus prioriza poder y flexibilidad, no onboarding suave.",[12,19219,19220],{},"Cuándo tiene sentido elegir Directus: agencia que tomó cliente con base MySQL legacy de diez años y necesita entregar panel administrativo sin rehacer schema, herramienta interna donde el modelado es dirigido por los datos (CRM custom, gestión de stock, plataforma de operaciones), aplicación cuya entidad central es \"dato relacional\", no \"documento editorial\". También es la elección obvia cuando el cliente ya tiene Postgres o MySQL corriendo otro sistema y quiere aprovechar.",[19,19222,19224],{"id":19223},"ghost-el-cms-de-publicacion","Ghost — el CMS de publicación",[12,19226,19227],{},"Ghost es el opuesto de la neutralidad. No pretende ser CMS universal — es blog y plataforma de newsletter, especializado en contenido editorial. Quien intenta usar Ghost para producto de e-commerce o app SaaS está usando herramienta errada. Quien usa para blog corporativo, sitio de mídia, podcast con membership o newsletter paga, encuentra un producto pulido y enfocado.",[12,19229,19230],{},"El stack es Node.js en el backend, base MySQL o SQLite (Postgres no es oficialmente soportado), y frontend en Handlebars con tema. El frontend es parte del paquete — Ghost sirve las páginas directamente, con tema instalado vía upload. Hay modo headless (usas solo la Content API y montas el frontend separado), pero el caso común es Ghost sirviendo todo.",[12,19232,19233],{},"El requisito mínimo es el más ligero de los tres. 1 vCPU, 1 GB de RAM y 5 GB de almacenamiento corren Ghost con holgura para blog de tráfico medio. En VPS de R$30 se puede correr — con el cuidado de configurar SMTP externo para newsletter (mandar email a partir del propio servidor es receta para caer en spam).",[12,19235,19236],{},"Los puntos fuertes son afilados. SEO out-of-the-box es el mejor entre los tres — meta tags, sitemap, schema.org, AMP (cuando tiene sentido), todo configurado por defecto. Sistema de membership y paywall viene nativo: creas niveles de suscripción, cobras vía Stripe, liberas contenido pago automáticamente. El editor markdown es genuinamente bueno, con cards (llamadas, callouts, código) que cubren el caso común sin volverse editor de Word. Los temas se enfocan en legibilidad y tipografía editorial — nada de la estética genérica de tema Wordpress.",[12,19238,19239],{},"Los puntos débiles salen de la especialización. Plugin ecosystem es cerrado por diseño — apps de integración existen en Ghost.org como producto pago, e instalar app personalizado es más difícil que en Strapi o Directus. No-blog es territorio hostil — intentar modelar producto, autor con perfil rico, taxonomía compleja choca con decisiones de diseño que priorizan el caso \"post + autor + tag\". Y soporte oficial a Postgres no existe — si tienes patrón de empresa en Postgres, vas a operar MySQL paralelo solo para Ghost.",[12,19241,19242],{},"Cuándo tiene sentido elegir Ghost: blog corporativo con paywall o contenido premium, sitio de mídia o periodismo independiente, podcast que quiere monetizar vía membership, content marketing tomado en serio con editor que va a usar el admin todos los días. Para cualquier cosa fuera de ese alcance, es forzar la barra.",[19,19244,17389],{"id":17388},[12,19246,19247],{},"Los tres CMS modernos lado a lado con Wordpress (la referencia heredada) y Payload (competidor reciente que vale mencionar):",[119,19249,19250,19271],{},[122,19251,19252],{},[125,19253,19254,19256,19259,19262,19265,19268],{},[128,19255,2983],{},[128,19257,19258],{},"Strapi",[128,19260,19261],{},"Directus",[128,19263,19264],{},"Ghost",[128,19266,19267],{},"Wordpress",[128,19269,19270],{},"Payload",[141,19272,19273,19289,19306,19324,19341,19359,19378,19396,19414,19431],{},[125,19274,19275,19278,19281,19283,19285,19287],{},[146,19276,19277],{},"RAM mínima realista",[146,19279,19280],{},"2 GB",[146,19282,11500],{},[146,19284,11500],{},[146,19286,11500],{},[146,19288,19280],{},[125,19290,19291,19293,19296,19298,19301,19304],{},[146,19292,16321],{},[146,19294,19295],{},"30–60 min",[146,19297,19295],{},[146,19299,19300],{},"15–30 min",[146,19302,19303],{},"10–20 min",[146,19305,19295],{},[125,19307,19308,19311,19314,19316,19319,19322],{},[146,19309,19310],{},"Modo headless",[146,19312,19313],{},"Sí, default",[146,19315,19313],{},[146,19317,19318],{},"Opcional",[146,19320,19321],{},"Opcional (REST + GraphQL)",[146,19323,19313],{},[125,19325,19326,19329,19331,19333,19336,19339],{},[146,19327,19328],{},"GraphQL nativo",[146,19330,3065],{},[146,19332,3065],{},[146,19334,19335],{},"No (REST)",[146,19337,19338],{},"Plugin externo",[146,19340,3065],{},[125,19342,19343,19346,19349,19352,19355,19357],{},[146,19344,19345],{},"Multi-tenancy fácil",[146,19347,19348],{},"Medio",[146,19350,19351],{},"Bueno",[146,19353,19354],{},"Difícil",[146,19356,19338],{},[146,19358,19351],{},[125,19360,19361,19364,19367,19369,19372,19375],{},[146,19362,19363],{},"Membership \u002F paywall",[146,19365,19366],{},"Plugin",[146,19368,19366],{},[146,19370,19371],{},"Nativo",[146,19373,19374],{},"Plugin pago",[146,19376,19377],{},"Personalizado",[125,19379,19380,19383,19386,19388,19391,19394],{},[146,19381,19382],{},"Plugin ecosystem",[146,19384,19385],{},"Rico",[146,19387,19348],{},[146,19389,19390],{},"Débil",[146,19392,19393],{},"Riquísimo",[146,19395,14480],{},[125,19397,19398,19401,19403,19406,19409,19411],{},[146,19399,19400],{},"Coste Cloud (USD\u002Fmes inicial)",[146,19402,5576],{},[146,19404,19405],{},"25",[146,19407,19408],{},"11",[146,19410,19405],{},[146,19412,19413],{},"35",[125,19415,19416,19419,19421,19423,19425,19428],{},[146,19417,19418],{},"Documentación local",[146,19420,3140],{},[146,19422,4890],{},[146,19424,4890],{},[146,19426,19427],{},"Riquísima",[146,19429,19430],{},"Inglés",[125,19432,19433,19436,19439,19442,19445,19448],{},[146,19434,19435],{},"Rango ideal de uso",[146,19437,19438],{},"API + admin",[146,19440,19441],{},"Admin sobre dato",[146,19443,19444],{},"Contenido editorial",[146,19446,19447],{},"Sitio genérico",[146,19449,19450],{},"App custom Node.js",[12,19452,19453],{},"La columna \"tiempo hasta primer deploy\" asume servidor ya provisionado y Docker instalado. La columna \"coste Cloud\" es el tier de entrada del producto — escala de precio sube conforme límites de tráfico, miembros o seats en el admin. La columna \"documentación local\" refleja lo que existe oficial más lo que la comunidad mantiene activa; ninguno de los tres tiene manual completo traducido, pero Strapi tiene el mejor camino de aprendizaje en portugués.",[19,19455,19457],{"id":19456},"setup-auto-hospedado-en-alto-nivel","Setup auto-hospedado en alto nivel",[12,19459,19460],{},"La receta no es copy-paste — es la hoja de ruta mental de lo que va a ser preciso. Detalles específicos cambian por VPS y por elección de orquestador.",[12,19462,19463,19464,19466,19467,19470,19471,571,19474,571,19477,571,19480,19483],{},"Para ",[27,19465,19258],{},", el setup mínimamente serio es docker-compose con tres servicios: Strapi, Postgres y Redis (Redis es opcional, pero acelera el admin notablemente cuando hay más de cinco editores). Volumen nombrado para ",[231,19468,19469],{},"\u002Fsrv\u002Fstrapi\u002Fuploads"," (media) y para datos de Postgres. Panel sube en el puerto 1337 internamente, expuesto vía subdominio con TLS por el router del orquestador. Variables de entorno críticas: ",[231,19472,19473],{},"APP_KEYS",[231,19475,19476],{},"JWT_SECRET",[231,19478,19479],{},"ADMIN_JWT_SECRET",[231,19481,19482],{},"DATABASE_*",". Olvidar cualquiera de esas hace que el admin no suba o pierda sesión a cada restart.",[12,19485,19463,19486,19488,19489,571,19492,571,19495,571,19498,571,19501,19504,19505,19508,19509,19512],{},[27,19487,19261],{},", el setup es parecido pero más ligero. Docker-compose con Directus y base (SQLite cabe en un volumen solo, Postgres si la expectativa es multi-usuario con escritura concurrente). Sin Redis necesario para empezar. Panel en el puerto 8055. Variables críticas: ",[231,19490,19491],{},"KEY",[231,19493,19494],{},"SECRET",[231,19496,19497],{},"ADMIN_EMAIL",[231,19499,19500],{},"ADMIN_PASSWORD",[231,19502,19503],{},"DB_*",". Punto de atención: si apuntas Directus a base existente con schema rico, abre el admin con calma y configura los permisos antes de dar acceso a cualquier otro usuario — por defecto el role ",[231,19506,19507],{},"admin"," ve todo y el role ",[231,19510,19511],{},"public"," ve nada, lo que es razonable; pero si creas role intermedio sin cuidado, expones colecciones enteras sin querer.",[12,19514,19463,19515,19517,19518,19521,19522,19524,19525,571,19528,19531,19532,19534,19535,19538],{},[27,19516,19264],{},", docker-compose con Ghost y MySQL. SQLite sirve para desarrollo pero es desalentado en producción por el equipo oficial. Volumen nombrado para ",[231,19519,19520],{},"\u002Fvar\u002Flib\u002Fghost\u002Fcontent"," (temas, media, configs) y para MySQL. Configurar SMTP externo es etapa obligatoria — Mailgun, Postmark y Resend tienen tier gratuito o barato, cualquiera de ellos sirve. Sin SMTP, recuperación de contraseña no funciona, newsletter no envía, signup de miembro queda roto. Variables críticas: ",[231,19523,10250],{}," (dominio público con https), ",[231,19526,19527],{},"database__connection__*",[231,19529,19530],{},"mail__*",". Error común: configurar ",[231,19533,10250],{}," como ",[231,19536,19537],{},"http:\u002F\u002Flocalhost"," en producción y descubrir solo después que todos los enlaces de email salieron rotos.",[19,19540,19542],{"id":19541},"costes-comparados","Costes comparados",[12,19544,19545],{},"La planilla honesta de cloud gestionado contra auto-hospedado, en moneda corriente (R$5,00 por dólar como referencia):",[12,19547,19548,19551],{},[27,19549,19550],{},"Strapi Cloud"," empieza en US$15 al mes en el tier Developer (R$75), sube a US$99 al mes en el tier Pro (R$495) con features como ambientes separados de staging y producción, más seats en el admin y soporte. Auto-hospedado en VPS de R$50 a R$80 al mes corre Strapi con holgura para workload pequeño y medio. Diferencia mensual: de R$25 a R$445 dependiendo del tier que compararías. Para agencia con cinco clientes en Strapi, eso se traduce en economía anual entre R$1.500 y R$26.700.",[12,19553,19554,19557],{},[27,19555,19556],{},"Directus Cloud"," empieza en US$25 al mes en el tier Standard (R$125), sube a US$99 al mes en el tier Pro (R$495) y tiene tier Enterprise con precio bajo consulta. Auto-hospedado en VPS de R$50 al mes cubre el caso común. Diferencia similar a la de Strapi — entre R$75 y R$445 al mes por instancia.",[12,19559,19560,19563],{},[27,19561,19562],{},"Ghost Pro"," empieza en US$11 al mes en el tier Starter (R$55) con hasta 500 miembros y un único staff seat, escala a US$31 (R$155) con 1.000 miembros, y alcanza US$249 al mes (R$1.245) en el tier que soporta 50 mil miembros. Auto-hospedado en VPS de R$50 a R$80 al mes no tiene techo de miembros — puedes tener 50 mil o 500 mil sin cambiar el servidor (la única cosa que cambia es el volumen de email transaccional, que escala separado). Para publicación que crece en audiencia, la economía anual auto-hospedando Ghost pasa de R$10 mil rápidamente.",[12,19565,19566,19569],{},[27,19567,19568],{},"Wordpress.com Business"," cuesta US$25 al mes (R$125), VIP queda en tres cifras. Comparar con auto-alojamiento de Wordpress en una VPS de R$50 es meh — Wordpress es pesado por naturaleza, exige más cuidado de seguridad y backup, y el ecosistema de plugin es fuente recurrente de incidente de producción. Para proyecto nuevo en 2026, es más sensato elegir entre Strapi, Directus o Ghost que heredar la complejidad del PHP.",[19,19571,19573],{"id":19572},"estrategia-para-agencia-alojando-treinta-clientes","Estrategia para agencia alojando treinta clientes",[12,19575,19576],{},"Tres opciones con tradeoffs claros.",[12,19578,19579,19582],{},[27,19580,19581],{},"Opción A — un VPS por cliente."," Aislamiento total: si un cliente tira el servidor de él, los otros veintinueve no sienten. Coste directo: 30 VPS × R$30 a R$50 = R$900 a R$1.500 al mes solo de infra. Coste operacional: treinta veces todo — treinta actualizaciones de SO, treinta certificados para monitorear, treinta backups para orquestar. Para agencia con más de diez clientes, la sobrecarga operacional come el margen que la opción tenía en primer lugar.",[12,19584,19585,19588],{},[27,19586,19587],{},"Opción B — un cluster compartido corriendo treinta instancias de los CMS."," Cuatro servidores totalizando 5 vCPU y 10 GB de RAM (la configuración que corremos en producción aquí en HeroCtl) alojan cómodamente treinta instancias de Strapi\u002FDirectus\u002FGhost con tráfico típico de cliente PYME. Coste de infra: cerca de R$300 a R$400 al mes por el cluster entero. Coste operacional: una estrategia única de monitoreo, una estrategia única de backup, un lugar para mirar cuando algo pesa el sistema. Margen de la agencia aumenta porque el punto donde cobras es el mismo y el punto donde gastas cayó.",[12,19590,19591,19594],{},[27,19592,19593],{},"Opción C — cluster compartido con cada cliente en subdominio propio."," Variación de la opción B, pero con enrutamiento explícito por subdominio (cliente1.tuagencia.com, cliente2.tuagencia.com) o dominio propio del cliente (tienda-del-cliente.com). El router integrado del orquestador resuelve la parte de TLS automático y direccionamiento de tráfico. Multi-tenancy queda en el nivel de DNS + container, no en el nivel del CMS — cada cliente tiene instancia aislada de Strapi\u002FDirectus\u002FGhost con base propia. Para agencia que vende \"sitio exclusivo\" como diferencial, es la forma de mantener la promesa sin multiplicar VPS.",[12,19596,19597],{},"La opción B con elementos de la C es lo que tiene más sentido para agencia típica. Cluster compartido, instancias aisladas, subdominio o dominio propio por cliente, backup centralizado.",[19,19599,19601],{"id":19600},"backup-y-migracion-entre-cms","Backup y migración entre CMS",[12,19603,19604],{},"Migración entre CMS es territorio donde proveedores omiten detalle deliberadamente. La verdad práctica:",[12,19606,19607,19610],{},[27,19608,19609],{},"Strapi a Strapi"," (entre versiones o entre instancias) tiene export e import vía plugin oficial, genera archivo JSON con schema y datos. Funciona bien para migración entre staging y producción; entre versiones majores, puede pedir ajuste manual en el JSON antes del import.",[12,19612,19613,19616],{},[27,19614,19615],{},"Strapi a Directus"," no tiene herramienta lista. Schema es distinto lo suficiente para exigir mapping manual — script en Node leyendo la API REST de Strapi y escribiendo en la API REST de Directus, ítem por ítem. Para base de mil o diez mil registros es trabajo de una tarde; para base mayor, vale paralelizar.",[12,19618,19619,19622],{},[27,19620,19621],{},"Wordpress a Strapi"," tiene herramientas third-party (wp2strapi y variantes), todas parciales. Lo que migra bien es post + autor + categoría + media. Lo que no migra bien es cualquier custom post type complejo, plugin de SEO con metadatos propios, o estructura de menú. Reserva un a tres días por sitio en la migración y revisa media manualmente.",[12,19624,19625,19628],{},[27,19626,19627],{},"Ghost a Ghost"," tiene export e import nativo en el admin — genera JSON con posts, autores, configuraciones de sitio, miembros. Funciona limpio entre instancias y entre versiones.",[12,19630,19631,19634],{},[27,19632,19633],{},"Backup de la base"," es la etapa no-negociable. Pg_dump (Postgres) o mysqldump (MySQL) diario, copiado a storage objeto fuera del servidor (S3, Backblaze B2, Wasabi). Sin eso, cualquier incidente — disco corrupto, rm accidental, hack — se vuelve evento de extinción para datos del cliente. Coste de S3 con versionado para un cluster pequeño queda debajo de R$50 al mes incluso guardando treinta días de retención.",[19,19636,19638],{"id":19637},"cinco-errores-que-matan-cms-auto-hospedado","Cinco errores que matan CMS auto-hospedado",[12,19640,19641,19644],{},[27,19642,19643],{},"No actualizar."," CMS desactualizado es vulnerabilidad abierta. Cron de update mensual es el piso — calendario fijo, ventana de mantenimiento combinada con cliente, test de smoke después. No hacer eso significa que antes o después alguien abre el admin del cliente sin credencial.",[12,19646,19647,19650],{},[27,19648,19649],{},"Contraseña admin débil."," Admin\u002Fadmin en producción sigue pasando en 2026. Contraseña fuerte generada por gestor de contraseña, autenticación de dos factores cuando el CMS soporta, role separado para editor (el cliente no recibe contraseña de admin total).",[12,19652,19653,19656],{},[27,19654,19655],{},"Sin backup automático."," Cliente ve seis meses de contenido desaparecer y la relación termina. Backup de la base diario, retenido por treinta días mínimo, copiado a storage fuera del servidor que aloja el CMS. Testar restore al menos una vez por trimestre — backup que nunca fue restaurado es teoría, no backup.",[12,19658,19659,19662],{},[27,19660,19661],{},"Storage de media local sin CDN."," Imágenes grandes en VPS pequeña tiran el servidor cuando una página se viraliza. Configurar storage objeto (S3, R2, Spaces) para media desde el día uno, incluso que el tráfico sea bajo al inicio. Strapi y Directus tienen proveedores oficiales para eso; Ghost soporta vía configuración.",[12,19664,19665,19668],{},[27,19666,19667],{},"Email transaccional no testado."," Strapi y Directus necesitan SMTP configurado para password reset funcionar. Ghost depende de SMTP para newsletter entera. Configurar y testar en el día del deploy — mandar email de test para ti mismo, comprobar bandeja de entrada y carpeta de spam, ajustar SPF\u002FDKIM si cae en spam. Sin eso, el cliente descubre que el sitio se rompió en el día en que necesite cambiar la propia contraseña.",[19,19670,19672],{"id":19671},"heroctl-como-infra-de-agencia","HeroCtl como infra de agencia",[12,19674,19675],{},"La última parte de la guía es honesta sobre cómo HeroCtl encaja en ese escenario. No pretendemos ser la única opción — Coolify, Dokploy y CapRover cubren casos parecidos con tradeoffs distintos. Lo que HeroCtl trae a la agencia alojando CMS es:",[12,19677,19678,19681],{},[27,19679,19680],{},"Templates de job para subir CMS nuevo en segundos."," En lugar de escribir docker-compose desde cero para cada cliente, guardas un archivo de configuración de cincuenta líneas con Strapi + Postgres ya parametrizado, cambias el dominio y el nombre de la base, y envías. Cliente nuevo entra en producción en menos tiempo de lo que tarda en hacer café.",[12,19683,19684,19687],{},[27,19685,19686],{},"Enrutamiento por subdominio con TLS automático."," Cada cliente en subdominio propio (o dominio propio con DNS apuntando) recibe certificado Let's Encrypt sin intervención. Renovación pasa sola. No tocas en archivo de configuración de servidor web — el router integrado lidia con eso.",[12,19689,19690,19693],{},[27,19691,19692],{},"Métricas por job."," Qué cliente está pesando el cluster queda visible en el panel — CPU, memoria, requests por segundo, latencia. Cuando un cliente pasa del volumen contratado, lo ves antes de que el cluster sienta.",[12,19695,19696,19698],{},[27,19697,13658],{}," (en el plan Business) cubre todos los clientes de una vez. En lugar de configurar treinta scripts de pg_dump separados, es una política central con retención configurable.",[12,19700,19701,19704],{},[27,19702,19703],{},"Auditoría detallada"," (en el plan Business) cubre exigencia de LGPD para cliente que necesita demostrar quién accedió a qué y cuándo. Para agencia atendiendo cliente en salud, finanzas o educación, deja de ser lujo.",[12,19706,19707],{},"La línea entre lo que viene en el plan Community (gratuito, sin límite de servidores o jobs) y lo que está en el Business está dibujada por el tipo de exigencia que aparece cuando la agencia crece. Para cinco o diez clientes, Community resuelve. Para treinta clientes donde dos de ellos exigen SSO y uno exige reporte de auditoría, el Business se paga él mismo en el primer mes.",[19,19709,7352],{"id":7351},[12,19711,19712,19715],{},[27,19713,19714],{},"Wordpress vs esos tres — ¿cuándo aún Wordpress gana?","\nCuando el cliente tiene equipo interno acostumbrado con Wordpress, cuando el sitio depende de plugin específico que solo existe en Wordpress (algunos plugins de e-commerce hyper-localizados, algunos LMS), y cuando el presupuesto es tan pequeño que entrenar editor en CMS nuevo cuesta más que la economía de hospedaje. Para proyecto nuevo en 2026 sin esas restricciones, raramente.",[12,19717,19718,19721],{},[27,19719,19720],{},"¿Puedo correr Strapi en VPS de R$30?","\nTécnicamente sí, en la práctica es fuente de incidente. 1 GB de RAM es el piso y cualquier pico de tráfico o upload de media mayor tira el proceso. Sube a R$50 a R$80 — la diferencia es menor que un almuerzo, y la estabilidad se vuelve otra cosa.",[12,19723,19724,19727],{},[27,19725,19726],{},"¿Ghost y Strapi en el mismo servidor, ok?","\nEn VPS pequeña (4 GB de RAM o menos) está apretado y sujeto a contención. En servidor de 8 GB o más con docker-compose separando recursos, funciona. En cluster con orquestador, es el caso común — los dos corren en hosts distintos o comparten con aislamiento de proceso.",[12,19729,19730,19733],{},[27,19731,19732],{},"¿Cómo migro Strapi v4 a v5 sin pasar la noche?","\nDocumenta el esquema actual antes de tocar. Sube ambiente de staging con v5 y la misma base copiada. Corre el migrador oficial y verifica todo en el admin. Reescribe plugins personalizados antes de promover a producción — ellos no migran automáticamente. Reserva dos a cuatro días útiles para un Strapi medio. Sin ambiente de staging, no des la vuelta directo en producción.",[12,19735,19736,19739],{},[27,19737,19738],{},"Email transaccional para Ghost newsletter — ¿qué proveedor más barato?","\nMailgun tiene tier gratuito hasta cinco mil emails al mes, después cobra por volumen. Resend tiene tier gratuito hasta tres mil. Postmark es pago desde el primer email pero es el más confiable en entrega. Para newsletter pequeña (hasta dos mil miembros), Mailgun o Resend gratuito resuelve. Por encima, Postmark vale el coste por la tasa de entrega.",[12,19741,19742,19745],{},[27,19743,19744],{},"¿Hay caso de agencia escalando así?","\nHay varias, pero las que hablan en público son minoría. El patrón típico es agencia con diez a treinta clientes, cluster de tres o cuatro servidores en proveedor cloud, instancias separadas por cliente, backup centralizado. Cuando la agencia publica número, suele hablar en economía de cincuenta a setenta por ciento sobre el equivalente en hospedaje gestionado — lo que pega con la aritmética arriba.",[12,19747,19748,19751],{},[27,19749,19750],{},"Media de imágenes grandes — ¿dónde guardar?","\nStorage objeto fuera del servidor que aloja el CMS. AWS S3, Cloudflare R2, Backblaze B2 y DigitalOcean Spaces cubren el caso. R2 y B2 tienen precio mejor que S3 puro para workload de lectura intensiva. Configura desde el día uno, incluso con tráfico bajo — migrar media después es dolor de cabeza que no compensa.",[19,19753,3310],{"id":3309},[12,19755,19756],{},"Los tres CMS modernos cubren tres casos distintos. Strapi para quien quiere admin pulido con API headless y plugin para todo. Directus para quien tiene dato y necesita admin sobre él. Ghost para quien publica contenido editorial y quiere paywall sin hack.",[12,19758,19759],{},"Auto-alojarse se volvió viable porque máquina se volvió barata, orquestador auto-hospedado se volvió bueno, y los tres productos maduraron empaquetamiento para Docker. Para agencia con más de cinco clientes, la economía de cloud para auto-alojamiento en cluster compartido paga una persona del equipo en pocos meses.",[12,19761,19762],{},"Si quieres testar el camino del orquestador sobre cluster propio:",[224,19764,19766],{"className":19765,"code":2949,"language":2530},[2528],[231,19767,2949],{"__ignoreMap":229},[12,19769,19770,19771,19775,19776,19778],{},"Posts relacionados que profundizan puntos específicos: ",[3337,19772,19774],{"href":19773},"\u002Fes\u002Fblog\u002Fheroku-auto-hospedado-2026","Heroku auto-hospedado en 2026"," cubre el panorama más amplio de \"huir del PaaS caro\", y ",[3337,19777,6338],{"href":6337}," trae la planilla completa de infra para producto digital saliendo desde cero.",[12,19780,19781],{},"Sin ceremonia.",{"title":229,"searchDepth":244,"depth":244,"links":19783},[19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,19796],{"id":19138,"depth":244,"text":19139},{"id":19179,"depth":244,"text":19180},{"id":19201,"depth":244,"text":19202},{"id":19223,"depth":244,"text":19224},{"id":17388,"depth":244,"text":17389},{"id":19456,"depth":244,"text":19457},{"id":19541,"depth":244,"text":19542},{"id":19572,"depth":244,"text":19573},{"id":19600,"depth":244,"text":19601},{"id":19637,"depth":244,"text":19638},{"id":19671,"depth":244,"text":19672},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-03-25","Los tres CMS modernos open-source que más se auto-hospedan. Cada uno para un caso. Tabla comparativa, requisitos reales y cuándo vale la pena pagar la versión cloud.",{},"\u002Fes\u002Fblog\u002Fstrapi-directus-ghost-auto-hospedado-guia",{"title":19121,"description":19798},{"loc":19800},"es\u002Fblog\u002Fstrapi-directus-ghost-auto-hospedado-guia",[19805,19806,19807,19808,7512,6396],"cms","strapi","directus","ghost","lt32DFV4qGtQT2rVqY-PCT0-rg2exA0XhWpiYL3xThA",{"id":19811,"title":19812,"author":7,"body":19813,"category":6382,"cover":3380,"date":20399,"description":20400,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":20401,"navigation":411,"path":8714,"readingTime":3387,"seo":20402,"sitemap":20403,"stem":20404,"tags":20405,"__hash__":20409},"blog_es\u002Fes\u002Fblog\u002Fmigrar-de-kubernetes-a-stack-mas-simple.md","Migrando de Kubernetes a stack más simple: caso real de reducción de complejidad",{"type":9,"value":19814,"toc":20380},[19815,19822,19829,19832,19836,19839,19842,19848,19854,19860,19866,19872,19878,19881,19885,19888,19894,19900,19906,19912,19918,19921,19925,19928,19938,19947,19956,19962,19968,19974,19977,19981,19984,19990,19996,20002,20008,20011,20015,20018,20022,20025,20028,20031,20035,20038,20114,20117,20120,20124,20127,20130,20133,20137,20140,20143,20146,20149,20153,20164,20167,20171,20174,20184,20190,20196,20202,20208,20221,20225,20228,20234,20240,20246,20250,20253,20285,20288,20292,20295,20298,20301,20304,20306,20312,20318,20324,20330,20336,20342,20348,20350,20353,20356,20359,20364,20367,20377],[12,19816,19817,19818,19821],{},"La narrativa pública de los últimos seis años fue siempre en la misma dirección: todo el mundo migra ",[27,19819,19820],{},"hacia"," Kubernetes. Conferencias, posts patrocinados, vacantes de SRE, casos de proveedor — el vector es único. Salió de máquina virtual desnuda y subió a K8s. Salió de Heroku y subió a K8s. Salió de Docker Compose y subió a K8s. La dirección es una sola flecha, y quien no está en la flecha debe estar haciéndolo mal.",[12,19823,19824,19825,19828],{},"La realidad silenciosa que nadie publica en conferencia es el vector inverso: cientos de equipos migran ",[27,19826,19827],{},"fuera"," de Kubernetes después de descubrir que pagaron caro por la complejidad que no necesitaban. No es titular, pero ocurre todos los meses. Empresa de quince devs con cluster EKS de seis nodos percibe que el equipo de plataforma se volvió la mitad del presupuesto de ingeniería. Startup que adoptó K8s al segundo día descubre que tres años después todavía gasta un viernes entero al mes solo actualizando versión de Helm chart de operadores. Equipo de producto que debería estar shippando feature está depurando webhook de admission controller.",[12,19830,19831],{},"Este post es el playbook para esa migración inversa, con las trampas reales que vimos suceder. No es pitch — es manual operacional. Si lees esto y decides quedarte en Kubernetes, genial. La decisión informada de quedarse es tan valiosa como la decisión informada de salir.",[19,19833,19835],{"id":19834},"la-pregunta-de-calificacion-deberias-siquiera-considerar-esto","La pregunta de calificación: ¿deberías siquiera considerar esto?",[12,19837,19838],{},"Antes de cualquier cosa, descarta el caso. Migración inversa solo tiene sentido para un perfil específico — y la mayoría de los equipos que piensa en salir de K8s no está en ese perfil. Los demás están investigando alternativa cuando deberían estar contratando un SRE más o simplificando el uso actual del K8s.",[12,19840,19841],{},"El perfil en que la migración tiene sentido tiene seis señales simultáneas:",[12,19843,19844,19847],{},[27,19845,19846],{},"Señal 1: la empresa corre Kubernetes en producción hace un año o más."," Migración no es experimento. Si el equipo está en K8s hace tres meses y ya está reclamando, el problema es onboarding, no plataforma. Espera el ciclo de aprendizaje completar antes de declarar quiebra.",[12,19849,19850,19853],{},[27,19851,19852],{},"Señal 2: el equipo de plataforma tiene entre una y tres personas."," Empresas con cinco o más ingenieros dedicados a plataforma tienen escala de operación que justifica K8s. Por debajo de eso, la herramienta tiende a consumir el equipo entero en mantenimiento.",[12,19855,19856,19859],{},[27,19857,19858],{},"Señal 3: el cluster tiene menos de cincuenta servidores en producción."," Por encima de ese número, el ecosistema de K8s te da herramientas de tooling — escalado horizontal de nodos, balanceo entre regiones, federación multi-cluster — que otra stack no te da. Por debajo, estás pagando overhead por capacidad que no usas.",[12,19861,19862,19865],{},[27,19863,19864],{},"Señal 4: las apps son típicas."," Web HTTP, base relacional, cache en memoria, jobs asíncronos, alguna cola. Si el stack incluye operador exótico de base distribuida, malla de servicio con políticas L7 sofisticadas, o agendamiento de GPU para entrenamiento de modelo, la migración inversa se complica.",[12,19867,19868,19871],{},[27,19869,19870],{},"Señal 5: 80% del tiempo de plataforma es mantenimiento, no feature nueva."," Si el equipo de plataforma pasa la mayoría de las semanas actualizando Helm chart, depurando upgrade de versión de cluster, o arreglando webhook que falló, es síntoma claro. La plataforma se volvió producto interno que se consume a sí mismo.",[12,19873,19874,19877],{},[27,19875,19876],{},"Señal 6: el salario total de plataforma representa más del 5% del MRR."," No es regla absoluta, pero es métrica útil. Cuando el equipo que opera la infra cuesta más que un veintavo del ingreso recurrente mensual, la infra está demasiado cara para la escala actual de la empresa.",[12,19879,19880],{},"Si tu empresa marca las seis, vale la pena leer el resto del post. Si marca tres o cuatro, lee pero decide con cautela. Si marca una o dos, probablemente el problema es otro.",[19,19882,19884],{"id":19883},"quien-definitivamente-no-debe-migrar","Quién definitivamente no debe migrar",[12,19886,19887],{},"Misma honestidad en el inverso. Existe perfil en que salir de K8s es decisión equivocada, y quien encaja debería cerrar esa pestaña.",[12,19889,19890,19893],{},[27,19891,19892],{},"Equipo fuerte de plataforma con proceso maduro."," Si tienes cinco ingenieros de plataforma que dominan K8s, pipeline de CI\u002FCD estable, runbook escrito, observabilidad configurada — salir de todo eso para empezar de cero en un stack más simple es tirar inversión real. La simplicidad del destino no compensa el reset.",[12,19895,19896,19899],{},[27,19897,19898],{},"Stack que depende de operadores críticos."," Base relacional con replicación automática gestionada por operador, cola distribuida con balanceo gestionado por operador, base columnar con bootstrap automático. Esos operadores son valor real. Cambiar a \"humano cuida de eso\" es regresión operacional, no simplificación.",[12,19901,19902,19905],{},[27,19903,19904],{},"Compliance que exige Kubernetes nominalmente."," Algunos frameworks de auditoría — FedRAMP en determinados niveles, ciertos contratos de gobierno, algunos sellos de seguridad sectoriales — listan herramientas pre-aprobadas. Si tu compliance officer necesita apuntar a un certificado existente, K8s es la respuesta. Migrar a herramienta que no está en la lista crea fricción que cuesta más que economía.",[12,19907,19908,19911],{},[27,19909,19910],{},"Federación multi-cluster en producción."," Si corres workloads que se mueven entre clusters en regiones diferentes, con replicación de estado coordinada por herramienta tipo Argo o FluxCD en modo multi-cluster, el ecosistema de K8s tiene primitivas que otros stacks no tienen. Migrar de eso es proyecto de seis meses como mínimo.",[12,19913,19914,19917],{},[27,19915,19916],{},"Workloads de ML\u002FAI con agendamiento de GPU complejo."," Entrenamiento distribuido, particionamiento de GPU, agendamiento que entiende afinidad de hardware específico. K8s tiene operadores y plugins maduros para eso. Stack más simple no tiene.",[12,19919,19920],{},"Si encajas en cualquiera de esos cinco, la recomendación honesta es quedarse donde estás y optimizar el uso actual de K8s.",[19,19922,19924],{"id":19923},"pre-flight-assessment-uno-a-dos-dias-antes-de-comprometer","Pre-flight assessment: uno a dos días antes de comprometer",[12,19926,19927],{},"Migración inversa empieza con inventario. Antes de marcar reunión de \"vamos a salir de K8s\", el equipo necesita medir lo que tiene hoy. Sin números, la decisión es vibe — y vibe no sobrevive al primer problema imprevisto durante cutover.",[12,19929,19930,19933,19934,19937],{},[27,19931,19932],{},"Inventario de manifests."," Corre ",[231,19935,19936],{},"kubectl get all -A --output yaml > all.yaml"," y cuenta. ¿Cuántos archivos en el repositorio de manifiestos? ¿Cuántas líneas en el agregado? ¿Cuántos namespaces? Nuestra medición informal en equipos pequeños: empresa con diez apps típicas suele tener entre 1.500 y 4.000 líneas de YAML, distribuidas entre Deployment, Service, Ingress, ConfigMap, Secret, HorizontalPodAutoscaler, y algún NetworkPolicy. Cada una de esas líneas es trabajo de migración.",[12,19939,19940,2578,19943,19946],{},[27,19941,19942],{},"Inventario de releases Helm.",[231,19944,19945],{},"helm list -A"," muestra cada chart instalado. Cada uno es una decisión. ¿Chart de operador de base — va a volverse job común en el destino, con replicación manual? ¿Chart de ingress — va a volverse config de router integrado? ¿Chart de monitoring — va a volverse agente externo? Cuantos más charts, más tiempo de migración.",[12,19948,19949,2578,19952,19955],{},[27,19950,19951],{},"Inventario de operadores.",[231,19953,19954],{},"kubectl get crds"," lista cada Custom Resource Definition. Cada CRD es una dependencia crítica que probablemente no tiene equivalente directo en el destino. Si la salida tiene tres o cuatro CRDs (cert-manager, ingress-nginx, prometheus-operator, sealed-secrets), está dentro de lo esperado para equipo pequeño. Si tiene treinta CRDs, la migración no es trivial — construiste plataforma sobre plataforma.",[12,19957,19958,19961],{},[27,19959,19960],{},"Inventario de RBAC y políticas complejas."," NetworkPolicy declarando aislamiento entre namespaces, PodSecurityPolicy o PodSecurityStandards configurados, RoleBinding de granularidad fina. Todo eso necesita equivalente en el destino, y el equivalente raramente es 1:1.",[12,19963,19964,19967],{},[27,19965,19966],{},"Volumen de tráfico."," Solicitudes por segundo en el horario pico, conexiones simultáneas en la base, throughput agregado de salida. El destino necesita absorber todo eso. Si nunca lo mediste, mídelo ahora — antes de comprometer cronograma de migración.",[12,19969,19970,19973],{},[27,19971,19972],{},"Mapeo de Service a Ingress."," Cada Service expuesto se vuelve punto de entrada en el destino. Lista de dominios, certificados asociados, sticky sessions configuradas, reglas de path-based routing. Sin esa lista, la migración se rompe exactamente en el momento de cutover.",[12,19975,19976],{},"Ese assessment lleva uno a dos días para un dev competente. Es barato. Saltarse esa etapa es la mayor fuente de migración que estalla cronograma.",[19,19978,19980],{"id":19979},"decision-de-stack-destino","Decisión de stack destino",[12,19982,19983],{},"Cuatro opciones principales hoy para equipo pequeño. Cada una con trade-off explícito.",[12,19985,19986,19989],{},[27,19987,19988],{},"Opción A: Docker Swarm."," Compatibilidad directa con formato Compose, multi-server simple, baja curva de aprendizaje. Bueno para equipo de un dev que ya conoce Compose. Limitación seria: Swarm está en modo mantenimiento hace tiempo, sin desarrollo activo de feature nueva. Corre y funciona, pero estás apostando en herramienta que no evoluciona.",[12,19991,19992,19995],{},[27,19993,19994],{},"Opción B: Nomad."," Similar a K8s en modelo declarativo, pero más simple y con binario único. Bueno para quien gusta de modelo declarativo robusto y quiere HA real. Limitación: la licencia cambió a modelo restringido desde 2023, y la empresa detrás fue adquirida en 2025. Para adopción nueva hoy, es camino con asterisco.",[12,19997,19998,20001],{},[27,19999,20000],{},"Opción C: HeroCtl."," Orquestador independiente con plano de control replicado, binario único, configuración corta. Bueno para quien quiere simplicidad operacional y alta disponibilidad real desde el primer día. Limitación honesta: ecosistema menor que K8s, sin biblioteca profunda de operadores listos.",[12,20003,20004,20007],{},[27,20005,20006],{},"Opción D: panel self-hosted (Coolify, Dokploy, similares)."," Panel web que orquesta Docker en una máquina o pequeño conjunto. Bueno para equipo muy pequeño sin requisitos formales de HA. Limitación: arquitectura que no soporta consenso distribuido real entre varios servidores — creció, se volvió punto único de falla.",[12,20009,20010],{},"La elección depende del perfil. Equipo de un dev sin requisito de SLA = Opción D. Equipo pequeño con requisito de HA real = Opción C. Equipo que prefiere modelo declarativo robusto y acepta licencia restringida = Opción B. Equipo ya invertido en Compose = Opción A.",[19,20012,20014],{"id":20013},"los-cinco-pasos-de-la-migracion","Los cinco pasos de la migración",[12,20016,20017],{},"A partir de aquí el playbook asume que el stack destino es HeroCtl, pero el esqueleto se aplica a cualquier destino. Ajusta los mapeos conceptuales para Swarm\u002FNomad\u002FCoolify según elección.",[368,20019,20021],{"id":20020},"paso-1-setup-del-destino-en-paralelo-una-semana","Paso 1 — Setup del destino en paralelo (una semana)",[12,20023,20024],{},"Regla dura: nunca migrar in-place. El cluster K8s actual sigue corriendo intocado durante toda la migración. El destino se provisiona en paralelo, en servidores nuevos, con dominio temporal o subdominio de prueba.",[12,20026,20027],{},"Tres a cinco servidores Linux nuevos. Instalar el stack destino. Validar que la red entre los servidores funciona, que el storage persiste después de reboot, que certificados son emitidos automáticamente, que secretos pueden ser inyectados en apps. Conectar el destino con el mismo registry de imágenes que el K8s actual usa — así la misma imagen que corre en producción va al destino sin rebuild.",[12,20029,20030],{},"Ese paso es deliberadamente liviano. La intención es probar que el destino funciona con app sintético antes de comprometer migración de app real.",[368,20032,20034],{"id":20033},"paso-2-migracion-de-manifests-para-spec-del-destino-una-a-dos-semanas","Paso 2 — Migración de manifests para spec del destino (una a dos semanas)",[12,20036,20037],{},"La mayor parte del esfuerzo está aquí. Cada workload del K8s necesita ser reexpresado en el formato del destino. El mapeo conceptual de K8s para HeroCtl sirve de referencia:",[2735,20039,20040,20050,20056,20062,20068,20074,20080,20086,20092,20098,20108],{},[70,20041,20042,20045,20046,20049],{},[27,20043,20044],{},"Deployment + ReplicaSet"," → job con ",[231,20047,20048],{},"replicas: N",". El concepto es el mismo: N copias del mismo workload, balanceadas entre servidores.",[70,20051,20052,20055],{},[27,20053,20054],{},"Service ClusterIP"," → service interno. En HeroCtl no necesita crear — cualquier task tiene nombre resolvible dentro del cluster por defecto.",[70,20057,20058,20061],{},[27,20059,20060],{},"Service LoadBalancer o Ingress"," → ingress integrado. Sin operador externo, sin cert-manager separado, sin ingress-nginx — todo embebido en el orquestador.",[70,20063,20064,20067],{},[27,20065,20066],{},"Pod"," → task. Concepto 1:1.",[70,20069,20070,20073],{},[27,20071,20072],{},"PersistentVolume"," → volumen nombrado. Puede exigir copia de datos, dependiendo del storage backend usado en K8s.",[70,20075,20076,20079],{},[27,20077,20078],{},"ConfigMap"," → bloque de env o archivo en el spec. No hay objeto separado.",[70,20081,20082,20085],{},[27,20083,20084],{},"Secret"," → secreto integrado del orquestador. Cifrado en reposo en el plano de control.",[70,20087,20088,20091],{},[27,20089,20090],{},"HorizontalPodAutoscaler"," → política de scaling en el spec del job. Disparada por uso de CPU, RAM, o métrica custom.",[70,20093,20094,20097],{},[27,20095,20096],{},"DaemonSet"," → job con restricción de placement \"1 por nodo\".",[70,20099,20100,20103,20104,20107],{},[27,20101,20102],{},"CronJob"," → job tipo ",[231,20105,20106],{},"periodic"," con expresión cron.",[70,20109,20110,20113],{},[27,20111,20112],{},"Helm chart"," → spec custom. No convierte 1:1 — reescribir a mano.",[12,20115,20116],{},"En líneas brutas, la reducción es dramática. Una app web típica en K8s tiene 30 a 50 líneas de Deployment, más 20 de Service, más 50 a 100 de Ingress + cert-manager + annotations. Total 100 a 170 líneas. El equivalente en HeroCtl queda entre 30 y 50 líneas, agregando todo en un único archivo.",[12,20118,20119],{},"Tiempo medio de migración por app: uno a tres días para dev competente. Diez apps en tres semanas es ritmo realista. Si llega mucho más lento, hay operador escondido o complejidad no detectada en el assessment — para y remide.",[368,20121,20123],{"id":20122},"paso-3-migracion-de-base-y-storage-uno-a-tres-dias","Paso 3 — Migración de base y storage (uno a tres días)",[12,20125,20126],{},"Dos estrategias. Si la base es gestionada (RDS, Cloud SQL, equivalente), el destino solo apunta a la nueva cadena de conexión y listo — la base queda donde estaba, agnóstica de plataforma. Si la base es self-hosted en K8s, es dump-and-restore manual: pg_dump en la base antigua, pg_restore en la nueva, con ventana de mantenimiento corta en el momento de cutover.",[12,20128,20129],{},"Volúmenes persistentes de K8s se vuelven volúmenes nombrados en el destino. Puede exigir copia de datos vía rsync o snapshot — dependiendo del storage backend, eso es ventana adicional.",[12,20131,20132],{},"Los secretos son extraídos del K8s y reinsertados en el destino. Usa canal seguro (kubectl get secret -o yaml es solo medio de lectura; nunca commitar archivo intermedio). En HeroCtl, los secretos son sometidos vía API con TLS y quedan cifrados en el plano de control.",[368,20134,20136],{"id":20135},"paso-4-cutover-una-a-tres-horas-normalmente-nocturno","Paso 4 — Cutover (una a tres horas, normalmente nocturno)",[12,20138,20139],{},"El paso crítico. Pre-checks antes de cualquier cambio de DNS: smoke test en el destino — login funciona, página principal carga, base está conectada, latencia es aceptable, cola procesa job, métricas llegan en el monitoring. Si alguno de los cinco falla, aborta el cutover.",[12,20141,20142],{},"DNS preparado: TTL reducido a 60 segundos veinticuatro horas antes de la ventana. Sin eso, propagación lleva horas y rollback es doloroso.",[12,20144,20145],{},"Cutover propiamente dicho: cambia el registro DNS para apuntar a las IPs del destino. Monitorea 5xx y latencia en ventana de cinco minutos. Si algo se rompe significativamente en los primeros treinta minutos, switch DNS de vuelta al K8s — rollback completo en sesenta segundos de propagación adicional.",[12,20147,20148],{},"Mantén el cluster K8s corriendo como standby por treinta días. No apagues. El costo extra está justificado: si algún bug latente aparece en la semana tres del destino, todavía tienes adónde volver.",[368,20150,20152],{"id":20151},"paso-5-decommission-del-k8s-una-a-dos-horas-despues-de-treinta-dias","Paso 5 — Decommission del K8s (una a dos horas, después de treinta días)",[12,20154,20155,20156,20159,20160,20163],{},"Treinta días después del cutover, sin incidente significativo, hora de apagar. ",[231,20157,20158],{},"kubectl delete cluster"," en el caso self-hosted, o ",[231,20161,20162],{},"aws eks delete-cluster"," (o equivalente en otras nubes) en el caso gestionado. Cancelar managed addons separadamente — la factura tiene ítems que no desaparecen solo con delete-cluster.",[12,20165,20166],{},"Reembolso prorrateado del mes corriente del plan gestionado, si el proveedor lo ofrece. Cancelación de las instancias de worker. Backup final del estado del cluster antes del delete, en caso de auditoría futura.",[19,20168,20170],{"id":20169},"las-seis-trampas-del-camino","Las seis trampas del camino",[12,20172,20173],{},"Assessment técnico cubre lo que logras medir. Las trampas abajo son lo que escapa al assessment y rompe el cronograma. Cada una ya causó migración que estalló plazo en algún equipo real.",[12,20175,20176,20179,20180,20183],{},[27,20177,20178],{},"Trampa 1: dependencia oculta en operador."," Crees que no tienes operador complejo, pero cert-manager + ingress-nginx + sealed-secrets ya es stack de tres operadores. Y probablemente tiene más — kube-state-metrics para monitoring, external-dns para actualizar DNS automáticamente, reloader para reiniciar pods cuando ConfigMap cambia. Mapear ",[179,20181,20182],{},"todo",". Cada operador es trabajo de migración que el assessment superficial pierde.",[12,20185,20186,20189],{},[27,20187,20188],{},"Trampa 2: asumir que Helm chart es reescribible en un día."," Chart simple con cinco templates es reescritura de pocas horas. Chart complejo con treinta templates, valores anidados, hooks de pre-install\u002Fpost-install, y dependencias de subcharts puede llevar una semana solo para mapear a spec equivalente. Calibra la estimación por el chart más complejo, no por el más simple.",[12,20191,20192,20195],{},[27,20193,20194],{},"Trampa 3: sticky sessions sin documentar."," El ingress-nginx en K8s soporta sesión persistente por configuración de annotation. Si la app depende de eso (carrito de compras, sesión de admin, websocket persistente) y nadie lo documentó, la migración se rompe exactamente en el cutover cuando un usuario empieza a alternar entre dos servidores backend y pierde estado de sesión. Auditar configuración de ingress antes — no confiar solo en lo que el equipo recuerda.",[12,20197,20198,20201],{},[27,20199,20200],{},"Trampa 4: límites de recurso diferentes."," K8s usa limit\u002Frequest con semántica precisa: request es garantía, limit es techo. El destino puede tener modelo declarativo diferente (límite hard, o cuota agregada por job, o semántica de soft-limit). Error de tuning aquí rompe autoscaling — la app queda subdimensionada en producción y no escala cuando debería, o sobredimensionada y desperdicia capacidad. Remedir consumo real después del cutover, ajustar límites en la primera semana.",[12,20203,20204,20207],{},[27,20205,20206],{},"Trampa 5: formato de log."," Algunos ingress en K8s emiten log en JSON por default — parser downstream (Loki, Datadog, ELK) está configurado para ese formato. Destino puede emitir log en texto plano o formato diferente. Parsing downstream se rompe silenciosamente — alertas paran de dispararse porque el pattern no coincide más. Verificar formato de log del router integrado del destino antes del cutover.",[12,20209,20210,20213,20214,5839,20217,20220],{},[27,20211,20212],{},"Trampa 6: pipeline de CI\u002FCD acoplado."," GitOps con ArgoCD o FluxCD apuntando a K8s necesita ser retrabajado. Si el pipeline aplica manifiesto declarativo con ",[231,20215,20216],{},"kubectl apply",[231,20218,20219],{},"helm upgrade",", eso no funciona en el destino. Adapter scripts en la etapa de deploy son necesarios — recibir el manifiesto viejo, traducir a spec nuevo, someter vía API. Estimar una a dos semanas solo para pipeline de CI\u002FCD, separado del tiempo de migración de manifests.",[19,20222,20224],{"id":20223},"cronograma-realista","Cronograma realista",[12,20226,20227],{},"Calibración honesta de expectativa, en tres rangos de tamaño.",[12,20229,20230,20233],{},[27,20231,20232],{},"Equipo de uno a dos devs, cinco a diez apps:"," cuatro a seis semanas total. Descomposición: una semana de setup del destino, dos a tres semanas de migración de manifests y ajuste, uno a tres días de cutover, treinta días de operación paralela, un día de decommission. Atención: el trabajo de migración roba foco del desarrollo de producto durante ese período. Considera ventana de feature freeze.",[12,20235,20236,20239],{},[27,20237,20238],{},"Equipo de tres a cinco devs, veinte a cincuenta apps:"," ocho a doce semanas. La multiplicación no es lineal — apps adicionales aumentan matriz de pruebas de cutover. Vale la pena dedicar una persona a tiempo completo a la migración y mantener al resto del equipo en producto.",[12,20241,20242,20245],{},[27,20243,20244],{},"Empresa con cien o más apps:"," proyecto de cuatro a seis meses, con una a dos personas dedicadas. En ese tamaño, la migración se vuelve fase con gerente de proyecto, hitos quincenales, y reportes de status. No es sprint.",[19,20247,20249],{"id":20248},"resultados-tipicos-post-migracion","Resultados típicos post-migración",[12,20251,20252],{},"Rangos observados en equipos que completaron la migración. No son garantías — son puntos de referencia.",[2735,20254,20255,20261,20267,20273,20279],{},[70,20256,20257,20260],{},[27,20258,20259],{},"Reducción de RAM total:"," 30% a 50%. El overhead de Kubernetes es real, y desaparece cuando sales. Cluster que usaba 32 GB de RAM agregado se vuelve algo entre 16 y 22 GB para el mismo workload.",[70,20262,20263,20266],{},[27,20264,20265],{},"Reducción de costo cloud:"," 40% a 70%. Viene de tres frentes: sin managed control plane (US$73\u002Fmes por cluster sale del presupuesto), sin NAT gateway por subnet (algunos proveedores cobran por GB), instancias menores posibles (overhead de plataforma sale del consumo).",[70,20268,20269,20272],{},[27,20270,20271],{},"Tiempo de deploy:"," similar o ligeramente mejor. No es donde está la ganancia — K8s es razonablemente rápido en deploy cuando está configurado bien.",[70,20274,20275,20278],{},[27,20276,20277],{},"Tiempo de aprendizaje para dev nuevo:"," una semana, contra cuatro a seis en K8s. El modelo mental es más simple — menos abstracciones intermedias entre \"quiero correr esto\" y \"está corriendo\".",[70,20280,20281,20284],{},[27,20282,20283],{},"Tiempo de operación mensual:"," una a tres horas-dev de mantenimiento, contra veinte a cuarenta en K8s. La ganancia mayor. Es aquí que el ROI se materializa.",[12,20286,20287],{},"Para calibrar la última métrica: cluster público de demostración nuestro corre en cuatro servidores totalizando cinco vCPUs y diez gigabytes de RAM, con plano de control ocupando entre 200 y 400 MB por servidor. Elección de nuevo coordinador, en caso de falla del actual, lleva cerca de siete segundos. Spec de aplicación típica en HeroCtl tiene cerca de cincuenta líneas — comparado a trescientas líneas o más de YAML en Kubernetes para equivalente \"hello world\" con TLS e ingress.",[19,20289,20291],{"id":20290},"la-pregunta-inevitable-va-a-volver-a-kubernetes-eventualmente","La pregunta inevitable: ¿va a volver a Kubernetes eventualmente?",[12,20293,20294],{},"Honestidad. Depende de escala.",[12,20296,20297],{},"Equipo que crece a treinta o más devs, con cien o más servidores en producción, multi-región, con requisito de federación entre clusters, eventualmente choca con el techo de stack más simple. En esa escala, K8s se vuelve elección racional — el ecosistema te da herramientas que otros stacks no tienen. La migración de vuelta es proyecto de meses, no de días, pero es camino viable.",[12,20299,20300],{},"Para startups que se mantienen sub-cincuenta servidores a lo largo de cinco años — la mayoría absoluta de ellas — raramente tiene sentido volver. La ganancia operacional del stack más simple se mantiene durante toda la vida útil del producto.",[12,20302,20303],{},"Migración reversa (HeroCtl → K8s) también es proyecto de semanas, no días. No es decisión one-way. Si la empresa crece mucho más rápido de lo que esperaba, el camino de vuelta existe — más caro que quedarse, pero existe. La decisión de migrar ahora no te encadena para siempre.",[19,20305,7352],{"id":7351},[12,20307,20308,20311],{},[27,20309,20310],{},"¿En cuánto tiempo paga el ROI?","\nPara equipo de uno a dos devs con cluster pequeño, la migración paga en tres a seis meses — el salario equivalente de tiempo recuperado en mantenimiento excede el costo del proyecto de migración. Para equipos mayores, depende de cuánto el equipo de plataforma consumía en mantenimiento; típicamente seis a doce meses.",[12,20313,20314,20317],{},[27,20315,20316],{},"¿Puedo mantener Kubernetes para un workload específico y migrar el resto?","\nSí, y en algunos casos es la estrategia correcta. Workload con operador crítico (base distribuida, cola con balanceo gestionado) queda en K8s. El resto va a stack más simple. Los dos clusters conviven con dominios separados o path-based routing en un router upstream. Cuesta un poco más que consolidar, pero evita reescribir lo que todavía funciona bien.",[12,20319,20320,20323],{},[27,20321,20322],{},"Helm charts complejos: ¿vale la pena reescribir?","\nCaso a caso. Chart de operador de tercero con cincuenta archivos: probablemente no vale la pena, mantén en K8s o cambia la tecnología. Chart propio con veinte templates: vale la pena, es reescritura de pocos días y elimina dependencia de Helm.",[12,20325,20326,20329],{},[27,20327,20328],{},"¿ArgoCD funciona con HeroCtl?","\nNo directamente — ArgoCD fue hecho para aplicar manifiesto K8s. Pero el concepto de GitOps funciona: pipeline observa el repositorio, traduce spec del destino a payload de API, somete vía curl autenticado. Plugin nativo está en consideración; por ahora es adapter script de cincuenta líneas.",[12,20331,20332,20335],{},[27,20333,20334],{},"El equipo que aprendió Kubernetes — ¿van a quedar resentidos?","\nPregunta legítima. Curva de aprendizaje de K8s es inversión real, y a nadie le gusta ver inversión descartada. Conversación directa: la habilidad no desaparece. K8s sigue siendo estándar de mercado para escala grande, y dev que ya dominó sigue empleable y valioso. La migración es decisión de producto para escala actual, no veredicto sobre el conocimiento individual.",[12,20337,20338,20341],{},[27,20339,20340],{},"¿Cloud agnostic es más o menos viable después?","\nMás viable, en la práctica. Stack más simple corre en cualquier servidor Linux con Docker — bare metal, VPS de cualquier proveedor, instancia de cualquier nube. K8s gestionado te ata al proveedor (EKS en AWS, GKE en Google, AKS en Azure) — cada uno con sabor propio. Salir amplía opciones.",[12,20343,20344,20347],{},[27,20345,20346],{},"¿Hay caso público de empresa que hizo esa migración?","\nVarios, pero la mayoría no publica en conferencia (el vector narrativo sigue siendo K8s para todos lados). En foros y en conversaciones informales, es fácil encontrar relato. Si quieres conversar con alguien que hizo la migración, escríbenos — hacemos el puente.",[19,20349,3310],{"id":3309},[12,20351,20352],{},"La decisión de salir de Kubernetes a stack más simple no es confesión de derrota — es reconocimiento de que la herramienta correcta depende de la escala actual de la empresa, y que la escala actual de la empresa no es la del libro de marketing del coloso. Equipo pequeño, cluster pequeño, apps típicas, plataforma consumiendo mitad del presupuesto de ingeniería: es exactamente el escenario en que la migración inversa paga.",[12,20354,20355],{},"No es decisión de una tarde. Es proyecto de cuatro a seis semanas para equipo pequeño, con inventario, mapeo, cutover nocturno, treinta días de operación paralela, y decommission cuidadoso. Pero es proyecto cuyo ROI se mide en horas-dev recuperadas todos los meses — todos los meses, durante los próximos años de la empresa.",[12,20357,20358],{},"Si quieres experimentar HeroCtl como destino candidato:",[224,20360,20362],{"className":20361,"code":5318,"language":2530},[2528],[231,20363,5318],{"__ignoreMap":229},[12,20365,20366],{},"Corre en cualquier servidor Linux con Docker. Tres servidores forman plano de control replicado con alta disponibilidad real. Spec de aplicación queda entre treinta y cincuenta líneas, agregando todo lo necesario (replicación, ingress, certificado automático, secretos). Plan Community gratuito permanente cubre todo el stack descrito aquí — solo Business y Enterprise agregan SSO, RBAC granular, auditoría detallada, escrow de código y soporte con SLA, dirigidos a empresas con requisitos formales de plataforma.",[12,20368,20369,20370,20373,20374,20376],{},"Para contexto adicional, ",[3337,20371,20372],{"href":5343},"k3s vs HeroCtl: cuándo cada uno tiene sentido"," trata de la elección cuando el equipo ya decidió salir del K8s vanilla pero duda entre distribución ligera de K8s y orquestador independiente. Y ",[3337,20375,15791],{"href":15790}," es el argumento de fondo para quien todavía no está convencido de que la complejidad es innecesaria en la escala actual.",[12,20378,20379],{},"Migración inversa no es titular de conferencia. Pero es la decisión correcta para más equipos que lo que la narrativa pública admite.",{"title":229,"searchDepth":244,"depth":244,"links":20381},[20382,20383,20384,20385,20386,20393,20394,20395,20396,20397,20398],{"id":19834,"depth":244,"text":19835},{"id":19883,"depth":244,"text":19884},{"id":19923,"depth":244,"text":19924},{"id":19979,"depth":244,"text":19980},{"id":20013,"depth":244,"text":20014,"children":20387},[20388,20389,20390,20391,20392],{"id":20020,"depth":271,"text":20021},{"id":20033,"depth":271,"text":20034},{"id":20122,"depth":271,"text":20123},{"id":20135,"depth":271,"text":20136},{"id":20151,"depth":271,"text":20152},{"id":20169,"depth":244,"text":20170},{"id":20223,"depth":244,"text":20224},{"id":20248,"depth":244,"text":20249},{"id":20290,"depth":244,"text":20291},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-03-18","Cuando la empresa adopta K8s demasiado temprano, todos pagan. El camino inverso — salir de K8s a orquestación más simple — es viable y más común de lo que parece. Qué validar antes, durante y después.",{},{"title":19812,"description":20400},{"loc":8714},"es\u002Fblog\u002Fmigrar-de-kubernetes-a-stack-mas-simple",[20406,6393,20407,20408,6382],"kubernetes","simplificacion","case","jj7JCXqjwDJW2UlkbfDIn-UDch0Y9tFiVtZ_12e8gQw",{"id":20411,"title":20412,"author":7,"body":20413,"category":6382,"cover":3380,"date":21763,"description":21764,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":21765,"navigation":411,"path":21766,"readingTime":6387,"seo":21767,"sitemap":21768,"stem":21769,"tags":21770,"__hash__":21771},"blog_es\u002Fes\u002Fblog\u002Fmigrar-de-heroku-guia-tecnica.md","Migrar de Heroku a cluster propio: guía técnica en 5 pasos",{"type":9,"value":20414,"toc":21750},[20415,20418,20421,20425,20428,20431,20485,20488,20491,20495,20498,20503,20516,20519,20522,20527,20545,20548,20553,20569,20581,20586,20602,20611,20614,20628,20633,20636,20665,20668,20673,20702,20705,20708,20711,20715,20718,20724,20727,20733,20736,20742,20745,20748,20752,20755,20898,20901,20906,20964,20969,21025,21028,21033,21036,21060,21065,21076,21079,21083,21086,21091,21100,21120,21138,21143,21151,21156,21280,21283,21288,21291,21294,21299,21302,21320,21323,21327,21330,21335,21338,21343,21349,21354,21389,21392,21397,21404,21409,21412,21420,21423,21428,21431,21435,21438,21441,21495,21498,21501,21505,21508,21522,21539,21557,21565,21581,21587,21593,21599,21603,21606,21637,21640,21643,21646,21648,21654,21660,21676,21682,21688,21694,21707,21709,21712,21715,21731,21734,21737,21747],[12,20416,20417],{},"El 28 de noviembre de 2022, Salesforce desconectó el plan gratuito de Heroku. Cientos de miles de hobby projects fueron borrados de una sola vez, y el ciclo de noticias duró unos dos meses — gente migrando a Render, a Fly.io, a Railway, a un VPS cualquiera. Lo que nadie previó en aquel momento es lo que ocurrió después: cuatro años pasaron, estamos en 2026, y todavía existen miles de SaaS brasileños en producción pagando entre US$25 y US$100 al mes por dyno solo porque \"migrar\" es el decimotercero ítem del backlog. Siempre hay una feature más urgente. Siempre hay un cliente preguntando cuándo sale el módulo X. Migrar da cero ingreso nuevo — entonces queda.",[12,20419,20420],{},"Este post es el plan para hacer que esa migración quepa en una semana de trabajo de un dev part-time, y el resto de un mes para estabilizar. No es un manifiesto, no es una comparación de proveedores, no es \"vente al HeroCtl\". Es un runbook. Al final hay una sección sobre opciones de destino, incluyendo nuestro producto, pero si terminas de leer y vas a Render o a Coolify o a Fly.io, el post hizo el trabajo.",[19,20422,20424],{"id":20423},"por-que-todavia-duele-migrar-la-verdad-no-dicha","Por qué todavía duele migrar (la verdad no dicha)",[12,20426,20427],{},"La primera cosa que necesita quedar clara: no es el Dockerfile. Escribir Dockerfile para una app Rails o Node es media tarde — hay template listo para cada framework, hay cinco posts en DEV explicándolo, hay Copilot escribiéndolo. Si tu resistencia es \"todavía no dockerizamos\", esa parte es la menos importante.",[12,20429,20430],{},"El dolor está en el ecosistema:",[2735,20432,20433,20451,20457,20463,20469,20475],{},[70,20434,20435,20438,20439,571,20441,571,20444,571,20447,20450],{},[27,20436,20437],{},"Postgres con extensions específicas"," que olvidaste que activaste en 2019. ",[231,20440,17312],{},[231,20442,20443],{},"pgcrypto",[231,20445,20446],{},"hstore",[231,20448,20449],{},"postgis"," — cada una es un motivo para que la migración se rompa silenciosamente.",[70,20452,20453,20456],{},[27,20454,20455],{},"Redis Premium con persistencia"," que usas para cola de Sidekiq Y para cache Y para rate limit. Para cache puede reiniciar de cero. Para cola no puede.",[70,20458,20459,20462],{},[27,20460,20461],{},"Sidekiq workers stateful"," con jobs agendados meses adelante. Migrar mientras corren es correr atrás del tren en movimiento.",[70,20464,20465,20468],{},[27,20466,20467],{},"Heroku Scheduler"," con aquel cron que nadie mira desde 2020 pero que hace el reporte mensual del CEO.",[70,20470,20471,20474],{},[27,20472,20473],{},"Papertrail"," integrado, NewRelic instrumentado, Bugsnag en todos los errores — tres SaaS extras de los que ni sabes si van a tener sentido en la nueva arquitectura.",[70,20476,20477,20480,20481,20484],{},[27,20478,20479],{},"Buildpack"," que corrió seis años sin nadie saber bien qué hace. Tiene un ",[231,20482,20483],{},"bin\u002Fpost_compile"," que minifica algo, tiene variable de ambiente que define qué versión de Ruby — en algún lugar, tu aplicación depende de seis comportamientos del buildpack que nunca fueron documentados.",[12,20486,20487],{},"Y está la parte humana: tú y tu equipo internalizaron primitivas Heroku a lo largo de años. Procfile, slug compilation, dynos, release phase, config vars. Todo eso se volvió intuición. Cuando vamos a rehacer fuera de Heroku, rehacemos inconscientemente — y en general mal, porque Heroku tenía defaults que esconden decisiones importantes que ahora son tuyas.",[12,20489,20490],{},"La migración técnica lleva una semana. La migración mental lleva un mes. Este post intenta acortar las dos.",[19,20492,20494],{"id":20493},"pre-flight-check-una-a-dos-horas-antes-de-cualquier-commit","Pre-flight check — una a dos horas, antes de cualquier commit",[12,20496,20497],{},"Antes de abrir el editor, necesitas el inventario. La mayor parte de las migraciones que salen mal es por una sorpresa que podría haber sido descubierta en la primera hora.",[12,20499,20500],{},[27,20501,20502],{},"Inventario de apps:",[224,20504,20506],{"className":226,"code":20505,"language":228,"meta":229,"style":229},"heroku apps\n",[231,20507,20508],{"__ignoreMap":229},[234,20509,20510,20513],{"class":236,"line":237},[234,20511,20512],{"class":247},"heroku",[234,20514,20515],{"class":255}," apps\n",[12,20517,20518],{},"¿Cuántas apps existen en la cuenta? ¿Cuáles todavía están en uso de verdad? ¿Cuáles pueden volverse cron-job y morir? ¿Cuáles fueron creadas para un cliente que se fue en 2021? Marca cada una en una hoja de cálculo con tres columnas: nombre, status (vivo\u002Fzombi\u002Fcron), prioridad de migración (alta\u002Fmedia\u002Fbaja).",[12,20520,20521],{},"La mayoría de las cuentas tiene 30% de apps zombis. Migrar zombi no tiene ROI — destruir tiene.",[12,20523,20524],{},[27,20525,20526],{},"Inventario de addons por app:",[224,20528,20530],{"className":226,"code":20529,"language":228,"meta":229,"style":229},"heroku addons -a mi-app\n",[231,20531,20532],{"__ignoreMap":229},[234,20533,20534,20536,20539,20542],{"class":236,"line":237},[234,20535,20512],{"class":247},[234,20537,20538],{"class":255}," addons",[234,20540,20541],{"class":251}," -a",[234,20543,20544],{"class":255}," mi-app\n",[12,20546,20547],{},"Cada línea es una decisión futura. ¿Postgres? ¿Redis? ¿Papertrail? ¿Heroku Scheduler? ¿SendGrid? ¿Mailgun? Para cada uno, escribe en la hoja: va a migrar a equivalente self-hosted, va a volverse SaaS externo, o va a descartar. Si no sabes para qué sirve, investiga antes — no en el momento del cutover.",[12,20549,20550],{},[27,20551,20552],{},"Inventario de buildpacks:",[224,20554,20556],{"className":226,"code":20555,"language":228,"meta":229,"style":229},"heroku buildpacks -a mi-app\n",[231,20557,20558],{"__ignoreMap":229},[234,20559,20560,20562,20565,20567],{"class":236,"line":237},[234,20561,20512],{"class":247},[234,20563,20564],{"class":255}," buildpacks",[234,20566,20541],{"class":251},[234,20568,20544],{"class":255},[12,20570,20571,20572,571,20575,571,20578,20580],{},"¿Multi-buildpack? ¿Custom buildpack? Si la salida tiene más de una línea, lee cada uno. Buildpack customizado suele tener hooks (",[231,20573,20574],{},"bin\u002Frelease",[231,20576,20577],{},"bin\u002Fcompile",[231,20579,20483],{},") que ejecutan cosas específicas. Vas a necesitar replicar esos pasos en el Dockerfile o en un release container.",[12,20582,20583],{},[27,20584,20585],{},"Inventario de env vars:",[224,20587,20589],{"className":226,"code":20588,"language":228,"meta":229,"style":229},"heroku config -a mi-app\n",[231,20590,20591],{"__ignoreMap":229},[234,20592,20593,20595,20598,20600],{"class":236,"line":237},[234,20594,20512],{"class":247},[234,20596,20597],{"class":255}," config",[234,20599,20541],{"class":251},[234,20601,20544],{"class":255},[12,20603,20604,20605,571,20607,20610],{},"Exporta todo a archivo seguro. NO commits. NO mandes por Slack. NO pegues en ChatGPT. Ese archivo tiene ",[231,20606,453],{},[231,20608,20609],{},"SECRET_KEY_BASE",", clave de API de pago. Trátalo como contraseña, porque es exactamente eso.",[12,20612,20613],{},"Atención a dos trampas:",[2735,20615,20616,20622],{},[70,20617,20618,20619,20621],{},"Variables con carácter ",[231,20620,1272],{}," en el nombre (algunas libs antiguas usan) escapan diferente en contenedores.",[70,20623,20624,20627],{},[231,20625,20626],{},"BUNDLE_WITHOUT=development:test"," grabado en producción es bomba reloj después de la migración.",[12,20629,20630],{},[27,20631,20632],{},"Inventario de Procfile:",[12,20634,20635],{},"Cada línea del Procfile es un servicio:",[2735,20637,20638,20644,20650,20656],{},[70,20639,20640,20643],{},[231,20641,20642],{},"web"," se vuelve el contenedor principal.",[70,20645,20646,20649],{},[231,20647,20648],{},"worker"," se vuelve segundo contenedor o job separado.",[70,20651,20652,20655],{},[231,20653,20654],{},"release"," se vuelve step pre-deploy (típicamente migrations).",[70,20657,20658,5839,20661,20664],{},[231,20659,20660],{},"clock",[231,20662,20663],{},"scheduler"," se vuelve cron job.",[12,20666,20667],{},"Si tu Procfile tiene cinco líneas, vas a tener cinco servicios en el destino. No son detalles — son el diseño de la topología.",[12,20669,20670],{},[27,20671,20672],{},"Métricas actuales:",[224,20674,20676],{"className":226,"code":20675,"language":228,"meta":229,"style":229},"heroku ps -a mi-app\nheroku logs --tail -a mi-app\n",[231,20677,20678,20688],{"__ignoreMap":229},[234,20679,20680,20682,20684,20686],{"class":236,"line":237},[234,20681,20512],{"class":247},[234,20683,9417],{"class":255},[234,20685,20541],{"class":251},[234,20687,20544],{"class":255},[234,20689,20690,20692,20695,20698,20700],{"class":236,"line":244},[234,20691,20512],{"class":247},[234,20693,20694],{"class":255}," logs",[234,20696,20697],{"class":251}," --tail",[234,20699,20541],{"class":251},[234,20701,20544],{"class":255},[12,20703,20704],{},"¿Cuántos dynos corriendo? ¿Cuál el tipo (Standard-1X, Performance-M)? ¿Volumen de logs por minuto? ¿Latencia media en NewRelic? ¿Pico de CPU\u002Fmemoria del mes pasado?",[12,20706,20707],{},"Esos números sirven para dimensionar el destino. Migrar y descubrir después que la memoria es la mitad de lo necesario es la forma más rápida de romper la confianza en el proyecto entero.",[12,20709,20710],{},"Al final del pre-flight tienes una hoja de cálculo con todo. Ese archivo es el corazón de la migración. Toda decisión vuelve a él.",[19,20712,20714],{"id":20713},"paso-1-eleccion-de-stack-destino-decision-arquitectural-30-minutos","Paso 1 — Elección de stack destino (decisión arquitectural, 30 minutos)",[12,20716,20717],{},"Tres caminos posibles. Voy a ser honesto sobre cada uno.",[12,20719,20720,20723],{},[27,20721,20722],{},"Opción A — VPS único con panel self-hosted.","\nUn servidor en DigitalOcean o Hetzner, instala Coolify o Dokploy, despliega tu app por el panel. Costo: R$30 a R$50 al mes para empezar, escala bien hasta unas 10 apps en servidor mediano. Sin alta disponibilidad — si el servidor cae, todo cae. SLA que logras prometer: best-effort.",[12,20725,20726],{},"Ideal para: indie hacker, proyecto personal, MVP, SaaS sin cliente que exige SLA por escrito.",[12,20728,20729,20732],{},[27,20730,20731],{},"Opción B — Cluster con alta disponibilidad.","\nTres o más servidores, orquestador que coordina entre ellos, sobrevive a la caída de un servidor sin afectar tráfico. Costo: R$150 a R$300 al mes para un cluster de tres nodos modestos. SLA posible: 99,9% sin desesperación.",[12,20734,20735],{},"Ideal para: SaaS B2B con clientes pagantes, cualquier aplicación donde media hora de downtime genera ticket de soporte.",[12,20737,20738,20741],{},[27,20739,20740],{},"Opción C — Plataforma gestionada externa.","\nRender, Railway, Fly.io. Pagas más, pero cero ops. Costo: R$200 a R$500 al mes para workload comparable a 2-3 dynos Heroku, escala lineal de ahí en adelante.",[12,20743,20744],{},"Ideal para: equipo que no tiene absolutamente a nadie para cuidar de servidor y prefiere transferir el problema a otra empresa.",[12,20746,20747],{},"Decisión honesta, en una pregunta: ¿hay cliente exigiendo SLA? Si no, opción A. Si sí, B. Si el equipo no tiene a nadie dispuesto a aprender mínima ops, C. No existe respuesta correcta universal — existe respuesta correcta para tu contexto. Mezclar las tres también es válido: app principal en B, herramienta interna en A, scheduler aislado en C.",[19,20749,20751],{"id":20750},"paso-2-dockerizacion-medio-dia-a-dos-dias-por-app","Paso 2 — Dockerización (medio día a dos días por app)",[12,20753,20754],{},"Aquí el trabajo técnico empieza. La lógica general es la misma para cualquier stack:",[224,20756,20760],{"className":20757,"code":20758,"language":20759,"meta":229,"style":229},"language-dockerfile shiki shiki-themes github-dark-default","FROM ruby:3.3-slim AS builder\nWORKDIR \u002Fapp\nCOPY Gemfile Gemfile.lock .\u002F\nRUN bundle install --without development test\nCOPY . .\nRUN bundle exec rake assets:precompile\n\nFROM ruby:3.3-slim\nWORKDIR \u002Fapp\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n    libpq5 nodejs && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F*\nCOPY --from=builder \u002Fusr\u002Flocal\u002Fbundle \u002Fusr\u002Flocal\u002Fbundle\nCOPY --from=builder \u002Fapp \u002Fapp\nEXPOSE 3000\nCMD [\"bundle\", \"exec\", \"puma\", \"-C\", \"config\u002Fpuma.rb\"]\n","dockerfile",[231,20761,20762,20776,20784,20792,20800,20807,20814,20818,20825,20831,20838,20843,20850,20857,20865],{"__ignoreMap":229},[234,20763,20764,20767,20770,20773],{"class":236,"line":237},[234,20765,20766],{"class":383},"FROM",[234,20768,20769],{"class":387}," ruby:3.3-slim ",[234,20771,20772],{"class":383},"AS",[234,20774,20775],{"class":387}," builder\n",[234,20777,20778,20781],{"class":236,"line":244},[234,20779,20780],{"class":383},"WORKDIR",[234,20782,20783],{"class":387}," \u002Fapp\n",[234,20785,20786,20789],{"class":236,"line":271},[234,20787,20788],{"class":383},"COPY",[234,20790,20791],{"class":387}," Gemfile Gemfile.lock .\u002F\n",[234,20793,20794,20797],{"class":236,"line":415},[234,20795,20796],{"class":383},"RUN",[234,20798,20799],{"class":387}," bundle install --without development test\n",[234,20801,20802,20804],{"class":236,"line":434},[234,20803,20788],{"class":383},[234,20805,20806],{"class":387}," . .\n",[234,20808,20809,20811],{"class":236,"line":459},[234,20810,20796],{"class":383},[234,20812,20813],{"class":387}," bundle exec rake assets:precompile\n",[234,20815,20816],{"class":236,"line":464},[234,20817,412],{"emptyLinePlaceholder":411},[234,20819,20820,20822],{"class":236,"line":479},[234,20821,20766],{"class":383},[234,20823,20824],{"class":387}," ruby:3.3-slim\n",[234,20826,20827,20829],{"class":236,"line":484},[234,20828,20780],{"class":383},[234,20830,20783],{"class":387},[234,20832,20833,20835],{"class":236,"line":490},[234,20834,20796],{"class":383},[234,20836,20837],{"class":387}," apt-get update && apt-get install -y --no-install-recommends \\\n",[234,20839,20840],{"class":236,"line":508},[234,20841,20842],{"class":387},"    libpq5 nodejs && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F*\n",[234,20844,20845,20847],{"class":236,"line":529},[234,20846,20788],{"class":383},[234,20848,20849],{"class":387}," --from=builder \u002Fusr\u002Flocal\u002Fbundle \u002Fusr\u002Flocal\u002Fbundle\n",[234,20851,20852,20854],{"class":236,"line":535},[234,20853,20788],{"class":383},[234,20855,20856],{"class":387}," --from=builder \u002Fapp \u002Fapp\n",[234,20858,20859,20862],{"class":236,"line":546},[234,20860,20861],{"class":383},"EXPOSE",[234,20863,20864],{"class":387}," 3000\n",[234,20866,20867,20870,20873,20876,20878,20881,20883,20886,20888,20891,20893,20896],{"class":236,"line":552},[234,20868,20869],{"class":383},"CMD",[234,20871,20872],{"class":387}," [",[234,20874,20875],{"class":255},"\"bundle\"",[234,20877,571],{"class":387},[234,20879,20880],{"class":255},"\"exec\"",[234,20882,571],{"class":387},[234,20884,20885],{"class":255},"\"puma\"",[234,20887,571],{"class":387},[234,20889,20890],{"class":255},"\"-C\"",[234,20892,571],{"class":387},[234,20894,20895],{"class":255},"\"config\u002Fpuma.rb\"",[234,20897,9534],{"class":387},[12,20899,20900],{},"Multi-stage. Build pesado queda en una etapa que es descartada. Imagen final tiene solo lo necesario para correr.",[12,20902,20903],{},[27,20904,20905],{},"Por lenguaje:",[2735,20907,20908,20924,20936,20951],{},[70,20909,20910,6562,20913,20916,20917,571,20920,20923],{},[27,20911,20912],{},"Ruby\u002FRails",[231,20914,20915],{},"ruby:3.x-slim"," como base, multi-stage para reducir tamaño. El slug compilation de Heroku se volvió tus propias líneas en el Dockerfile — ",[231,20918,20919],{},"bundle install",[231,20921,20922],{},"assets:precompile",", copiar artefactos.",[70,20925,20926,6562,20929,20932,20933,101],{},[27,20927,20928],{},"Node",[231,20930,20931],{},"node:20-alpine"," resuelve la mayoría de los casos. Atención a deps con binarios nativos (sharp, bcrypt, sqlite3, canvas) — Alpine usa musl, y algunas libs necesitan glibc. Si se rompe, cambia a ",[231,20934,20935],{},"node:20-slim",[70,20937,20938,6562,20941,20944,20945,5839,20947,20950],{},[27,20939,20940],{},"Python\u002FDjango",[231,20942,20943],{},"python:3.x-slim",", gunicorn o uvicorn como server. ",[231,20946,8512],{},[231,20948,20949],{},"pyproject.toml"," en la etapa de build.",[70,20952,20953,6562,20956,20959,20960,20963],{},[27,20954,20955],{},"Elixir\u002FPhoenix",[231,20957,20958],{},"elixir:1.x-alpine",", release como artefacto (",[231,20961,20962],{},"mix release","), runtime image solo con erlang.",[12,20965,20966],{},[27,20967,20968],{},"Mapeo Procfile → Docker:",[119,20970,20971,20981],{},[122,20972,20973],{},[125,20974,20975,20978],{},[128,20976,20977],{},"Procfile",[128,20979,20980],{},"Equivalente en destino",[141,20982,20983,20995,21005,21015],{},[125,20984,20985,20990],{},[146,20986,20987],{},[231,20988,20989],{},"web: bundle exec puma",[146,20991,20992,20994],{},[231,20993,20869],{}," del contenedor principal",[125,20996,20997,21002],{},[146,20998,20999],{},[231,21000,21001],{},"worker: bundle exec sidekiq",[146,21003,21004],{},"Contenedor separado, misma imagen, comando diferente",[125,21006,21007,21012],{},[146,21008,21009],{},[231,21010,21011],{},"release: bundle exec rake db:migrate",[146,21013,21014],{},"Job de release, ejecuta antes del rolling update",[125,21016,21017,21022],{},[146,21018,21019],{},[231,21020,21021],{},"clock: bundle exec clockwork",[146,21023,21024],{},"Cron job, o contenedor singleton",[12,21026,21027],{},"La mayor parte de los orquestadores modernos (HeroCtl, Render, Railway, Coolify) entiende esos cuatro formatos directamente.",[12,21029,21030],{},[27,21031,21032],{},"Assets:",[12,21034,21035],{},"Slug compilation de Heroku hace precompile automático. En Docker necesitas pensar:",[2735,21037,21038,21044,21050],{},[70,21039,21040,21041,20950],{},"Rails: ",[231,21042,21043],{},"RUN bundle exec rake assets:precompile",[70,21045,21046,21047,20950],{},"Node: ",[231,21048,21049],{},"RUN npm run build",[70,21051,21052,21053,2403,21056,21059],{},"Asset host (CDN): si usas CloudFront o S3 para servir static, configurar ",[231,21054,21055],{},"RAILS_SERVE_STATIC_FILES",[231,21057,21058],{},"ASSET_HOST"," correctamente.",[12,21061,21062],{},[27,21063,21064],{},"Tiempo medio realista:",[2735,21066,21067,21070,21073],{},[70,21068,21069],{},"App Rails media (CRUD con Sidekiq): 1 a 2 días.",[70,21071,21072],{},"App Node simple (API, sin build pesado de frontend): 4 horas.",[70,21074,21075],{},"App con 5+ workers stateful y procesamiento de medios: 3 a 5 días.",[12,21077,21078],{},"La primera app demora más. La segunda demora la mitad. De la tercera en adelante, es mecánico.",[19,21080,21082],{"id":21081},"paso-3-migracion-de-base-la-parte-mas-arriesgada-2-a-8-horas","Paso 3 — Migración de base (la parte más arriesgada, 2 a 8 horas)",[12,21084,21085],{},"Aquí mora el miedo. Base es el único lugar donde \"volver atrás\" es caro. Todo lo demás es redeploy.",[12,21087,21088],{},[27,21089,21090],{},"Postgres:",[12,21092,21093,21094,21096,21097,21099],{},"Heroku Postgres expone acceso directo vía ",[231,21095,5736],{}," si tienes las credenciales (están en ",[231,21098,453],{},"). Antes de cualquier cosa, descubre tus extensions:",[224,21101,21105],{"className":21102,"code":21103,"language":21104,"meta":229,"style":229},"language-sql shiki shiki-themes github-dark-default","SELECT extname, extversion FROM pg_extension;\n","sql",[231,21106,21107],{"__ignoreMap":229},[234,21108,21109,21112,21115,21117],{"class":236,"line":237},[234,21110,21111],{"class":383},"SELECT",[234,21113,21114],{"class":387}," extname, extversion ",[234,21116,20766],{"class":383},[234,21118,21119],{"class":387}," pg_extension;\n",[12,21121,21122,21123,571,21125,571,21127,571,21129,571,21131,571,21134,21137],{},"Comunes: ",[231,21124,20443],{},[231,21126,20446],{},[231,21128,20449],{},[231,21130,17312],{},[231,21132,21133],{},"uuid-ossp",[231,21135,21136],{},"unaccent",". Si el destino no tiene todas, o tiene en versión diferente, lo descubres antes — no en medio del restore a las 3 de la mañana.",[12,21139,21140],{},[27,21141,21142],{},"Destino posible para Postgres:",[2735,21144,21145,21148],{},[70,21146,21147],{},"Postgres corriendo como job en el propio cluster (RPO\u002FRTO menor, control total, tú cuidas del backup).",[70,21149,21150],{},"Postgres gestionado regional — RDS São Paulo, Neon, Supabase, Aiven. Más caro, menos ops.",[12,21152,21153],{},[27,21154,21155],{},"Migración con mínimo downtime — opción A (con ventana):",[224,21157,21159],{"className":226,"code":21158,"language":228,"meta":229,"style":229},"# Drena tráfico: pone app en mantenimiento, espera Sidekiq vaciar\nheroku maintenance:on -a mi-app\n\n# Dump\npg_dump $HEROKU_DATABASE_URL --no-owner --no-privileges --format=custom --file=dump.sql\n\n# Restore en destino\npg_restore --no-owner --no-privileges --dbname=$DEST_DATABASE_URL dump.sql\n\n# Smoke test en destino\npsql $DEST_DATABASE_URL -c 'SELECT count(*) FROM users;'\n\n# Cutover de DNS, app en destino apunta a la nueva base\nheroku maintenance:off -a mi-app  # opcional, solo para que Heroku siga atendiendo \u002Fhealthz\n",[231,21160,21161,21166,21177,21181,21186,21205,21209,21214,21233,21237,21242,21256,21260,21265],{"__ignoreMap":229},[234,21162,21163],{"class":236,"line":237},[234,21164,21165],{"class":240},"# Drena tráfico: pone app en mantenimiento, espera Sidekiq vaciar\n",[234,21167,21168,21170,21173,21175],{"class":236,"line":244},[234,21169,20512],{"class":247},[234,21171,21172],{"class":255}," maintenance:on",[234,21174,20541],{"class":251},[234,21176,20544],{"class":255},[234,21178,21179],{"class":236,"line":271},[234,21180,412],{"emptyLinePlaceholder":411},[234,21182,21183],{"class":236,"line":415},[234,21184,21185],{"class":240},"# Dump\n",[234,21187,21188,21190,21193,21196,21199,21202],{"class":236,"line":434},[234,21189,5736],{"class":247},[234,21191,21192],{"class":387}," $HEROKU_DATABASE_URL ",[234,21194,21195],{"class":251},"--no-owner",[234,21197,21198],{"class":251}," --no-privileges",[234,21200,21201],{"class":251}," --format=custom",[234,21203,21204],{"class":251}," --file=dump.sql\n",[234,21206,21207],{"class":236,"line":459},[234,21208,412],{"emptyLinePlaceholder":411},[234,21210,21211],{"class":236,"line":464},[234,21212,21213],{"class":240},"# Restore en destino\n",[234,21215,21216,21219,21222,21224,21227,21230],{"class":236,"line":479},[234,21217,21218],{"class":247},"pg_restore",[234,21220,21221],{"class":251}," --no-owner",[234,21223,21198],{"class":251},[234,21225,21226],{"class":251}," --dbname=",[234,21228,21229],{"class":387},"$DEST_DATABASE_URL",[234,21231,21232],{"class":255}," dump.sql\n",[234,21234,21235],{"class":236,"line":484},[234,21236,412],{"emptyLinePlaceholder":411},[234,21238,21239],{"class":236,"line":490},[234,21240,21241],{"class":240},"# Smoke test en destino\n",[234,21243,21244,21247,21250,21253],{"class":236,"line":508},[234,21245,21246],{"class":247},"psql",[234,21248,21249],{"class":387}," $DEST_DATABASE_URL ",[234,21251,21252],{"class":251},"-c",[234,21254,21255],{"class":255}," 'SELECT count(*) FROM users;'\n",[234,21257,21258],{"class":236,"line":529},[234,21259,412],{"emptyLinePlaceholder":411},[234,21261,21262],{"class":236,"line":535},[234,21263,21264],{"class":240},"# Cutover de DNS, app en destino apunta a la nueva base\n",[234,21266,21267,21269,21272,21274,21277],{"class":236,"line":546},[234,21268,20512],{"class":247},[234,21270,21271],{"class":255}," maintenance:off",[234,21273,20541],{"class":251},[234,21275,21276],{"class":255}," mi-app",[234,21278,21279],{"class":240},"  # opcional, solo para que Heroku siga atendiendo \u002Fhealthz\n",[12,21281,21282],{},"Ventana típica: 30 minutos a 2 horas, dependiendo del tamaño de la base. Para base por debajo de 5GB, 30 min es holgado.",[12,21284,21285],{},[27,21286,21287],{},"Migración con mínimo downtime — opción B (logical replication):",[12,21289,21290],{},"Replicación lógica de Postgres permite que inicies la copia mientras la app sigue escribiendo en Heroku. Cuando la réplica llega al estado actual, haces el cutover de DNS y el destino se vuelve el nuevo primario.",[12,21292,21293],{},"Funciona si el destino logra alcanzar Heroku vía red. Para Heroku Postgres necesita abrir whitelist de la IP del destino (Heroku tiene mecanismo para eso en planes pagados). Setup lleva una tarde, cutover dura segundos.",[12,21295,21296],{},[27,21297,21298],{},"Redis:",[12,21300,21301],{},"Dos naturalezas distintas — trata diferente:",[2735,21303,21304,21310],{},[70,21305,21306,21309],{},[27,21307,21308],{},"Redis como cache",": simplemente reinicia de cero en el destino. El cache se recalienta solo. No hay nada que migrar.",[70,21311,21312,21315,21316,21319],{},[27,21313,21314],{},"Redis como cola Sidekiq\u002FResque con persistencia",": aquí duele. Snapshot vía ",[231,21317,21318],{},"BGSAVE",", transfiere el RDB, restore en el destino. O: pausa los workers en Heroku, procesa la cola hasta el final, haz cutover con cola vacía.",[12,21321,21322],{},"Redis Premium de Heroku tiene persistencia activada por default; Redis simple en el destino puede no tener — verifica antes.",[19,21324,21326],{"id":21325},"paso-4-dns-ssl-y-cutover-1-a-3-horas","Paso 4 — DNS, SSL y cutover (1 a 3 horas)",[12,21328,21329],{},"El cutover es la hora de la verdad. Todo lo que vino antes era preparación.",[12,21331,21332],{},[27,21333,21334],{},"24 horas antes:",[12,21336,21337],{},"Reduce el TTL del registro DNS a 60 segundos. Eso garantiza que, cuando apuntes al destino, propaga rápido. TTL alto es lo que hace cutover volverse pesadilla de 6 horas con la mitad de los clientes todavía hitting el servidor antiguo.",[12,21339,21340],{},[27,21341,21342],{},"Setup paralelo:",[12,21344,21345,21346,622],{},"App corriendo en paralelo en los dos destinos. Heroku sigue respondiendo en el dominio antiguo. Destino responde en un dominio temporal (ej: ",[231,21347,21348],{},"app-nuevo.heroctl.com",[12,21350,21351],{},[27,21352,21353],{},"Smoke test en el destino:",[224,21355,21357],{"className":226,"code":21356,"language":228,"meta":229,"style":229},"curl https:\u002F\u002Fapp-nuevo.heroctl.com\u002Fhealthz\ncurl https:\u002F\u002Fapp-nuevo.heroctl.com\u002Fapi\u002Fv1\u002Fusuarios -H \"Authorization: Bearer $TOKEN\"\n# Hit endpoints críticos manualmente, con ojos humanos\n",[231,21358,21359,21366,21384],{"__ignoreMap":229},[234,21360,21361,21363],{"class":236,"line":237},[234,21362,1220],{"class":247},[234,21364,21365],{"class":255}," https:\u002F\u002Fapp-nuevo.heroctl.com\u002Fhealthz\n",[234,21367,21368,21370,21373,21376,21379,21382],{"class":236,"line":244},[234,21369,1220],{"class":247},[234,21371,21372],{"class":255}," https:\u002F\u002Fapp-nuevo.heroctl.com\u002Fapi\u002Fv1\u002Fusuarios",[234,21374,21375],{"class":251}," -H",[234,21377,21378],{"class":255}," \"Authorization: Bearer ",[234,21380,21381],{"class":387},"$TOKEN",[234,21383,1207],{"class":255},[234,21385,21386],{"class":236,"line":271},[234,21387,21388],{"class":240},"# Hit endpoints críticos manualmente, con ojos humanos\n",[12,21390,21391],{},"Si algo está mal, descúbrelo ahora. Después del cutover vas a estar lidiando con tickets de soporte simultáneamente.",[12,21393,21394],{},[27,21395,21396],{},"Cutover:",[12,21398,21399,21400,21403],{},"Cambia el CNAME (o A record) del dominio de producción al destino. En hasta 60 segundos, nuevas requests van al destino nuevo. Heroku sigue respondiendo en el dominio antiguo (la URL ",[231,21401,21402],{},"*.herokuapp.com",") por 30 días — eso es cinturón de seguridad importante.",[12,21405,21406],{},[27,21407,21408],{},"SSL\u002FTLS:",[12,21410,21411],{},"Heroku tenía certificado automático embebido. En el destino, dependiendo de la elección:",[2735,21413,21414,21417],{},[70,21415,21416],{},"HeroCtl, Coolify, Render, Railway, Fly.io: certificado automático vía Let's Encrypt, sin pensar.",[70,21418,21419],{},"VPS único desnudo: configuras cert-manager-equivalente, o Caddy con ACME, o nginx + certbot.",[12,21421,21422],{},"Antes del cutover de DNS, valida que el destino emitió el certificado para el dominio. Let's Encrypt valida vía HTTP-01 o DNS-01 — el desafío HTTP-01 solo funciona después de que el DNS apunte, entonces tienes huevo-gallina. Solución: emite vía DNS-01 antes (no necesita que el DNS apunte al destino), o acepta 30 segundos de error de TLS en el momento del cutover.",[12,21424,21425],{},[27,21426,21427],{},"Sticky sessions:",[12,21429,21430],{},"Si tu app usa WebSocket, o tiene sesión en memoria (en lugar de Redis o base), necesitas sticky session en el balanceador. Heroku no hacía eso por default, pero algunas apps terminan dependiendo de ruteo estable sin percibir. En el destino, configura cookie-based session affinity si es necesario.",[19,21432,21434],{"id":21433},"paso-5-decommission-heroku-1-hora-30-dias-despues","Paso 5 — Decommission Heroku (1 hora, 30 días después)",[12,21436,21437],{},"Treinta días es el cinturón de seguridad. Mantén la app en Heroku encendida, sin tráfico (al final el DNS ya apuntó a otro lugar), solo por si acaso. Costo: lo que ya estabas pagando, dividido proporcionalmente hasta la fecha de cancelación.",[12,21439,21440],{},"Treinta días después, si nada se rompió:",[224,21442,21444],{"className":226,"code":21443,"language":228,"meta":229,"style":229},"heroku addons:destroy heroku-postgresql -a mi-app\nheroku addons:destroy heroku-redis -a mi-app\nheroku addons:destroy papertrail -a mi-app\nheroku apps:destroy mi-app\n",[231,21445,21446,21460,21473,21486],{"__ignoreMap":229},[234,21447,21448,21450,21453,21456,21458],{"class":236,"line":237},[234,21449,20512],{"class":247},[234,21451,21452],{"class":255}," addons:destroy",[234,21454,21455],{"class":255}," heroku-postgresql",[234,21457,20541],{"class":251},[234,21459,20544],{"class":255},[234,21461,21462,21464,21466,21469,21471],{"class":236,"line":244},[234,21463,20512],{"class":247},[234,21465,21452],{"class":255},[234,21467,21468],{"class":255}," heroku-redis",[234,21470,20541],{"class":251},[234,21472,20544],{"class":255},[234,21474,21475,21477,21479,21482,21484],{"class":236,"line":271},[234,21476,20512],{"class":247},[234,21478,21452],{"class":255},[234,21480,21481],{"class":255}," papertrail",[234,21483,20541],{"class":251},[234,21485,20544],{"class":255},[234,21487,21488,21490,21493],{"class":236,"line":415},[234,21489,20512],{"class":247},[234,21491,21492],{"class":255}," apps:destroy",[234,21494,20544],{"class":255},[12,21496,21497],{},"Cada addon tiene que ser cancelado separadamente — algunos tienen billing propio que sigue incluso con app destruido. Verifica la factura del mes siguiente con lupa.",[12,21499,21500],{},"Heroku hace reembolso pro-rata hasta el día de la cancelación. No olvides cancelar la cuenta entera si es la última app — sino pagas tarifa de plataforma todos los meses por nada.",[19,21502,21504],{"id":21503},"trampas-comunes","Trampas comunes",[12,21506,21507],{},"La mayor parte de las migraciones se traba en esas ocho cosas. Lee todo antes de empezar.",[12,21509,21510,21513,21514,571,21516,571,21518,21521],{},[27,21511,21512],{},"Slug compilation hooks invisibles."," Apps antiguas tienen ",[231,21515,20574],{},[231,21517,20483],{},[231,21519,21520],{},"bin\u002Fpre_compile",". Esos scripts corren dentro del buildpack y hacen cosas como minificar JS, generar archivos derivados, o correr una migración que nadie recuerda. Antes de Dockerizar, abre cada uno y replica en un step del Dockerfile o en release container.",[12,21523,21524,21527,21528,21531,21532,21534,21535,21538],{},[27,21525,21526],{},"Config vars con formato roto."," Heroku acepta ",[231,21529,21530],{},"MY:VAR"," como nombre de variable (con ",[231,21533,1272],{},"). Contenedores en general también, pero algunas herramientas de orquestación escapan diferente. Renombra a ",[231,21536,21537],{},"MY_VAR"," antes de migrar.",[12,21540,21541,21544,21545,21548,21549,21552,21553,21556],{},[27,21542,21543],{},"Redis URL con formato variante."," Heroku usa ",[231,21546,21547],{},"redis:\u002F\u002Fh:senha@host:port",". Algunos clients (gems Ruby antiguas, principalmente) esperan ",[231,21550,21551],{},"redis:\u002F\u002F:senha@host:port",". Si ves ",[231,21554,21555],{},"Redis::CommandError: WRONGPASS",", es probablemente eso.",[12,21558,21559,21564],{},[27,21560,21561,21563],{},[231,21562,20626],{}," grabado en el env."," Cuando corres ese mismo contenedor fuera de Heroku, sigue sin instalar gems de desarrollo. En producción, ok. En staging donde necesitas correr pruebas, se rompe. Limpia esa variable antes de usar el config dump en otro ambiente.",[12,21566,21567,2578,21570,21573,21574,571,21577,21580],{},[27,21568,21569],{},"Gems específicas de Heroku.",[231,21571,21572],{},"rails_12factor"," (deprecado pero aún en apps de 2014), ",[231,21575,21576],{},"heroku_san",[231,21578,21579],{},"taps",". Removiste, fin. Si algo depende, cambia por equivalente estándar.",[12,21582,21583,21586],{},[27,21584,21585],{},"DNS con Heroku-DNS-Target."," Heroku recomienda usar ALIAS o ANAME para apuntar a la app, en lugar de CNAME, para raíces de dominio. Cuando migres, cambia a A record directo a la IP del destino. ALIAS apuntando a Heroku es lo que va a fastidiarte en dominios apex.",[12,21588,21589,21592],{},[27,21590,21591],{},"Papertrail \u002F NewRelic \u002F Bugsnag desconectados sin sustituto."," Logs y observabilidad son fáciles de dejar para después y romperse en la primera hora post-migración. Antes del cutover, tiene que tener: logs centralizados (HeroCtl tiene escritor único embebido; Render expone vía UI; Coolify tiene Loki opcional), métricas básicas (CPU, memoria, requests), y alguna herramienta de errores (Sentry self-hosted o SaaS).",[12,21594,21595,21598],{},[27,21596,21597],{},"Sidekiq\u002FResque con jobs en vuelo durante cutover."," Durante el momento del cutover, algunos jobs van a la cola del destino sin haber sido procesados en el origen. Si tu job no es idempotente (puede correr dos veces sin efecto colateral), eso es problema. Solución: pausa los workers en Heroku 5 minutos antes del cutover, espera que la cola vacíe, haz cutover con cola vacía.",[19,21600,21602],{"id":21601},"cronograma-realista-para-startup-media-5-a-10-apps-heroku","Cronograma realista para startup media (5 a 10 apps Heroku)",[12,21604,21605],{},"Equipo pequeño, un dev part-time:",[2735,21607,21608,21614,21620,21626,21632],{},[70,21609,21610,21613],{},[27,21611,21612],{},"Semana 1",": pre-flight completo + elección de stack + setup del destino (cluster vacío corriendo, panel accesible).",[70,21615,21616,21619],{},[27,21617,21618],{},"Semana 2",": Dockerización del primer app de bajo riesgo + migración de base en ambiente de staging.",[70,21621,21622,21625],{},[27,21623,21624],{},"Semana 3",": cutover del primer app en producción + validación de 7 días.",[70,21627,21628,21631],{},[27,21629,21630],{},"Semanas 4 a 6",": migración de los demás apps en paralelo, ritmo de 1 a 2 por semana.",[70,21633,21634,21636],{},[27,21635,16930],{},": 4 a 6 semanas de elapsed time, tal vez 80 horas de trabajo efectivo distribuidas.",[12,21638,21639],{},"Equipo medio (3 devs, 20 apps): 8 semanas, 200 horas de trabajo efectivo.",[12,21641,21642],{},"Equipo grande (cluster de 50+ apps): trátalo como proyecto formal, con gerente de proyecto, y calcula trimestre.",[12,21644,21645],{},"La regla de bolsillo: nunca migres más de 2 apps en paralelo si es el mismo dev haciéndolo. El costo de contexto-switching engulle la ganancia de paralelismo.",[19,21647,3226],{"id":3225},[12,21649,21650,21653],{},[27,21651,21652],{},"¿Cuánto cuesta la migración en horas-hombre?","\nPara un SaaS de 5 apps, dev part-time: ~80 horas. A R$200\u002Fh, R$16k. Comparado a R$2k\u002Fmes de factura Heroku que ahorras, payback en 8 meses. En los 4 años siguientes, es solo economía.",[12,21655,21656,21659],{},[27,21657,21658],{},"¿Y si no tengo Docker setup?","\nNo necesitas pre-instalar nada — las plataformas de destino construyen la imagen por ti (Render, Railway, Fly.io aceptan Dockerfile directo del git). HeroCtl exige imagen en registry, entonces subes a ECR, GCR, Docker Hub o GHCR. Para uso local, instalas Docker Desktop y listo.",[12,21661,21662,21665,21666,21668,21669,21671,21672,21675],{},[27,21663,21664],{},"¿Heroku Postgres tiene export limit?","\nTiene límite de IOPS durante ",[231,21667,5736],{}," en planes bajos. Bases por encima de 5GB en plan Hobby pueden necesitar ",[231,21670,5736],{}," en modo paralelo (",[231,21673,21674],{},"-j",") o usar logical replication para evitar carga grande. Para Standard o superior, sin problema relevante.",[12,21677,21678,21681],{},[27,21679,21680],{},"¿Sidekiq scheduled jobs sobreviven?","\nSobreviven si migras el Redis con snapshot (BGSAVE → restore). Si reinicias Redis de cero en el destino, pierdes scheduled jobs. Considera eso en el cutover: o haces la transferencia de Redis junto, o aceptas reagendar manualmente algunos jobs.",[12,21683,21684,21687],{},[27,21685,21686],{},"¿Puedo probar con 1 app antes?","\nEse es el camino recomendado. Toma el app menos crítico (interno, o de bajísimo tráfico), haz la migración entera en él primero. Aprende con los tropiezos ahí. Después migras los de producción con confianza. La primera migración enseña más que leer 10 posts como este.",[12,21689,21690,21693],{},[27,21691,21692],{},"¿Y si la migración falla?","\nLos 30 días de Heroku corriendo en paralelo son tu red. Si el destino se rompe de forma irreversible en la primera hora, vuelve el DNS a Heroku, lleva 60 segundos, vida normal. El único caso donde rollback es caro es si hiciste cutover de base con escrituras en el destino — ahí necesitas replicar de vuelta. Por eso la recomendación es cutover de DNS y cutover de base simultáneos, con ventana corta.",[12,21695,21696,21699,21700,21703,21704,21706],{},[27,21697,21698],{},"¿Hay camino de migración asistida del HeroCtl?","\nPara HeroCtl, sí — tenemos un conversor experimental que lee ",[231,21701,21702],{},"app.json"," + ",[231,21705,20977],{}," y genera un manifiesto de job equivalente. Funciona para apps simples (web + worker + release), y tropieza en casos exóticos (multi-buildpack pesado, hooks customizados). Si quieres probar, manda mensaje.",[19,21708,3310],{"id":3309},[12,21710,21711],{},"Migrar de Heroku cuatro años después es vergonzoso — tenía que haber salido en 2022. Pero cuatro años volviéndose cinco es peor. El costo compuesto de no migrar (R$25k a R$100k por año en factura Heroku acumulada, más la fragilidad de depender de un producto que Salesforce ya mostró que no tiene cariño por usuarios pequeños) es mayor que el costo de una semana de trabajo enfocado.",[12,21713,21714],{},"Si decides probar HeroCtl, instala en cualquier servidor Linux:",[224,21716,21717],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,21718,21719],{"__ignoreMap":229},[234,21720,21721,21723,21725,21727,21729],{"class":236,"line":237},[234,21722,1220],{"class":247},[234,21724,2958],{"class":251},[234,21726,2961],{"class":255},[234,21728,2964],{"class":383},[234,21730,2967],{"class":247},[12,21732,21733],{},"Funciona en 1 servidor (modo simple) o en 3+ (modo HA real). El plan Community es gratuito sin límite de servidores y sin límite de jobs — no necesitas decidir nada comercial para hacer la migración entera.",[12,21735,21736],{},"Si decides por Render, Railway o Coolify, genial también. El punto de este post no es capturarte como cliente — es sacarte de Heroku. Cuatro años después, es hora.",[12,21738,21739,21740,21743,21744,101],{},"Para contexto adicional sobre auto-hospedaje en 2026, lee ",[3337,21741,21742],{"href":19773},"Heroku auto-hospedado: el estado del arte en 2026",". Para entender por qué construimos un orquestador nuevo en lugar de adoptar uno existente, lee ",[3337,21745,21746],{"href":6545},"Por qué creamos HeroCtl",[3351,21748,21749],{},"html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}",{"title":229,"searchDepth":244,"depth":244,"links":21751},[21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762],{"id":20423,"depth":244,"text":20424},{"id":20493,"depth":244,"text":20494},{"id":20713,"depth":244,"text":20714},{"id":20750,"depth":244,"text":20751},{"id":21081,"depth":244,"text":21082},{"id":21325,"depth":244,"text":21326},{"id":21433,"depth":244,"text":21434},{"id":21503,"depth":244,"text":21504},{"id":21601,"depth":244,"text":21602},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"2026-03-11","El fin del plan gratuito de Heroku en noviembre\u002F2022 transformó migración en prioridad para cientos de equipos. Plan detallado con checklist, tiempo estimado, y trampas comunes.",{},"\u002Fes\u002Fblog\u002Fmigrar-de-heroku-guia-tecnica",{"title":20412,"description":21764},{"loc":21766},"es\u002Fblog\u002Fmigrar-de-heroku-guia-tecnica",[20512,6393,6396,3393,6395],"fhN6dQetvGzN-ho79yJhBfLZuePnAvtSUT_LyOJNYgs",{"id":21773,"title":21774,"author":7,"body":21775,"category":8761,"cover":3380,"date":22483,"description":22484,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":22485,"navigation":411,"path":6333,"readingTime":3387,"seo":22486,"sitemap":22487,"stem":22488,"tags":22489,"__hash__":22493},"blog_es\u002Fes\u002Fblog\u002Faws-ecs-vs-kubernetes-vs-auto-hospedado.md","AWS ECS vs Kubernetes vs auto-hospedado: tres caminos para correr contenedores en 2026",{"type":9,"value":21776,"toc":22468},[21777,21780,21783,21786,21790,21793,21796,21821,21824,21827,21831,21834,21837,21843,21849,21855,21861,21867,21870,21874,21877,21891,21895,21898,21901,21915,21919,21926,21952,21956,21959,21976,21980,21983,21986,22003,22006,22010,22013,22039,22043,22046,22229,22232,22236,22239,22245,22251,22257,22263,22269,22273,22276,22345,22348,22369,22372,22375,22379,22385,22391,22397,22403,22409,22415,22421,22423,22426,22429,22432,22435,22451,22454,22463,22466],[12,21778,21779],{},"AWS hoy vende, como mínimo, cuatro productos diferentes para correr contenedor en producción: ECS (con EC2 o con Fargate), EKS, App Runner y Lightsail Containers. No es redundancia de catálogo ni confusión interna — es respuesta directa al mercado. Cada uno cubre una franja distinta de quien está llegando a AWS con la misma pregunta básica: cómo subir un contenedor, mantenerlo vivo, exponerlo a internet, actualizarlo sin que se caiga, y dormir tranquilo.",[12,21781,21782],{},"ECS es la apuesta de AWS para quien no quiere Kubernetes. No es \"Kubernetes más simple\", es una alternativa propietaria a Kubernetes, escrita por los ingenieros de Amazon antes de que K8s se volviera consenso. EKS es Kubernetes gestionado, mismo de la estantería que GKE y AKS. Auto-hospedado es la salida de AWS entera — corres en cualquier servidor Linux, pagas solo el servidor, y te llevas tus contenedores contigo si el proveedor cambia de humor.",[12,21784,21785],{},"Los tres caminos resuelven el mismo problema con tradeoffs muy diferentes. Este post pone lado a lado lo que cada uno cobra, lo que cada uno amarra, y en qué contexto cada uno tiene sentido — sin fingir que existe un ganador uniforme.",[19,21787,21789],{"id":21788},"aws-ecs-que-es-exactamente","AWS ECS: qué es exactamente",[12,21791,21792],{},"ECS es el orquestador propietario de Amazon. No es open-source, no corre fuera de AWS, no tiene implementación alternativa. Fue anunciado en 2014, antes de que Kubernetes ganara tracción, y desde entonces AWS invierte en él como la puerta de entrada \"AWS-nativa, sin K8s\" al mundo de contenedores.",[12,21794,21795],{},"El modelo conceptual es propio:",[2735,21797,21798,21804,21810,21815],{},[70,21799,21800,21803],{},[27,21801,21802],{},"Task definition"," en lugar de Pod. Es un archivo JSON describiendo el contenedor, recursos, puertos, variables de entorno, IAM role.",[70,21805,21806,21809],{},[27,21807,21808],{},"Service"," en lugar de Deployment. Mantiene N tasks corriendo, hace health check, integra con Application Load Balancer.",[70,21811,21812,21814],{},[27,21813,6873],{}," es solo un agrupamiento lógico — sin plano de control pagado. El control plane es gratuito (AWS lo gestiona internamente, no lo ves ni lo mantienes).",[70,21816,21817,21820],{},[27,21818,21819],{},"Capacity provider"," define dónde las tasks corren: EC2 (gestionas instancias) o Fargate (serverless por vCPU\u002FRAM\u002Fsegundo).",[12,21822,21823],{},"La integración con el resto de AWS es el punto fuerte real. Task toma IAM role directo, sin sidecar de auth. Logs van a CloudWatch sin agente. Imágenes vienen de ECR sin configurar pull secret. ALB enruta tráfico a las tasks con service discovery automático. Todo eso con consola gráfica decente, CLI estable, y SDK en todos los lenguajes.",[12,21825,21826],{},"Comparado a K8s, ECS es deliberadamente simple. No tiene CRDs, no tiene operators, no tiene Helm charts, no tiene sidecar pattern formalizado, no tiene control de admisión. Tienes task, service, cluster — y se acabó. Para un equipo ya inmerso en AWS, esa simplicidad es el argumento.",[19,21828,21830],{"id":21829},"aws-ecs-donde-duele","AWS ECS: dónde duele",[12,21832,21833],{},"El lock-in es absoluto, y vale la pena nombrar eso primero. Task definition no corre fuera de AWS. ECR no es registry portable (hasta puedes tirar, pero la IAM amarra de vuelta). ALB es AWS-only. Service discovery vía Cloud Map es AWS-only. CloudWatch es AWS-only. No estás adoptando \"una forma de correr contenedores\" — estás adoptando una stack entera que solo existe ahí dentro. Migrar hacia afuera exige reescribir cada pieza.",[12,21835,21836],{},"El coste aparece en capas que nadie suma en la primera evaluación:",[12,21838,21839,21842],{},[27,21840,21841],{},"Fargate",": US$0.04 por vCPU-hora + US$0.0044 por GB-hora. Una app modesta con 0.5 vCPU + 1 GB, corriendo 24×7, cuesta US$25\u002Fmes. Parece poco hasta que recuerdas que cada microservicio es una task, y que la producción típica tiene 8 a 15 microservicios + tasks de cola + cron jobs. Cinco aplicaciones pequeñas se vuelven tranquilo US$120 solo de Fargate.",[12,21844,21845,21848],{},[27,21846,21847],{},"CloudWatch Logs",": US$0.50 por GB ingerido + US$0.03 por GB almacenado por mes. Una app que loga 5 GB\u002Fmes deja US$2.65. Multiplicado por diez servicios, US$26\u002Fmes solo de log. Y es la opción \"barata\" — si activas Insights para hacer queries serias, dobla.",[12,21850,21851,21854],{},[27,21852,21853],{},"Egress",": US$0.09 por GB después de los primeros 100 GB gratis. Una app sirviendo 500 GB de tráfico de salida por mes paga US$36. Streaming de vídeo, descargas de imagen, API pública pesada: el egress se vuelve el item mayor de la factura, frecuentemente pasando del compute.",[12,21856,21857,21860],{},[27,21858,21859],{},"Red",": VPC es gratuita, pero NAT Gateway cuesta US$0.045\u002Fhora — US$32\u002Fmes fijo — solo para existir, más US$0.045 por GB procesado. Necesitas NAT para cualquier task en subnet privada que llame internet (actualizar paquete, hablar con API externa, mandar email vía SES). En producción con alta disponibilidad, la recomendación es NAT en dos zonas — dos NAT Gateways, US$64\u002Fmes baseline antes de cualquier tráfico.",[12,21862,21863,21866],{},[27,21864,21865],{},"Application Load Balancer",": US$0.0225\u002Fhora (US$16\u002Fmes fijo) + US$0.008 por LCU-hora. Para una app con tráfico moderado, US$25\u002Fmes es realista.",[12,21868,21869],{},"Suma realista para una operación pequeña con cinco apps en Fargate, ALB compartido, NAT en una zona sola, logs moderados: US$200 a US$300\u002Fmes. Crece linear con el número de tasks. No es caro para los estándares enterprise, pero es múltiplas veces el coste equivalente en VPS dedicado.",[19,21871,21873],{"id":21872},"aws-ecs-quien-lo-usa-y-ama-con-razon","AWS ECS: quién lo usa y ama con razón",[12,21875,21876],{},"Existe un perfil claro para quien ECS es la respuesta correcta, y lo recomendamos sin reservas para esos casos:",[2735,21878,21879,21882,21885,21888],{},[70,21880,21881],{},"Empresa que ya es 100% AWS, con equipo entrenado en la consola y en las IAM policies. Añadir ECS es incremental — no requiere aprender herramienta nueva fuera de la burbuja.",[70,21883,21884],{},"Workloads de burst, scheduled jobs, ETLs nocturnos. Fargate brilla cuando quieres 50 tasks corriendo por 12 minutos al día y cero el resto del tiempo. Pagar por segundo es honesto.",[70,21886,21887],{},"Cumplimiento que exige AWS específica (FedRAMP High, contratos federales americanos, ciertas configuraciones HIPAA con BAA AWS). Cuando la auditoría pide AWS, ECS te entrega el camino más corto sin instalar K8s encima.",[70,21889,21890],{},"Equipo que prioriza zero-ops sobre coste y portabilidad. Si no tienes a nadie para mantener una instancia EC2, Fargate es genuinamente menos trabajo — nunca ves una máquina, nunca parcheas kernel, nunca apareces para hablar de saturación de disco.",[19,21892,21894],{"id":21893},"kubernetes-que-es-exactamente","Kubernetes: qué es exactamente",[12,21896,21897],{},"La audiencia conoce K8s, así que el resumen aquí es corto. Estándar de hecho para orquestación desde alrededor de 2018, con ecosistema CNCF gigante (cert-manager, ingress controllers, operators para prácticamente cualquier base). API consistente entre clouds, lo que vuelve multi-cloud genuinamente viable (caro, pero viable). Curva de aprendizaje bien documentada — 300+ líneas de manifiesto para colocar un hello world con TLS al aire.",[12,21899,21900],{},"Modelos de operación:",[2735,21902,21903,21909],{},[70,21904,21905,21908],{},[27,21906,21907],{},"Gestionado"," (EKS, GKE, AKS): proveedor mantiene el plano de control. Cobra cerca de US$73\u002Fmes por cluster en las tres grandes. Más NAT, ALB, observabilidad, registry. Equipo típico mínimo: 2 SREs.",[70,21910,21911,21914],{},[27,21912,21913],{},"Self-managed"," con k3s, kubeadm, kops, Rancher: instalas en VMs o bare metal. Sin coste de plano de control, pero te vuelves el equipo de plataforma. Equipo mínimo: 1 SRE muy bueno o 2 medianos.",[19,21916,21918],{"id":21917},"kubernetes-donde-duele","Kubernetes: dónde duele",[12,21920,21921,21922,21925],{},"Ya cubrimos a fondo en ",[3337,21923,21924],{"href":15790},"Kubernetes es overkill: cuando no lo necesitas",". Resumen directo:",[2735,21927,21928,21934,21940,21946],{},[70,21929,21930,21933],{},[27,21931,21932],{},"Coste operacional",": 1 a 2 SREs dedicados, US$5-8k\u002Fmes cada uno. Ese es el item mayor de la cuenta — multiplica por doce meses y el cluster pasó la casa de US$100k\u002Faño solo en personas.",[70,21935,21936,21939],{},[27,21937,21938],{},"Curva",": 6+ meses para un equipo productivo de hecho (no \"entrega manifiesto\", y sí \"depura problema a las tres de la mañana sin destruir producción\").",[70,21941,21942,21945],{},[27,21943,21944],{},"Stack alrededor",": cert-manager, ingress controller, operador de métricas, agente de logs, malla de servicios si la hay — cada uno con versión propia, política de actualización propia, modelo de fallo propio.",[70,21947,21948,21951],{},[27,21949,21950],{},"Manifiestos largos",": \"hello world\" con namespace + deployment + service + ingress + cert + RBAC queda en 300 líneas. Helm reduce duplicación pero añade una capa conceptual.",[19,21953,21955],{"id":21954},"kubernetes-quien-lo-usa-y-lo-justifica","Kubernetes: quién lo usa y lo justifica",[12,21957,21958],{},"Los perfiles en que K8s es la elección obvia, sin ironía:",[2735,21960,21961,21964,21967,21970,21973],{},[70,21962,21963],{},"Empresa Series B+ con equipo de plataforma de 3 o más personas dedicadas. La escala humana sostiene la complejidad.",[70,21965,21966],{},"Multi-cloud o neutralidad de proveedor como requisito real (no como aspiración de slide). Vas efectivamente a correr en dos clouds, y K8s es la única abstracción madura que cubre las dos.",[70,21968,21969],{},"Workloads que dependen de operadores específicos maduros: operador de Postgres con replicación, operador de Kafka con balanceo, operador de Cassandra con bootstrap. Reescribir eso \"a mano\" cuesta más que el cluster.",[70,21971,21972],{},"Cumplimiento nominal — algunos frameworks listan Kubernetes por nombre en controles. Si tu auditor necesita apuntar a un certificado SOC2 que dice \"Kubernetes 1.28\", la herramienta tiene que llamarse Kubernetes.",[70,21974,21975],{},"Operación por encima de 50 servidores en producción sostenida. En ese tamaño, el ecosistema CNCF te da herramientas que tendrías que construir desde cero en alternativas menores.",[19,21977,21979],{"id":21978},"auto-hospedado-moderno","Auto-hospedado moderno",[12,21981,21982],{},"La tercera opción es lo que cambió en los últimos dos años. Auto-hospedado dejó de ser \"Docker Compose en un servidor con suerte\" y se volvió una categoría con productos serios — HeroCtl es uno de ellos, pero Coolify, Dokploy, Caprover y otros también ocupan el espacio.",[12,21984,21985],{},"La propuesta común:",[2735,21987,21988,21991,21994,21997,22000],{},[70,21989,21990],{},"Un binario (o imagen Docker simple) instalado en N servidores Linux con Docker.",[70,21992,21993],{},"Plano de control replicado, con elección automática de coordinador. Pierdes un servidor, el cluster sigue.",[70,21995,21996],{},"Router embebido, certificados Let's Encrypt automáticos.",[70,21998,21999],{},"Sin dependencia de proveedor cloud — corre en cualquier VPS, cualquier bare metal, cualquier mezcla.",[70,22001,22002],{},"Modelo comercial honesto: Community gratuito permanente sin feature gate artificial, Business pagado publicado para quien necesita SSO\u002Fauditoría\u002FSLA, Enterprise para contratos con escrow y soporte 24×7.",[12,22004,22005],{},"El coste se reduce a dos líneas: las VPS y el tiempo del dev part-time que cuida de eso. Tres droplets de US$24\u002Fmes cada uno en DigitalOcean — US$72\u002Fmes — sostienen una operación que en ECS quedaría entre US$300 y US$600.",[19,22007,22009],{"id":22008},"auto-hospedado-donde-duele","Auto-hospedado: dónde duele",[12,22011,22012],{},"Honestidad vale más que folleto. Donde auto-hospedado no es la respuesta:",[2735,22014,22015,22021,22027,22033],{},[70,22016,22017,22020],{},[27,22018,22019],{},"Eres responsable de todo",". Sin soporte AWS para llamar cuando se complique. Comunidad activa ayuda, y el soporte pagado Business existe — pero la primera línea de defensa eres tú leyendo el log.",[70,22022,22023,22026],{},[27,22024,22025],{},"Franja de escala saludable: 1 a 500 servidores",". Por encima de eso, herramental específico de Kubernetes aún gana. No es defecto del producto — es donde la CNCF gastó diez años puliendo cosas que nadie más tiene.",[70,22028,22029,22032],{},[27,22030,22031],{},"Cumplimiento enterprise específico",". Si tu auditor necesita que el orquestador aparezca en una lista pre-aprobada de proveedores, y esa lista lista AWS\u002FAzure\u002FGCP\u002FK8s, auto-hospedado nuevo te excluye por defecto.",[70,22034,22035,22038],{},[27,22036,22037],{},"Integraciones nativas AWS",": Cognito como auth, S3 con IAM directo en la task, RDS con IAM auth — todo eso se puede adaptar, pero la adaptación es trabajo extra. En ECS funciona sin pensar.",[19,22040,22042],{"id":22041},"lado-a-lado-doce-criterios-sin-matiz","Lado a lado: doce criterios sin matiz",[12,22044,22045],{},"La tabla abajo es la versión honesta de la decisión.",[119,22047,22048,22063],{},[122,22049,22050],{},[125,22051,22052,22054,22057,22060],{},[128,22053,2983],{},[128,22055,22056],{},"AWS ECS (Fargate)",[128,22058,22059],{},"Kubernetes (EKS)",[128,22061,22062],{},"Auto-hospedado",[141,22064,22065,22079,22093,22107,22120,22133,22147,22160,22173,22187,22201,22215],{},[125,22066,22067,22070,22073,22076],{},[146,22068,22069],{},"Coste mínimo USD\u002Fmes — 5 apps pequeñas",[146,22071,22072],{},"US$200-300",[146,22074,22075],{},"US$300-500 + equipo SRE",[146,22077,22078],{},"US$60-100 + dev part-time",[125,22080,22081,22084,22087,22090],{},[146,22082,22083],{},"Coste previsible mes a mes",[146,22085,22086],{},"No — egress + log varían",[146,22088,22089],{},"No — suma de muchas líneas",[146,22091,22092],{},"Sí — VPS es fija",[125,22094,22095,22098,22101,22104],{},[146,22096,22097],{},"Lock-in (0-10)",[146,22099,22100],{},"10 — task def es AWS-only",[146,22102,22103],{},"4 — manifiestos portables con matices",[146,22105,22106],{},"1 — VPS Linux cualquiera",[125,22108,22109,22111,22114,22117],{},[146,22110,16321],{},[146,22112,22113],{},"2-4 horas (con IAM bien)",[146,22115,22116],{},"1-3 días",[146,22118,22119],{},"15-30 minutos",[125,22121,22122,22124,22127,22130],{},[146,22123,3152],{},[146,22125,22126],{},"Media (conceptos propios + AWS)",[146,22128,22129],{},"Alta (6+ meses para productividad real)",[146,22131,22132],{},"Baja (modelo Heroku)",[125,22134,22135,22138,22141,22144],{},[146,22136,22137],{},"Ecosistema de operadores",[146,22139,22140],{},"Restringido al catálogo AWS",[146,22142,22143],{},"Cientos, maduros",[146,22145,22146],{},"Limitado, en crecimiento",[125,22148,22149,22151,22154,22157],{},[146,22150,7104],{},[146,22152,22153],{},"Nativo (AWS regions)",[146,22155,22156],{},"Nativo vía federación",[146,22158,22159],{},"Manual, con cuidado",[125,22161,22162,22165,22168,22170],{},[146,22163,22164],{},"Soporte 24\u002F7",[146,22166,22167],{},"Pagado aparte (Business+)",[146,22169,22167],{},[146,22171,22172],{},"Pagado Enterprise",[125,22174,22175,22178,22181,22184],{},[146,22176,22177],{},"Cumplimiento enterprise nominal",[146,22179,22180],{},"Fuerte (FedRAMP, HIPAA)",[146,22182,22183],{},"Fuerte (listado nominalmente)",[146,22185,22186],{},"En construcción",[125,22188,22189,22192,22195,22198],{},[146,22190,22191],{},"Franja ideal de escala",[146,22193,22194],{},"1-200 tasks",[146,22196,22197],{},"50-100.000 servidores",[146,22199,22200],{},"1-500 servidores",[125,22202,22203,22206,22209,22212],{},[146,22204,22205],{},"Equipo mínimo",[146,22207,22208],{},"1 dev + un lector de docs AWS",[146,22210,22211],{},"2 SREs",[146,22213,22214],{},"1 dev part-time",[125,22216,22217,22220,22223,22226],{},[146,22218,22219],{},"Dolor de migración (salir)",[146,22221,22222],{},"Alto — reescribir stack",[146,22224,22225],{},"Bajo — manifiestos son portables",[146,22227,22228],{},"Mínimo — Docker es Docker",[12,22230,22231],{},"La columna que importa varía por contexto, y es exactamente ese el punto: no existe ganador uniforme.",[19,22233,22235],{"id":22234},"decision-por-contexto","Decisión por contexto",[12,22237,22238],{},"Traducción práctica de las tablas en recomendación directa. Si tu escenario cae en uno de esos cinco, la respuesta es la indicada — sin floritura.",[12,22240,22241,22244],{},[27,22242,22243],{},"\"Ya estamos en AWS, equipo pequeño, contratos exigen AWS.\"","\nECS Fargate. El lock-in ya es hecho consumado, y Fargate elimina el trabajo de gestionar instancia. Cambias coste previsible por zero-ops, que es el tradeoff correcto cuando el equipo tiene pocos brazos y no puede parar para parchear kernel.",[12,22246,22247,22250],{},[27,22248,22249],{},"\"Multi-cloud strategy o cumplimiento exige neutralidad entre proveedores.\"","\nKubernetes. Si el equipo es fuerte, k3s self-managed en VMs reduce drásticamente el coste del plano de control. Si el equipo es mediano, EKS gestionado en una cloud principal y equivalente en la otra. No pagues el coste de K8s sin el requisito real — el requisito real existe y la herramienta encaja.",[12,22252,22253,22256],{},[27,22254,22255],{},"\"Startup early stage, costes duelen, equipo no es especialista AWS.\"","\nAuto-hospedado. HeroCtl, Coolify, Dokploy — el segmento maduró. Tres droplets, un dev part-time, US$80\u002Fmes de infra, y te quedas con la operación entera bajo control. Cuando el producto gane tracción y la empresa quede grande, se puede reevaluar — pero llegar hasta ahí costando US$80\u002Fmes es la diferencia entre cerrar runway y no cerrar.",[12,22258,22259,22262],{},[27,22260,22261],{},"\"Big enterprise, cumplimiento lista K8s nominalmente, equipo de plataforma con 5+ personas.\"","\nEKS gestionado. El coste del plano de control desaparece en el presupuesto, el equipo absorbe la complejidad, y la auditoría queda satisfecha. Ese es el caso canónico de K8s — no intentes ahorrar aquí.",[12,22264,22265,22268],{},[27,22266,22267],{},"\"Solo dev experimentando, side project, MVP.\"","\nRender o Railway en la nube hospedada (paga solo lo que usa, cero ops), o Coolify en un VPS de US$5. No montes cluster para un proyecto que puede morir en tres meses. Cuando pase de US$1k MRR y quede claro que va a sobrevivir, migra a HeroCtl o Dokploy en un cluster de tres VPS.",[19,22270,22272],{"id":22271},"migrar-de-ecs-al-auto-hospedado-camino-practico","Migrar de ECS al auto-hospedado: camino práctico",[12,22274,22275],{},"Para quien ya está en ECS y quiere reducir cuenta, el mapeo conceptual es más simple de lo que parece. Las primitivas baten casi uno-a-uno:",[119,22277,22278,22287],{},[122,22279,22280],{},[125,22281,22282,22285],{},[128,22283,22284],{},"ECS",[128,22286,2995],{},[141,22288,22289,22296,22303,22309,22316,22323,22330,22337],{},[125,22290,22291,22293],{},[146,22292,21802],{},[146,22294,22295],{},"Job spec",[125,22297,22298,22300],{},[146,22299,21808],{},[146,22301,22302],{},"Group dentro del job",[125,22304,22305,22307],{},[146,22306,6873],{},[146,22308,6873],{},[125,22310,22311,22313],{},[146,22312,21841],{},[146,22314,22315],{},"Servidor dedicado (VPS o bare metal)",[125,22317,22318,22320],{},[146,22319,5601],{},[146,22321,22322],{},"Router integrado, con TLS automático",[125,22324,22325,22327],{},[146,22326,21847],{},[146,22328,22329],{},"Escritor único embebido",[125,22331,22332,22335],{},[146,22333,22334],{},"IAM role de la task",[146,22336,5677],{},[125,22338,22339,22342],{},[146,22340,22341],{},"ECR",[146,22343,22344],{},"ECR sigue funcionando, o registry interno",[12,22346,22347],{},"Camino práctico para una app simple:",[67,22349,22350,22357,22360,22363,22366],{},[70,22351,22352,22353,22356],{},"Levanta tres VPS Linux con Docker. Instala el orquestador en uno de los tres (",[231,22354,22355],{},"curl -sSL get.heroctl.com\u002Finstall.sh | sh","). Los otros dos entran como agentes — comando único para cada uno.",[70,22358,22359],{},"Toma la task definition en JSON. Mapea: contenedor, recursos, puertos, variables de entorno, secretos. Se vuelve un archivo de configuración de ~50 líneas.",[70,22361,22362],{},"Envía vía CLI. El cluster decide dónde correr, abre puerto, registra en el router, emite certificado Let's Encrypt, empieza a servir.",[70,22364,22365],{},"Apunta el DNS del dominio al IP del servidor coordinador (o a un Load Balancer DNS-based si tiene más de una región).",[70,22367,22368],{},"Prueba en staging por una semana. Si está ok, repite para producción y descomisiona ECS.",[12,22370,22371],{},"Tiempo medio por app simple: 1 a 3 horas, incluyendo el test. Apps con dependencia fuerte de IAM\u002FCognito\u002FSQS toman más — necesitas adaptar la llamada AWS para que vaya vía SDK + clave (en lugar de IAM role implícito). Apps stateless de HTTP son casi mecánicas.",[12,22373,22374],{},"Ahorro anual típico en scale-up modesto (15 microservicios, 1 ALB, NAT en una zona, logs moderados): US$10.000 a US$30.000 que salen de la factura AWS y se vuelven salario o marketing. El componente humano también cambia — dejas de necesitar un especialista AWS dedicado.",[19,22376,22378],{"id":22377},"preguntas-que-aparecen","Preguntas que aparecen",[12,22380,22381,22384],{},[27,22382,22383],{},"¿Puedo usar ECS Fargate sin ALB para ahorrar?","\nTécnicamente sí, exponiendo la task con IP público — pero pierdes TLS automático, balanceo de carga, health check en capa 7, y service discovery. Para producción real eso no es un ahorro, es deuda. Vale solo para workloads internos sin ingress (jobs de cola, ETLs).",[12,22386,22387,22390],{},[27,22388,22389],{},"¿EKS Anywhere es viable fuera de AWS?","\nExiste y funciona, pero el coste de licencia es caro y la integración con el ecosistema AWS es parcial — ganas el nombre \"EKS\" sin ganar la integración nativa. Para correr K8s fuera de AWS, k3s o kubeadm tienen mejor relación coste\u002Fbeneficio en la práctica.",[12,22392,22393,22396],{},[27,22394,22395],{},"¿Migrar de ECS a auto-hospedado, cuánto tarda en lo realista?","\nApps simples: 1-3 horas cada una. Operación entera con 10-15 servicios: 2 a 4 semanas si lo vas a hacer con cuidado, con tests en staging. El cuello de botella suele ser las dependencias de servicios AWS-específicos (SQS, SNS, Cognito), no el orquestador en sí.",[12,22398,22399,22402],{},[27,22400,22401],{},"¿Mantener los dos (ECS + auto-hospedado en paralelo) tiene sentido?","\nTiene, durante la migración y a veces permanente. Workloads que dependen fuertemente de IAM nativo (acceso directo a S3 sin claves, por ejemplo) pueden quedarse en ECS. El resto va al cluster auto-hospedado. Enrutamiento por DNS resuelve la división de tráfico.",[12,22404,22405,22408],{},[27,22406,22407],{},"¿Cumplimiento que exige AWS, puedo usar HeroCtl en EC2?","\nPuedes. HeroCtl corre en cualquier VPS Linux con Docker — incluyendo instancias EC2. Pierdes la ventaja de portabilidad total, pero mantienes el modelo operacional simple y el coste previsible. Es una buena opción para equipos que necesitan quedarse dentro de AWS por contrato pero quieren huir de la complejidad nativa.",[12,22410,22411,22414],{},[27,22412,22413],{},"¿ECS App Runner es alternativa buena?","\nApp Runner es la oferta de AWS para \"Heroku encima de ECS\". Funciona para apps muy simples (una imagen, un puerto, build automático del Git). Cobra más que Fargate equivalente y tiene menos control. Para MVP de fin de semana, es razonable. Para producción seria, ECS directo con Fargate da más flexibilidad por el mismo dinero.",[12,22416,22417,22420],{},[27,22418,22419],{},"¿GKE Autopilot vs Fargate vs HeroCtl?","\nGKE Autopilot y Fargate ocupan el mismo nicho conceptual: serverless por pod\u002Ftask, no ves el nodo. GKE Autopilot es generalmente más barato para workloads estables, y más caro para burst. Ambos tienen lock-in fuerte. HeroCtl ataca el problema por otro lado — ves el servidor a propósito, lo pagas entero, y el orquestador distribuye las cargas. Para workload estable de larga duración, sale más barato. Para workload de burst extremo, serverless gana.",[19,22422,3310],{"id":3309},[12,22424,22425],{},"No existe un camino que gane en los doce criterios de la tabla. ECS gana en integración AWS, pierde en portabilidad. Kubernetes gana en ecosistema, pierde en simplicidad. Auto-hospedado gana en coste y claridad, pierde en herramental específico de escala extrema.",[12,22427,22428],{},"La elección correcta depende de tu equipo, de tu cumplimiento, de tus contratos, y de la etapa de la empresa. La elección equivocada es no hacer la cuenta — adoptar ECS porque \"es el estándar AWS\" sin sumar Fargate + ALB + NAT + CloudWatch + egress; adoptar Kubernetes porque \"es lo que está de moda\" sin tener los 2 SREs; o quedarse en auto-hospedado casero frágil cuando la operación ya pasó de 50 servidores y el ecosistema CNCF pasó a justificar.",[12,22430,22431],{},"Si estás revisando la stack de orquestación de contenedores en 2026, la recomendación práctica es simple: mide el coste real de los doce meses anteriores, identifica en cuál de los cinco perfiles tu equipo encaja, y decide. Si el perfil es \"startup early, equipo pequeño, coste duele\", el camino de menor riesgo es experimentar auto-hospedado en paralelo durante un mes, antes de migrar.",[12,22433,22434],{},"Para empezar:",[224,22436,22437],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,22438,22439],{"__ignoreMap":229},[234,22440,22441,22443,22445,22447,22449],{"class":236,"line":237},[234,22442,1220],{"class":247},[234,22444,2958],{"class":251},[234,22446,5329],{"class":255},[234,22448,2964],{"class":383},[234,22450,2967],{"class":247},[12,22452,22453],{},"Tres VPS Linux, diez minutos por servidor, y tienes cluster con plano de control replicado, router integrado, certificados automáticos. A partir de ahí, es cuestión de mover servicio por servicio de la factura AWS al cluster propio.",[12,22455,22456,22457,22459,22460,22462],{},"Lecturas relacionadas: ",[3337,22458,21924],{"href":15790}," explica con más detalle cuándo el coloso no encaja; ",[3337,22461,20372],{"href":5343}," compara las dos alternativas livianas dentro de la categoría auto-hospedado.",[12,22464,22465],{},"Orquestación de contenedores es una decisión de largo plazo. Hazla por la cuenta correcta, no por la inercia.",[3351,22467,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":22469},[22470,22471,22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482],{"id":21788,"depth":244,"text":21789},{"id":21829,"depth":244,"text":21830},{"id":21872,"depth":244,"text":21873},{"id":21893,"depth":244,"text":21894},{"id":21917,"depth":244,"text":21918},{"id":21954,"depth":244,"text":21955},{"id":21978,"depth":244,"text":21979},{"id":22008,"depth":244,"text":22009},{"id":22041,"depth":244,"text":22042},{"id":22234,"depth":244,"text":22235},{"id":22271,"depth":244,"text":22272},{"id":22377,"depth":244,"text":22378},{"id":3309,"depth":244,"text":3310},"2026-03-04","ECS es la oferta de AWS para huir de Kubernetes. Kubernetes es Kubernetes. Auto-hospedado es el camino de salida de AWS. Cada uno tiene sentido en contextos específicos — sin trade-off uniforme.",{},{"title":21774,"description":22484},{"loc":6333},"es\u002Fblog\u002Faws-ecs-vs-kubernetes-vs-auto-hospedado",[6392,22490,20406,22491,14948,22492],"ecs","fargate","auto-hospedado","Yi3jv7ZW-unMexiGj-aUqzpu6JejZZPYkBFbdXPrrTs",{"id":22495,"title":22496,"author":7,"body":22497,"category":8761,"cover":3380,"date":23037,"description":23038,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":23039,"navigation":411,"path":5343,"readingTime":8766,"seo":23040,"sitemap":23041,"stem":23042,"tags":23043,"__hash__":23046},"blog_es\u002Fes\u002Fblog\u002Fk3s-vs-heroctl-cuando-cada-uno-tiene-sentido.md","k3s vs HeroCtl: cuándo necesitas Kubernetes ligero y cuándo no necesitas Kubernetes",{"type":9,"value":22498,"toc":23023},[22499,22510,22513,22517,22524,22531,22534,22541,22545,22556,22570,22573,22577,22580,22586,22592,22598,22604,22610,22614,22621,22624,22627,22630,22634,22640,22646,22652,22658,22664,22668,22674,22680,22686,22692,22698,22700,22703,22846,22849,22853,22856,22862,22868,22874,22880,22886,22890,22893,22899,22905,22911,22914,22916,22919,22925,22931,22934,22937,22939,22945,22951,22957,22963,22969,22975,22981,22985,22991,22994,22997,23000,23005,23008,23020],[12,22500,22501,22502,22505,22506,22509],{},"La pregunta llega casi semanalmente a nuestra bandeja de entrada: \"¿ustedes son tipo un k3s, no?\". La respuesta corta es no. La respuesta larga empieza percibiendo que k3s y HeroCtl se confunden porque ocupan el mismo espacio mental — \"orquestación sin la complejidad de Kubernetes pleno\" — pero resuelven problemas que solo parecen iguales por fuera. k3s ",[27,22503,22504],{},"es"," Kubernetes, destilado. HeroCtl ",[27,22507,22508],{},"no es"," Kubernetes, y esa diferencia cambia todo lo que viene después: lo que lees, lo que instalas, a quién contratas, qué celebras los sábados.",[12,22511,22512],{},"Este post es para tech leads que conocen K8s lo suficiente para tener cicatrices y están considerando alguna alternativa más ligera. La intención no es convencer a nadie de abandonar Kubernetes — Kubernetes es la elección correcta para muchos casos. La intención es dar el mapa para que decidas entre k3s y HeroCtl sin mezclar las premisas de los dos.",[19,22514,22516],{"id":22515},"que-es-k3s-exactamente","Qué es k3s, exactamente",[12,22518,22519,22520,22523],{},"k3s es una distribución de Kubernetes mantenida por Rancher (hoy SUSE). Es ",[27,22521,22522],{},"Kubernetes pleno y certificado por la CNCF"," — la misma API, los mismos controladores, el mismo modelo de objeto. Lo que cambia es el empaquetado.",[12,22525,22526,22527,22530],{},"En lugar de cinco a siete componentes separados corriendo como servicios de sistema, k3s entrega un único binario de cerca de 50 MB que sube API server, scheduler, controller manager, kubelet y container runtime en un único árbol de procesos. El almacenamiento por defecto es SQLite en lugar de la base distribuida tradicional de Kubernetes — puedes cambiar a la base distribuida cuando quieras HA real, o usar un cluster externo de base SQL vía driver ",[231,22528,22529],{},"kine",". Los plugins de proveedor de nube fueron removidos del binario — si los necesitas, los instalas aparte.",[12,22532,22533],{},"La instalación cabe en un comando, sube en menos de 30 segundos en un servidor modesto, y el requisito mínimo de RAM es 512 MB. Funciona en Raspberry Pi. Funciona en una VPS de 5 dólares. Funciona en hardware industrial sin ventilador corriendo dentro de una caja de acero en una fábrica.",[12,22535,22536,22537,22540],{},"El punto más importante: ",[27,22538,22539],{},"kubectl, manifiestos K8s, operators, charts de templating y todo lo demás que aprendiste sobre Kubernetes funcionan idénticos",". Un cluster k3s acepta los mismos archivos YAML que un cluster gestionado de AWS acepta. La migración de uno al otro es, en la práctica, copiar manifiestos. La compatibilidad es la feature.",[19,22542,22544],{"id":22543},"que-k3s-no-hace-aun-siendo-ligero","Qué k3s NO hace, aun siendo \"ligero\"",[12,22546,22547,22548,22551,22552,22555],{},"La palabra \"ligero\" engaña. k3s es ligero en ",[27,22549,22550],{},"footprint"," (RAM, disco, número de procesos), no en ",[27,22553,22554],{},"modelo mental",". Lo que quita es la barrera de instalación y la dependencia de cinco servicios externos para subir. Lo que mantiene es todo lo que vuelve a Kubernetes Kubernetes:",[2735,22557,22558,22561,22564,22567],{},[70,22559,22560],{},"Manifiesto de \"hello world\" sigue pasando de las 100 líneas cuando agregas Service, Ingress y ConfigMap. Agregando TLS automático y RBAC mínimo, va a 300+.",[70,22562,22563],{},"Sigues necesitando entender namespaces, services, ingress, persistent volumes, secrets, configmaps, RBAC, network policies, pod disruption budgets, liveness\u002Freadiness probes, init containers, sidecars, taints, tolerations, affinity rules, y así sucesivamente.",[70,22565,22566],{},"Operators y charts de templating siguen siendo el camino idiomático para cualquier cosa no trivial. ¿Postgres replicado? Operator. ¿Kafka? Operator. ¿Certificados automáticos? Operator. ¿Métricas? Stack de tres productos.",[70,22568,22569],{},"La curva de aprendizaje es prácticamente la misma. k3s quita tal vez 10% — el pedazo de \"instalar y mantener el plano de control\". El 90% restante — entender cómo el sistema modela aplicaciones, cómo los controladores reconcilian estado, cómo depurar cuando una probe empieza a fallar — sigue ahí, intacto.",[12,22571,22572],{},"Si un SRE veterano mira un manifiesto k3s, se siente en casa. Si un desarrollador de producto que nunca tocó Kubernetes mira ese mismo manifiesto, se siente exactamente tan perdido como si estuviera mirando un manifiesto de cluster gestionado.",[19,22574,22576],{"id":22575},"quien-debe-usar-k3s-perfil-real","Quién debe usar k3s (perfil real)",[12,22578,22579],{},"Vamos a ser concretos. k3s tiene sentido para:",[12,22581,22582,22585],{},[27,22583,22584],{},"Equipos que ya hablan Kubernetes fluidamente y quieren correr en hardware barato."," Edge computing, IoT, tiendas físicas con servidor local, fábricas con gateways industriales, ambientes on-prem con hardware modesto. El equipo ya sabe operar K8s — k3s solo permite llevar esa expertise a lugares donde un plano de control de 4 GB de RAM sería inviable.",[12,22587,22588,22591],{},[27,22589,22590],{},"Empresa migrando de Kubernetes gestionado a self-managed para reducir costo."," Cluster gestionado en proveedor de nube cobra cerca de US$73\u002Fmes solo por el plano de control, multiplicado por el número de clusters. Suma NAT, balanceadores de carga, observabilidad — sale caro. Quien ya pagó ese peaje y quiere parar puede subir k3s en VPS comunes y cortar la cuenta en orden de magnitud. La operación no se vuelve más simple; la factura se vuelve menor.",[12,22593,22594,22597],{},[27,22595,22596],{},"Workloads que dependen del ecosistema CNCF."," Operators maduros para Postgres con replicación automática (CloudNativePG, Zalando), Kafka (Strimzi), Cassandra, Elasticsearch — esos operators existen porque alguien invirtió tres años puliendo. Si tu arquitectura depende de cuatro de ellos en producción, quieres Kubernetes pleno, y k3s te da Kubernetes pleno.",[12,22599,22600,22603],{},[27,22601,22602],{},"Quien quiere herramientas K8s-compatibles funcionando 1:1."," kubectl, charts de templating, ArgoCD para GitOps, herramientas de scanning de imagen, herramientas de policy como OPA Gatekeeper. Si tu pipeline de CI\u002FCD existente usa esas herramientas, k3s mantiene todas funcionando sin adaptación.",[12,22605,22606,22609],{},[27,22607,22608],{},"Compliance que exige distribución CNCF-certified."," Algunos frameworks de auditoría piden nominalmente una distribución certificada. k3s aparece en esa lista. HeroCtl no — somos demasiado jóvenes para estar en cualquier lista, y nuestra propuesta es lo suficientemente diferente para que algunas listas nunca lleguen a incluirnos.",[19,22611,22613],{"id":22612},"que-es-heroctl-exactamente","Qué es HeroCtl, exactamente",[12,22615,22616,22617,22620],{},"HeroCtl es un orquestador independiente. No es una distribución derivada de Kubernetes; no comparte API; no usa los mismos primitivos. Es una capa ",[27,22618,22619],{},"diferente"," que atiende una intención parecida — correr contenedores en varios servidores con alta disponibilidad real — usando otro vocabulario y otras decisiones de diseño.",[12,22622,22623],{},"Concretamente: un único archivo ejecutable que instalas en N servidores Linux. Los primeros tres se vuelven quórum para el plano de control replicado. Sometes jobs vía CLI, API o panel web embebido. Un job es un archivo de configuración de cerca de 50 líneas que describe la aplicación entera — incluyendo réplicas, ingress, certificados, secretos. El cluster decide dónde correr, hace health check, gestiona rolling updates, emite certificados automáticos vía router integrado.",[12,22625,22626],{},"No hay operadores especializados que instalar, no hay stacks de observabilidad montadas por separado, no hay malla de servicio configurada aparte. Métricas persistentes corren como job del propio sistema. Logs tienen escritor único embebido. Cifrado entre servicios y gestión de claves vienen listos. Ingress con TLS automático es parte del binario.",[12,22628,22629],{},"La consecuencia es un modelo operacional corto. Subir una aplicación nueva es describir, someter, esperar — y el cluster cuida de ruteo, certificado, replicación, métricas y health check sin que instales nada extra.",[19,22631,22633],{"id":22632},"que-heroctl-no-hace-limites-honestos","Qué HeroCtl NO hace (límites honestos)",[12,22635,22636,22639],{},[27,22637,22638],{},"No es compatible con la API de Kubernetes."," kubectl no conversa con HeroCtl. Charts de templating no corren. Manifiestos K8s no son aceptados. Si tu dependencia crítica es una herramienta del ecosistema CNCF que habla con la API de Kubernetes, HeroCtl no sustituye — es una herramienta diferente, con vocabulario propio.",[12,22641,22642,22645],{},[27,22643,22644],{},"No tiene ecosistema de operadores especializados."," No hay un operador maduro de Postgres con replicación automática esperando ser instalado. Corres Postgres como un job común y cuidas backup y replicación como humano cuida — no delegas a controlador externo. Para muchos equipos eso es alivio; para otros es regresión.",[12,22647,22648,22651],{},[27,22649,22650],{},"Rango de escala recomendado va de 1 a 500 servidores."," Probamos hasta cientos en laboratorio, validamos algunas decenas en producción. Por encima de eso, Kubernetes (pleno o en distribución como k3s) gana por ecosistema — herramientas de federación multi-cluster, autoscaling cruzado entre regiones, primitivas de migración de almacenamiento entre nubes existen ahí y todavía no existen aquí.",[12,22653,22654,22657],{},[27,22655,22656],{},"Federación multi-cluster no es nativa."," Si necesitas varias regiones orquestadas como una única superficie, con workloads moviéndose automáticamente entre ellas, herramientas como Rancher Fleet o los recursos multi-cluster de Kubernetes resuelven hoy. HeroCtl no.",[12,22659,22660,22663],{},[27,22661,22662],{},"Compliance que lista Kubernetes nominalmente."," Si tu certificación exige nominalmente una distribución certificada por la CNCF, HeroCtl no cumple — somos un producto nuevo, demasiado joven para figurar en listas establecidas. k3s, OpenShift y Talos cumplen. Ese es el camino.",[19,22665,22667],{"id":22666},"quien-debe-usar-heroctl-perfil-real","Quién debe usar HeroCtl (perfil real)",[12,22669,22670,22673],{},[27,22671,22672],{},"Equipos que NO quieren aprender Kubernetes pero necesitan orquestación con HA real."," Paneles self-hosted populares funcionan bien en un servidor pero no tienen consenso distribuido — cuando quieres tres servidores aguantando pérdida de uno sin downtime, esos paneles no sirven. Kubernetes serviría, pero cuesta un SRE en el equipo. HeroCtl es el medio que faltaba.",[12,22675,22676,22679],{},[27,22677,22678],{},"Indie hackers y startups hasta cerca de R$1M de ingresos anuales."," Stack típica: aplicación web, base relacional, cola asíncrona, cache. No hay Kafka, no hay Cassandra, no hay siete operadores de base. Para ese perfil, el ecosistema CNCF es capacidad ociosa cara — pagas en curva de aprendizaje y en complejidad operacional sin usar lo que pagas.",[12,22681,22682,22685],{},[27,22683,22684],{},"Aplicaciones web típicas sin dependencias exóticas."," HTTP encima de base SQL y cache en memoria cubre tal vez 70% del mercado SaaS. Para ese pedazo, Kubernetes es overkill y HeroCtl está dimensionado.",[12,22687,22688,22691],{},[27,22689,22690],{},"Quien quiere \"simplicidad de Coolify con HA real\"."," Coolify, Dokploy y similares acertaron la experiencia pero erraron la alta disponibilidad. Kubernetes acertó la alta disponibilidad pero erró la experiencia. HeroCtl intenta acertar los dos al costo de no ser Kubernetes.",[12,22693,22694,22697],{},[27,22695,22696],{},"Compliance LGPD-only."," Si tu compliance es LGPD y contratos comerciales brasileños, sin FedRAMP ni ITAR en el horizonte, la ausencia de certificaciones específicas no es bloqueo.",[19,22699,4825],{"id":4824},[12,22701,22702],{},"La tabla abajo cubre los criterios que más aparecen en la decisión. Cada línea tiene reserva — lee el texto.",[119,22704,22705,22716],{},[122,22706,22707],{},[125,22708,22709,22711,22714],{},[128,22710,2983],{},[128,22712,22713],{},"k3s",[128,22715,2995],{},[141,22717,22718,22729,22740,22751,22761,22771,22780,22791,22802,22813,22824,22835],{},[125,22719,22720,22723,22726],{},[146,22721,22722],{},"Tipo de producto",[146,22724,22725],{},"Distribución de Kubernetes",[146,22727,22728],{},"Orquestador independiente, no-Kubernetes",[125,22730,22731,22734,22737],{},[146,22732,22733],{},"Líneas para hello world + TLS + ingress",[146,22735,22736],{},"200–300 (manifiestos + operador de TLS)",[146,22738,22739],{},"~50 (job spec)",[125,22741,22742,22745,22748],{},[146,22743,22744],{},"RAM mínima total en el cluster",[146,22746,22747],{},"512 MB por nodo (1.5 GB en 3 nodos HA)",[146,22749,22750],{},"~600 MB por el plano de control (200–400 MB por nodo × 3)",[125,22752,22753,22755,22758],{},[146,22754,3152],{},[146,22756,22757],{},"8–16 semanas (curva K8s completa)",[146,22759,22760],{},"1–2 semanas",[125,22762,22763,22766,22768],{},[146,22764,22765],{},"Compatibilidad kubectl + charts de templating",[146,22767,16930],{},[146,22769,22770],{},"Ninguna — vocabulario propio",[125,22772,22773,22775,22778],{},[146,22774,11370],{},[146,22776,22777],{},"No — instala aparte",[146,22779,16387],{},[125,22781,22782,22785,22788],{},[146,22783,22784],{},"Certificados automáticos embebidos",[146,22786,22787],{},"No — operador externo",[146,22789,22790],{},"Sí, embebidos",[125,22792,22793,22796,22799],{},[146,22794,22795],{},"Métricas embebidas",[146,22797,22798],{},"No — stack externa de 3 productos",[146,22800,22801],{},"Sí, job del propio sistema",[125,22803,22804,22807,22810],{},[146,22805,22806],{},"Logs centralizados",[146,22808,22809],{},"No — stack externa de 2 productos",[146,22811,22812],{},"Sí, escritor único embebido",[125,22814,22815,22818,22821],{},[146,22816,22817],{},"Ecosistema de operators",[146,22819,22820],{},"Vasto (cientos)",[146,22822,22823],{},"Inexistente — workloads como jobs comunes",[125,22825,22826,22829,22832],{},[146,22827,22828],{},"Rango de escala recomendado",[146,22830,22831],{},"1 nodo a 10 mil+",[146,22833,22834],{},"1 a 500 servidores",[125,22836,22837,22840,22843],{},[146,22838,22839],{},"Modelo comercial",[146,22841,22842],{},"Open source (Apache 2.0), soportado por SUSE",[146,22844,22845],{},"Community gratuita + Business pagado + Enterprise",[12,22847,22848],{},"La columna que más importa varía por contexto. Para equipo que ya tiene expertise K8s, \"compatibilidad kubectl\" pesa mucho. Para equipo que está empezando, \"líneas para hello world\" y \"curva de aprendizaje\" pesan más.",[19,22850,22852],{"id":22851},"cuando-los-dos-estan-en-la-conversacion-decision-practica","Cuando los dos están en la conversación (decisión práctica)",[12,22854,22855],{},"Cinco escenarios reales que aparecen en conversaciones con lectores. Las respuestas son directas porque la realidad es directa.",[12,22857,22858,22861],{},[27,22859,22860],{},"\"Ya tenemos Kubernetes gestionado y duele operacionalmente.\"","\nk3s reduce costo cloud porque sales del plano de control pagado. El dolor operacional permanece — manifiestos largos, operadores de TLS, stacks externas de observabilidad. Ahorras en la factura pero no en el tiempo. HeroCtl reduce el dolor de raíz, pero exige aprender otra herramienta y reescribir los primitivos. Si el dolor es financiero, k3s. Si el dolor es tiempo de ingeniería, HeroCtl.",[12,22863,22864,22867],{},[27,22865,22866],{},"\"Estamos empezando ahora, queremos algo simple.\"","\nHeroCtl. Kubernetes (pleno o k3s) agrega meses de curva de aprendizaje que no generan valor para el producto en la fase inicial. Pasas tres meses aprendiendo charts de templating e ingress controllers en lugar de shippar features. En early-stage, el costo de oportunidad es todo.",[12,22869,22870,22873],{},[27,22871,22872],{},"\"Compliance exige distribución CNCF-certified.\"","\nk3s o Talos. HeroCtl no cumple esa lista. No es orgullo — es honestidad. Cuando estemos listos para esas listas, volvemos a conversar.",[12,22875,22876,22879],{},[27,22877,22878],{},"\"El equipo tiene 1 SRE fuerte que adora Kubernetes.\"","\nk3s. Deja al SRE feliz, mantiene todo el conocimiento existente del equipo, y aún así corta la factura cloud. HeroCtl forzaría al SRE a reaprender y abandonar herramientas que domina — fricción innecesaria cuando la expertise ya está pagada.",[12,22881,22882,22885],{},[27,22883,22884],{},"\"El equipo tiene 0 SRE y crece por el producto.\"","\nHeroCtl. Kubernetes sin expertise es receta para desastre — vas a descubrir qué es un pod stuck en CrashLoopBackOff en una noche de viernes, sin tener contexto para depurar. HeroCtl está dimensionado para equipo que no tiene guardia dedicada a infra.",[19,22887,22889],{"id":22888},"la-migracion-improbable","La migración improbable",[12,22891,22892],{},"Migrar de k3s a HeroCtl, o viceversa, es una operación que parece peor de lo que es.",[12,22894,22895,22898],{},[27,22896,22897],{},"Conceptualmente, los dos son similares."," Ambos corren contenedores, ambos tienen noción de réplicas, ambos tienen ingress, ambos tienen health check, ambos tienen rolling update. Si sabes hacer una cosa, sabes pensar la otra.",[12,22900,22901,22904],{},[27,22902,22903],{},"Sintácticamente, son incompatibles."," Manifiesto Kubernetes no convierte 1:1 a job spec HeroCtl. Los campos no encajan, las abstracciones no son las mismas, los defaults son diferentes. Reescribes.",[12,22906,22907,22910],{},[27,22908,22909],{},"Reescribir no es tan caro como parece."," Para equipo típico con 20 a 40 specs en producción, la migración toma una tarde. La razón es que la mayoría de los manifiestos K8s tiene repetición estructural enorme — 80% de los campos son estandarizados, y descubres rápidamente el mapeo. Para equipos con pocas decenas de jobs, conversor manual basta. Por encima de eso, estamos abiertos a conversar sobre conversores experimentales.",[12,22912,22913],{},"La migración del otro lado (HeroCtl → k3s) es más cara, porque estás saliendo de un modelo escueto para un modelo verboso. Ganas ecosistema; pagas en verbosidad.",[19,22915,18067],{"id":18066},[12,22917,22918],{},"Escenario: 4 VPS en proveedor europeo de bajo costo, cada una con 4 vCPU y 8 GB de RAM. Costo de infraestructura: cerca de R$100\u002Fmes por VPS, R$400\u002Fmes total.",[12,22920,22921,22924],{},[27,22922,22923],{},"k3s self-managed en ese escenario"," cuesta R$400\u002Fmes de infra más salario parcial de SRE. SRE fuerte en Brasil cuesta R$15k a R$25k\u002Fmes lleno. Aunque solo asignes 30% de su tiempo al cluster — lo que es optimista para equipo pequeño — son R$5k a R$7,5k de costo de gente. Total: R$5,4k a R$7,9k\u002Fmes.",[12,22926,22927,22930],{},[27,22928,22929],{},"HeroCtl Community en el mismo escenario"," cuesta R$400\u002Fmes de infra más asignación de dev part-time al cluster. Como el modelo operacional es más corto, 10% del tiempo de un dev sénior basta — R$1,5k a R$2,5k\u002Fmes. Total: R$1,9k a R$2,9k\u002Fmes.",[12,22932,22933],{},"La diferencia está en el salario de gente. k3s pide más expertise; más expertise cuesta más. La infra es prácticamente igual.",[12,22935,22936],{},"Ese cálculo se invierte cuando el equipo ya tiene SRE pagado independientemente de la elección de orquestador. Si el SRE existe por el resto del stack, el costo marginal de operar k3s es bajo, y el ecosistema CNCF pasa a valer oro. Es otro tipo de empresa.",[19,22938,3226],{"id":3225},[12,22940,22941,22944],{},[27,22942,22943],{},"¿k3s sigue siendo Kubernetes pleno?","\nSí. k3s está certificado por la CNCF como distribución conformante. Los mismos manifiestos corren, kubectl funciona idéntico, la API es la misma. Las remociones fueron de dependencias y plugins de nube — no de la API ni de la semántica.",[12,22946,22947,22950],{},[27,22948,22949],{},"¿HeroCtl puede correr en Raspberry Pi como k3s?","\nTécnicamente, sí — HeroCtl corre en cualquier servidor Linux con Docker, incluyendo ARM. Prácticamente, el caso de uso \"edge en Raspberry Pi\" es territorio donde k3s tiene años de pulido y HeroCtl todavía no fue ejercitado lo suficiente. Si tu uso es edge industrial en hardware ARM modesto, k3s es la elección más probada hoy. HeroCtl en Pi funciona para hobby; para producción edge, espera algunos trimestres más.",[12,22952,22953,22956],{},[27,22954,22955],{},"¿kubectl funciona en HeroCtl?","\nNo. HeroCtl tiene CLI propia y API propia. La intención fue diferente desde el inicio — no intentamos ser compatibles con Kubernetes. Quien quiere kubectl quiere Kubernetes; es la herramienta correcta para esa persona.",[12,22958,22959,22962],{},[27,22960,22961],{},"¿Cómo migrar de Kubernetes gestionado a k3s?","\nLa mayoría de los manifiestos corre directo. Las excepciones suelen ser: anotaciones específicas del proveedor de nube (load balancer, storage class), integraciones de IAM nativas y algún ingress controller que asumía infraestructura cloud. Cambias por equivalentes del ecosistema CNCF (MetalLB para LB, longhorn o storage local para volúmenes) y rehaces las anotaciones. Para cluster con pocas decenas de manifiestos, la migración lleva algunos días.",[12,22964,22965,22968],{},[27,22966,22967],{},"¿HeroCtl tiene multi-region como Rancher Fleet?","\nNo nativo. Hoy el quórum del plano de control está dimensionado para un cluster por región. Puedes operar HeroCtl en varias regiones en paralelo, cada una con su cluster, pero no hay hoy una capa de federación que presente todos como superficie única. Está en el roadmap. Quien necesita eso hoy, k3s + Rancher Fleet o Kubernetes pleno + Karmada son caminos ejercitados.",[12,22970,22971,22974],{},[27,22972,22973],{},"¿Cuál escala más alto?","\nKubernetes (pleno o k3s). Empresas operan clusters K8s con decenas de miles de nodos en producción. HeroCtl apunta al rango \"1 a 500 servidores\" y no pretende competir por encima de eso. Si operas en el nivel de cientos de miles de máquinas, K8s es el camino — no por elección, por dimensionamiento.",[12,22976,22977,22980],{},[27,22978,22979],{},"¿Puedo correr los dos lado a lado?","\nSí. Ambos son orquestadores que corren contenedores en servidores Linux. Puedes tener un cluster k3s para workloads que dependen del ecosistema CNCF y un cluster HeroCtl para apps web típicas — no entran en conflicto, son productos diferentes. Algunos clientes nuestros hacen exactamente eso: HeroCtl para el producto principal, k3s para ambiente de pruebas que necesita imitar el cluster gestionado de producción del cliente final.",[19,22982,22984],{"id":22983},"cierre-honesto","Cierre honesto",[12,22986,22987,22988,22990],{},"La pregunta inicial — \"¿ustedes son tipo un k3s, no?\" — tiene ahora una respuesta larga. No lo somos. k3s es Kubernetes empaquetado para caber en hardware modesto, manteniendo intacta toda la curva de aprendizaje y todo el ecosistema. HeroCtl es una capa ",[27,22989,22619],{}," de Kubernetes, con vocabulario propio, modelo operacional más corto, sin ecosistema de operadores y sin compatibilidad con kubectl.",[12,22992,22993],{},"Si ya hablas Kubernetes fluidamente y quieres llevar esa expertise a hardware barato o edge, k3s es la elección. Si nunca quisiste aprender Kubernetes pero necesitas orquestación con alta disponibilidad real, HeroCtl es la elección. Si tu dolor es compliance que lista distribuciones certificadas, k3s o Talos. Si tu dolor es tiempo de ingeniería gastado en manifiestos largos y operadores externos, HeroCtl.",[12,22995,22996],{},"No hay ganador universal — hay herramientas que combinan con contextos diferentes. La elección equivocada no es ni k3s ni HeroCtl; es adoptar cualquiera de las dos sin entender qué problema estás resolviendo realmente.",[12,22998,22999],{},"Quien quiera experimentar HeroCtl en el servidor más cercano, el camino es único:",[224,23001,23003],{"className":23002,"code":5318,"language":2530},[2528],[231,23004,5318],{"__ignoreMap":229},[12,23006,23007],{},"Cinco minutos después tienes un cluster de un nodo corriendo. Agrega dos servidores más con el mismo comando + token, y tienes alta disponibilidad real — sin instalar operador externo, sin montar stack de observabilidad, sin aprender vocabulario nuevo de manifiestos.",[12,23009,23010,23011,23013,23014,23016,23017,23019],{},"Para continuar la lectura, dos posts conversan directamente con este: ",[3337,23012,15791],{"href":15790}," trata de la decisión general de no adoptar K8s; ",[3337,23015,6334],{"href":6333}," compara las tres familias cuando el servidor de la nube está en la mesa. Y para entender por qué existimos como producto separado en lugar de ser una distribución K8s más, ",[3337,23018,6546],{"href":6545}," tiene el historial completo.",[12,23021,23022],{},"La intención, como siempre, es simple: orquestación de contenedores, sin ceremonia — pero con honestidad sobre cuándo ceremonia es lo que necesitas.",{"title":229,"searchDepth":244,"depth":244,"links":23024},[23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,23036],{"id":22515,"depth":244,"text":22516},{"id":22543,"depth":244,"text":22544},{"id":22575,"depth":244,"text":22576},{"id":22612,"depth":244,"text":22613},{"id":22632,"depth":244,"text":22633},{"id":22666,"depth":244,"text":22667},{"id":4824,"depth":244,"text":4825},{"id":22851,"depth":244,"text":22852},{"id":22888,"depth":244,"text":22889},{"id":18066,"depth":244,"text":18067},{"id":3225,"depth":244,"text":3226},{"id":22983,"depth":244,"text":22984},"2026-02-26","k3s es Kubernetes empaquetado para caber en 512MB. Para quien ya habla K8s y quiere llevarlo a menos. HeroCtl es una capa DIFERENTE de Kubernetes. Cómo decidir entre los dos sin mezclar premisas.",{},{"title":22496,"description":23038},{"loc":5343},"es\u002Fblog\u002Fk3s-vs-heroctl-cuando-cada-uno-tiene-sentido",[22713,20406,14948,23044,23045],"edge","lightweight","fWNLs9jnNOuyevnsrcaUHmNkAASDuq-I0sbqnPmxOLE",{"id":23048,"title":23049,"author":7,"body":23050,"category":8761,"cover":3380,"date":23628,"description":23629,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":23630,"navigation":411,"path":23631,"readingTime":8766,"seo":23632,"sitemap":23633,"stem":23634,"tags":23635,"__hash__":23640},"blog_es\u002Fes\u002Fblog\u002Fheroctl-vs-nomad.md","HeroCtl vs Nomad: la alternativa para quien fue agarrado por el cambio de licencia",{"type":9,"value":23051,"toc":23615},[23052,23055,23058,23062,23075,23078,23081,23085,23088,23094,23097,23103,23109,23113,23116,23119,23125,23131,23137,23140,23144,23147,23150,23153,23156,23159,23162,23166,23169,23175,23181,23187,23193,23196,23200,23203,23209,23219,23225,23228,23236,23239,23243,23419,23422,23426,23429,23435,23445,23455,23461,23467,23493,23496,23500,23503,23513,23519,23525,23531,23533,23539,23545,23554,23560,23570,23576,23582,23588,23590,23593,23596,23599,23606,23612],[12,23053,23054],{},"La historia de Nomad es, en retrospectiva, un aviso. Para mucha gente que eligió Nomad entre 2020 y 2022 — por el argumento de \"más simple que Kubernetes, código abierto de verdad, gobernanza abierta\" — los dos anuncios que vinieron después cambiaron la base del contrato. En agosto de 2023 la licencia cambió. En febrero de 2025 la empresa fue vendida. El producto técnico sigue siendo bueno. El contrato alrededor de él, ya no es el mismo que estaba en la mesa cuando firmaste.",[12,23056,23057],{},"Este post es sobre esa diferencia. No es una crítica al núcleo técnico de Nomad — vamos a llegar a él. Es sobre el problema estructural de adoptar una herramienta cuya base contractual puede cambiar entre una reorganización y la siguiente, y lo que queda para quien decide hoy, en abril de 2026.",[19,23059,23061],{"id":23060},"donde-nomad-acerto-y-sigue-acertando","Donde Nomad acertó (y sigue acertando)",[12,23063,23064,23065,571,23068,571,23071,23074],{},"Antes de cualquier crítica, el crédito debido. Nomad es técnicamente bueno. Plano de control replicado funciona en producción. La interfaz de línea de comando es consistente — ",[231,23066,23067],{},"nomad job run",[231,23069,23070],{},"nomad job stop",[231,23072,23073],{},"nomad alloc logs"," se comportan de forma previsible en mil clusters diferentes. La operación multi-region fue pensada de hecho, con federación entre datacenters y enrutamiento entre ellos. Soporta workloads no-Docker (binarios nativos, máquinas virtuales ligeras, drivers customizados) — una flexibilidad que el competidor mayor nunca priorizó.",[12,23076,23077],{},"Quien operó Nomad en producción en serio raramente reclama del núcleo. Los incidentes que aparecen en post-mortem públicos casi siempre están en el borde — integración con el gestor de configuración, integración con el router externo, integración con el cofre de secretos — no en el orquestador propiamente dicho.",[12,23079,23080],{},"Ese desempeño técnico es importante porque define el tono del resto del post: el problema de Nomad no es el código. El código es bueno. El problema es lo que sucedió alrededor del código.",[19,23082,23084],{"id":23083},"la-linea-del-tiempo-en-fechas-absolutas","La línea del tiempo, en fechas absolutas",[12,23086,23087],{},"Vale la pena recapitular sin dramatizar.",[12,23089,23090,23093],{},[27,23091,23092],{},"Agosto de 2023."," HashiCorp, entonces empresa de capital abierto, anuncia cambio de licencia en todos los productos principales — incluyendo Terraform, Vault, Consul y Nomad. La licencia migra de Mozilla Public License 2.0 (una licencia abierta, con copias de la definición de OSI) a Business Source License 1.1 — una licencia \"source available\". La diferencia práctica es la cláusula que restringe uso en productos comerciales que compitan con la oferta paga de la empresa. Aún puedes leer el código. Puedes ejecutar internamente. Ya no puedes embeberlo en un producto comercial tuyo, y ya no puedes ofrecerlo como servicio gestionado a terceros, sin licenciamiento separado.",[12,23095,23096],{},"La reacción de la comunidad fue inmediata. En pocas semanas, un fork de Terraform — OpenTofu — salió del papel, con gobernanza de Linux Foundation. Meses después, Vault ganó OpenBao con gobernanza parecida. Nomad y Consul quedaron sin fork comunitario equivalente fuerte. Hubo discusiones, contribuciones paradas, algunas salidas de mantenedores — pero nada del tamaño de lo que sucedió con Terraform.",[12,23098,23099,23102],{},[27,23100,23101],{},"Febrero de 2025."," IBM anuncia adquisición de HashiCorp por aproximadamente US$6.4 mil millones. La operación cierra aún en 2025. HashiCorp pasa a formar parte del portfolio IBM — alineado a ofertas existentes de IBM en torno a plataformas internas, gestión de configuración y nube híbrida.",[12,23104,23105,23108],{},[27,23106,23107],{},"Hoy (abril de 2026)."," La licencia BSL continúa en vigor. El soporte oficial es exclusivamente por el canal IBM. La cadencia de release sigue, pero el roadmap responde a OKRs internos de IBM ahora — ya no a un plan de producto independiente. No hay fork comunitario fuerte equivalente al OpenTofu para Nomad. Quien está en producción, está en producción; quien está adoptando hoy, está adoptando una herramienta cuyo dueño cambió dos veces en 30 meses.",[19,23110,23112],{"id":23111},"lo-que-eso-significa-en-la-practica","Lo que eso significa en la práctica",[12,23114,23115],{},"Para quien ya tenía Nomad en producción antes de agosto de 2023, la situación es gestionable. La versión inmediatamente anterior al cambio de licencia está congelada en MPL 2.0 — puedes seguir con ella, agarrar patches seleccionados, esperar madurar un fork. No es cómodo, pero es practicable.",[12,23117,23118],{},"Para quien está decidiendo en 2026, es una decisión diferente. Tres asteriscos importan:",[12,23120,23121,23124],{},[27,23122,23123],{},"La próxima feature crítica puede subir solo en la versión paga."," La licencia no impide eso, y la empresa ya no tiene un plan de producto independiente que mantenga las features estratégicas en el camino abierto. Es una elección ahora, no un principio.",[12,23126,23127,23130],{},[27,23128,23129],{},"El roadmap responde a OKRs IBM."," Eso puede ser bueno — IBM tiene músculo de ingeniería, va a invertir — o malo, si las prioridades de IBM (compliance, gubernamental, integración con productos legados) son diferentes de las tuyas. No controlas cuál de los dos sucede.",[12,23132,23133,23136],{},[27,23134,23135],{},"Precios comerciales pueden ser revisitados en una próxima reorganización."," Adquisiciones grandes suelen tener un período de \"descubrimiento de valor\" donde tablas de precio son reevaluadas. No hay regla que impida una nueva ronda de cambios contractuales en 12 o 24 meses. No tienes protección contra eso.",[12,23138,23139],{},"Comunidad técnica registra esas señales. La tasa de contribuciones externas a Nomad cayó después de agosto de 2023. Empresas que antes exhibían casos de uso públicos pararon de publicar. Talks en conferencias se enfriaron. El ecosistema sigue existiendo — pero perdió la tracción de producto-de-comunidad que tenía entre 2018 y 2022.",[19,23141,23143],{"id":23142},"la-leccion-correcta-no-es-codigo-abierto-o-nada","La lección correcta no es \"código abierto o nada\"",[12,23145,23146],{},"Aquí llega la parte que importa para cualquier herramienta de infraestructura — incluyendo HeroCtl.",[12,23148,23149],{},"El problema de Nomad no fue volverse pago. Empresas necesitan ser sostenibles; cobrar por software es legítimo; software comercial serio es mejor para todos que software abierto que entra en mantenimiento esquelético porque nadie paga.",[12,23151,23152],{},"El problema de Nomad fue cambiar el contrato con quien ya había apostado. Quien eligió Nomad en 2021 basado en la licencia abierta tenía una expectativa razonable — que aquella base sería estable. No fue. En tres años, la base se volvió otra cosa, y el coste de salida era — exactamente — la cantidad de trabajo que había sido invertido en la elección original.",[12,23154,23155],{},"Eso revela una asimetría. Software abierto que puede volverse comercial en cualquier momento es más arriesgado que software comercial publicado desde el día uno, con términos congelados para contratos existentes. El primero parece más seguro porque \"es abierto\". Es una percepción equivocada cuando el control del proyecto está concentrado en una única empresa, sujeta a adquisición, IPO, cambio de CEO o presión de inversor. El contrato puede cambiar; la percepción de seguridad era ilusión.",[12,23157,23158],{},"Software comercial honesto — precios publicados, términos congelados, sin cambio retroactivo, mecanismo de continuidad si la empresa encierra — es estructuralmente más previsible.",[12,23160,23161],{},"Ese es el pivote de HeroCtl.",[19,23163,23165],{"id":23164},"como-heroctl-resuelve-eso-estructuralmente","Cómo HeroCtl resuelve eso estructuralmente",[12,23167,23168],{},"HeroCtl nació comercial. No hubo fase de \"open source mientras crecemos, comercial después\". Los términos están en la mesa desde el día uno, publicados, con mecanismos contra-rug-pull explícitos.",[12,23170,23171,23174],{},[27,23172,23173],{},"Plan Community gratuito permanente."," Sin límite de servidores. Sin límite de jobs. Sin feature gate artificial. Ejecuta toda la stack — alta disponibilidad real, router integrado, certificados automáticos, criptografía entre servicios, métricas y logs. Individuos y equipos pequeños nunca necesitan salir de Community.",[12,23176,23177,23180],{},[27,23178,23179],{},"Sin phone-home, sin kill-switch."," Una vez instalado, el cluster funciona sin nunca hablar con servidor de la empresa. No hay activación periódica que expira. No hay flag que pueda ser revocada de fuera. Si la internet de la oficina se cae para siempre, el cluster sigue corriendo.",[12,23182,23183,23186],{},[27,23184,23185],{},"Escrow de código fuente en Enterprise."," Contratos Enterprise incluyen cláusula de escrow — el código es depositado con tercera parte custodiante. Si la empresa encierra operaciones, el código va a los clientes pagantes vía custodiante, con licencia para continuidad interna. No es \"confía en nosotros\"; es un mecanismo legal que sobrevive a la desaparición de la empresa.",[12,23188,23189,23192],{},[27,23190,23191],{},"Precios publicados."," Business y Enterprise tienen precios visibles en la página de planes — sin \"habla con ventas\" obligatorio como táctica de calificación. Sin cláusula de revisión unilateral; el precio acordado queda congelado para contratos existentes.",[12,23194,23195],{},"La diferencia con lo que sucedió en agosto de 2023 y febrero de 2025 no es una promesa. Es una estructura.",[19,23197,23199],{"id":23198},"comparacion-tecnica-honesta","Comparación técnica honesta",[12,23201,23202],{},"Quitando licencia, ¿cuál es la diferencia técnica? En alto nivel, sorprendentemente menos de lo que imaginarías.",[12,23204,23205,23208],{},[27,23206,23207],{},"Primitivas similares."," Nomad organiza trabajo en job → group → task. HeroCtl organiza en job → replica → task. Los conceptos mapean casi uno a uno. Un job describe el servicio, el agrupamiento determina réplica y localización, la task es lo que efectivamente ejecuta. Ambos soportan jobs de larga duración (services), jobs en lote (batch) y jobs periódicos.",[12,23210,23211,23214,23215,23218],{},[27,23212,23213],{},"Plano de control replicado en ambos."," Los dos usan consenso entre servidores para durabilidad del estado. Ambos toleran la pérdida de una minoría de servidores sin indisponibilidad. Ambos eligen coordinador automáticamente. En HeroCtl, el test de caos público muestra elección en alrededor de siete segundos después de un ",[231,23216,23217],{},"kill -9"," en el servidor que coordina.",[12,23220,23221,23224],{},[27,23222,23223],{},"Diferencia clave 1: batería incluida vs montar la malla."," Aquí las filosofías divergen. Nomad fue diseñado para ser compuesto con otros componentes del mismo ecosistema — gestor de configuración externo para service mesh, cofre de secretos externo, y algún gateway separado para ingress. Eso da flexibilidad enorme en escenarios complejos, pero significa que ejecutar Nomad en producción honestamente suele exigir tres productos en paralelo, cada uno con su propio plano de control, su propia actualización, su propia curva de aprendizaje.",[12,23226,23227],{},"HeroCtl tiene router integrado, certificados automáticos vía Let's Encrypt y criptografía entre servicios embebidos en el binario único. No montas la malla — viene montada. Para equipos pequeños eso son dos meses de trabajo economizados; para equipos grandes operando decenas de datacenters federados, es menos flexibilidad.",[12,23229,23230,23233,23234,101],{},[27,23231,23232],{},"Diferencia clave 2: franja de aplicación."," Nomad apunta a escala alta. Hay clusters públicos ejecutando decenas de miles de nodos. El ecosistema es más maduro en esa franja — y quien está bajando de Nomad porque la complejidad no se justifica suele estar haciendo la misma cuenta que describimos en ",[3337,23235,21924],{"href":15790},[12,23237,23238],{},"HeroCtl apunta a la franja \"1 a 500 servidores\" — single-server para prototipado, tres para alta disponibilidad real, decenas a cientos para escala productiva de SaaS medio. Por encima de eso, aún no testeamos en larga escala en producción; el roadmap llega allí, pero no es la prioridad del trimestre.",[19,23240,23242],{"id":23241},"lado-a-lado-sin-floritura","Lado a lado, sin floritura",[119,23244,23245,23256],{},[122,23246,23247],{},[125,23248,23249,23251,23254],{},[128,23250,2983],{},[128,23252,23253],{},"Nomad (bajo BSL\u002FIBM)",[128,23255,2995],{},[141,23257,23258,23268,23277,23290,23301,23311,23322,23333,23344,23355,23366,23377,23388,23399,23410],{},[125,23259,23260,23262,23265],{},[146,23261,22839],{},[146,23263,23264],{},"Source available (BSL 1.1) + comercial vía IBM",[146,23266,23267],{},"Comercial desde el día 1, plan gratuito permanente",[125,23269,23270,23273,23275],{},[146,23271,23272],{},"Plano de control replicado",[146,23274,3065],{},[146,23276,3065],{},[125,23278,23279,23282,23285],{},[146,23280,23281],{},"Elección de coordinador",[146,23283,23284],{},"Sí, en segundos",[146,23286,23287,23288],{},"Sí, ~7 segundos tras ",[231,23289,23217],{},[125,23291,23292,23295,23298],{},[146,23293,23294],{},"Router HTTP\u002FTLS",[146,23296,23297],{},"Externo (gateway de tercero)",[146,23299,23300],{},"Embebido",[125,23302,23303,23305,23308],{},[146,23304,3924],{},[146,23306,23307],{},"Externos (operador especializado)",[146,23309,23310],{},"Embebidos (Let's Encrypt automático)",[125,23312,23313,23316,23319],{},[146,23314,23315],{},"Criptografía entre servicios",[146,23317,23318],{},"Externa (gestor de configuración + cofre)",[146,23320,23321],{},"Embebida",[125,23323,23324,23327,23330],{},[146,23325,23326],{},"Cofre de secretos",[146,23328,23329],{},"Externo (cofre dedicado)",[146,23331,23332],{},"Embebido (cluster es el cofre)",[125,23334,23335,23338,23341],{},[146,23336,23337],{},"Métricas + logs",[146,23339,23340],{},"Stack externa",[146,23342,23343],{},"Job interno + escritor único embebido",[125,23345,23346,23349,23352],{},[146,23347,23348],{},"Líneas para app+ingress+TLS",[146,23350,23351],{},"80–120 líneas en varios archivos",[146,23353,23354],{},"~50 líneas en un archivo",[125,23356,23357,23360,23363],{},[146,23358,23359],{},"Ecosistema de drivers",[146,23361,23362],{},"Profundo (Docker, exec, java, qemu, plugins)",[146,23364,23365],{},"Docker como runtime",[125,23367,23368,23371,23374],{},[146,23369,23370],{},"Escala máxima testada",[146,23372,23373],{},"Decenas de miles de nodos",[146,23375,23376],{},"1–500 nodos (franja-objetivo)",[125,23378,23379,23382,23385],{},[146,23380,23381],{},"Soporte oficial",[146,23383,23384],{},"Canal IBM",[146,23386,23387],{},"Directo del fabricante; SLA en Business",[125,23389,23390,23393,23396],{},[146,23391,23392],{},"Contrato congelado para clientes existentes",[146,23394,23395],{},"No — cambió en 2023",[146,23397,23398],{},"Sí, cláusula explícita",[125,23400,23401,23404,23407],{},[146,23402,23403],{},"Mecanismo de continuidad si la empresa encierra",[146,23405,23406],{},"Implícito (BSL convierte a MPL tras 4 años)",[146,23408,23409],{},"Escrow activo en Enterprise",[125,23411,23412,23415,23417],{},[146,23413,23414],{},"Phone-home \u002F kill-switch",[146,23416,3059],{},[146,23418,3059],{},[12,23420,23421],{},"La columna que quita el sueño es la penúltima. \"Contrato congelado para clientes existentes\" es exactamente lo que faltó en agosto de 2023 — quien había adherido con expectativa de licencia abierta fue agarrado por el retroactivo. En HeroCtl, eso es una cláusula explícita.",[19,23423,23425],{"id":23424},"migracion-de-nomad-a-heroctl","Migración de Nomad a HeroCtl",[12,23427,23428],{},"La buena noticia de la convergencia de primitivas: la migración no es un rediseño de arquitectura. Es, en la mayor parte, una traducción de archivo.",[12,23430,23431,23434],{},[27,23432,23433],{},"Mapeo directo."," Un job en Nomad se vuelve un job en HeroCtl. Un group se vuelve un agrupamiento de réplicas. Una task continúa siendo la unidad que ejecuta en el agente. Constraints de placement (node class, datacenter, atributo customizado) tienen equivalentes directos. Update strategies (rolling, canary, blue-green) idem. Health checks vía comando o HTTP idem.",[12,23436,23437,23440,23441,23444],{},[27,23438,23439],{},"Lo que cambia en el archivo."," El archivo de configuración de HeroCtl es menor — alrededor de 50 líneas para un caso común de aplicación web con ingress y secretos, comparado con 80–120 líneas en jobspec equivalente. La diferencia viene de menos abstracciones intermedias y de la integración nativa con el router (describes ",[231,23442,23443],{},"ingress: { host, tls: true }"," en el propio job, no en un documento separado).",[12,23446,23447,23450,23451,23454],{},[27,23448,23449],{},"Lo que necesita adaptación."," Integraciones con el cofre de secretos externo necesitan volverse ",[231,23452,23453],{},"secrets:"," bloques en el propio job (el cluster es el cofre en HeroCtl). Service mesh vía gestor de configuración externo necesita ser sustituido por la criptografía entre servicios embebida — generalmente es simplificación, no regresión. Drivers no-Docker (exec, java) hoy no tienen equivalente directo; aplicaciones que dependen de eso quedan con Nomad o empaquetan en contenedor.",[12,23456,23457,23460],{},[27,23458,23459],{},"Conversor experimental."," Hay un conversor de jobspec en desarrollo — toma un archivo Nomad en entrada, emite un archivo HeroCtl en salida, con avisos para los casos no cubiertos. Está en desarrollo, no lo promovemos como producto listo. Cubre los casos comunes (job de servicio con Docker, ingress, health check, secretos); los casos de borde aún exigen revisión manual. Si es relevante para tu migración, escríbenos.",[12,23462,23463,23466],{},[27,23464,23465],{},"Plan en fases."," El camino que recomendamos para quien tiene producción en Nomad:",[2735,23468,23469,23475,23481,23487],{},[70,23470,23471,23474],{},[27,23472,23473],{},"Fase 1 (semanas 1–2)."," Subir cluster HeroCtl en paralelo, con 3 servidores. Migrar primero un job no crítico — preferentemente un job batch o periódico que no tiene usuario despierto dependiendo de él. Validar logs, métricas, comportamiento bajo fallo.",[70,23476,23477,23480],{},[27,23478,23479],{},"Fase 2 (semanas 3–4)."," Migrar una aplicación web con pocos usuarios. Validar emisión de certificado, rolling update, comportamiento durante pérdida de servidor. Comparar latencia y tasa de error con el Nomad equivalente.",[70,23482,23483,23486],{},[27,23484,23485],{},"Fase 3 (semanas 5+)."," Cutover por aplicación, no cutover del cluster entero. DNS apunta a HeroCtl, monitorear una semana, próxima aplicación. Mantén Nomad ejecutando lo que aún no migró.",[70,23488,23489,23492],{},[27,23490,23491],{},"Fase 4 (cuando cómodo)."," Decommission de Nomad. Documenta lo que aprendiste en tu wiki interna para la próxima herramienta — porque siempre hay próxima herramienta.",[12,23494,23495],{},"Para equipos con pocas decenas de jobs, la migración entera es una tarde. Para equipos con cientos de jobs, y drivers exóticos, es trabajo a medida — escríbenos que ayudamos a planificar.",[19,23497,23499],{"id":23498},"cuando-nomad-sigue-siendo-la-eleccion-correcta","Cuándo Nomad sigue siendo la elección correcta",[12,23501,23502],{},"Honestidad primero: no migres por moda.",[12,23504,23505,23508,23509,23512],{},[27,23506,23507],{},"Si ya estás ejecutando Nomad en producción sin problema operacional, quédate."," Cambio de licencia para quien no embebe ni ofrece como servicio gestionado es gestionable — ejecutas internamente, actualizas con cuidado, esperas que el ecosistema decante. Migrar una stack que funciona es trabajo innecesario. Para quien está saliendo de Nomad detrás de algo más simple y single-server, vale la pena considerar ",[3337,23510,23511],{"href":16704},"Coolify como alternativa"," antes de asumir que el camino es HeroCtl.",[12,23514,23515,23518],{},[27,23516,23517],{},"Si tu arquitectura depende profundamente de otros componentes del mismo ecosistema."," Cofre de secretos integrado con gestor de configuración integrado con Nomad, con políticas y ACLs federadas — deshacer esa integración es caro. El coste de salida puede ser mayor que el asterisco de licencia.",[12,23520,23521,23524],{},[27,23522,23523],{},"Si operas multi-region en escala grande."," Cientos de datacenters federados, con workloads moviéndose entre ellos, dependiendo de federación madura entre clusters. Nomad tuvo ocho años invertidos en esa dirección. HeroCtl tiene algunos trimestres en producción real. La elección conservadora para ese perfil es Nomad — y está todo bien.",[12,23526,23527,23530],{},[27,23528,23529],{},"Si tienes contratos gubernamentales que listan proveedores nominalmente."," Algunos frameworks (FedRAMP, ITAR, contratos federales) exigen proveedores listados. IBM ahora atiende esa lista. HeroCtl es joven de más. Si tu compliance officer necesita apuntar al nombre de una empresa en una lista de auditoría, hoy la respuesta es Nomad vía IBM, no HeroCtl.",[19,23532,7352],{"id":7351},[12,23534,23535,23538],{},[27,23536,23537],{},"¿HeroCtl es solo un clon de Nomad?","\nNo. Convergencia de primitivas (job, agrupamiento, task, plano de control replicado) refleja que esos son los bloques correctos para orquestación de contenedores — no copia. Las diferencias importantes (batería incluida en lugar de malla externa, contrato comercial congelado, franja de aplicación 1–500) son elecciones estructurales opuestas, no detalle de implementación. Si fuera clon, el archivo de configuración tendría 100+ líneas y dependería de tres productos paralelos.",[12,23540,23541,23544],{},[27,23542,23543],{},"¿Y si HeroCtl cambia de licencia?","\nLa pregunta es justa — es exactamente el tipo de pregunta que importa después de agosto de 2023. Tres protecciones: el contrato comercial publicado tiene cláusula de términos congelados para clientes existentes (precio acordado queda, no cambia retroactivamente); el binario no tiene phone-home ni kill-switch (una vez instalado, ejecuta independiente); contratos Enterprise tienen escrow activo (código va a los clientes pagantes si la empresa encierra). No es \"confía en nosotros\". Es estructura legal y técnica que sobrevive a cambio de gestión, adquisición o encierre.",[12,23546,23547,23550,23551,23553],{},[27,23548,23549],{},"¿El conversor de jobspec convierte integración con cofre de secretos y gestor de configuración?","\nNo totalmente. Integraciones con cofre externo se vuelven ",[231,23552,23453],{}," bloques en el job HeroCtl — el conversor hace la transformación sintáctica, pero a ti te cabe revisar la lógica (rotación, política de acceso, alcance). Service mesh vía gestor externo generalmente se vuelve la criptografía embebida, con simplificación en la mayoría de los casos. Los casos exóticos (políticas dinámicas, secretos con renovación coordinada) quedan con aviso de \"revisar manualmente\" en el reporte del conversor.",[12,23555,23556,23559],{},[27,23557,23558],{},"¿Y los plugins de driver de Nomad? Tengo un driver customizado para ejecutar binarios nativos.","\nHoy, HeroCtl ejecuta sobre Docker como runtime. Drivers exóticos (exec, java, qemu, customizados) no tienen equivalente directo — la aplicación necesita ser empaquetada en contenedor. Para mucha cosa, eso es simplificación; para algunos workloads (binarios compilados estáticamente, máquinas virtuales ligeras), es trabajo extra. Si dependes de driver no-Docker en producción, habla con nosotros antes de migrar.",[12,23561,23562,23565,23566,23569],{},[27,23563,23564],{},"¿Y los jobs periódicos y en lote?","\nSoportados. HeroCtl tiene jobs de larga duración, jobs en lote (ejecuta, termina, libera) y jobs periódicos (cron-like). La sintaxis es directa — una clave ",[231,23567,23568],{},"schedule: \"*\u002F5 * * * *\""," en el archivo de configuración. Lo que aún no tenemos es fan-out masivo de batch (miles de tasks paralelas con agregación de resultado) — para eso, herramientas dedicadas a flujo de datos siguen siendo mejores.",[12,23571,23572,23575],{},[27,23573,23574],{},"¿Puedo operar HeroCtl detrás de un Nomad existente?","\nTécnicamente sí — HeroCtl ejecuta en cualquier servidor Linux con Docker, así que puedes describir un job Nomad que sube el agente HeroCtl. Pero la recomendación es lo contrario: ejecutar HeroCtl en paralelo, migrar aplicación por aplicación, decomisionar Nomad cuando cómodo. Anidar dos orquestadores es mantener dos planos de control, dos modelos mentales, dos conjuntos de logs — sin ganancia.",[12,23577,23578,23581],{},[27,23579,23580],{},"¿El precio de Business es mayor o menor que el de Nomad Enterprise?","\nLos precios de Business y Enterprise están publicados en la página de planes de HeroCtl — sin \"habla con ventas\" obligatorio como táctica de calificación. La licencia comercial de Nomad bajo IBM es negociada caso por caso y no tiene precio público; comparaciones directas dependen de cotización. El punto que destacamos no es \"somos más baratos que IBM\" — es \"nuestro precio es público y congelado para contratos existentes\". Sabes lo que pagas en cinco años. Esa previsibilidad es el producto.",[12,23583,23584,23587],{},[27,23585,23586],{},"¿Cómo funciona el soporte?","\nCommunity tiene foro público y canales comunitarios — sin SLA. Business tiene soporte oficial directo del fabricante con SLA de horas en primera respuesta. Enterprise añade soporte 24×7 y desarrollo dedicado para extensiones específicas. Importante: soporte oficial es directo, no tercerizado vía canal, no dependiente de vendor extra en la cadena.",[19,23589,3310],{"id":3309},[12,23591,23592],{},"La historia de Nomad es menos sobre Nomad y más sobre la forma de adoptar infraestructura. Software abierto controlado por una única empresa es frágil en escala de años — no en el código, sino en el contrato. Adquisición, IPO, cambio de gestión, presión de inversor: cualquiera de esos puede reescribir la base bajo tus pies.",[12,23594,23595],{},"La respuesta correcta no es \"rechaza todo lo que tiene CIF detrás\". La respuesta correcta es exigir que el contrato sea explícito desde el día uno, con términos congelados para quien ya firmó y mecanismo de continuidad si la empresa desaparece. Software comercial honesto, con esas tres propiedades, es estructuralmente más previsible que software abierto que puede cambiar.",[12,23597,23598],{},"Ese es el diseño de HeroCtl. Comercial desde el día uno. Plan Community gratuito permanente, sin feature gate artificial. Business y Enterprise con precios publicados. Sin phone-home, sin kill-switch. Escrow en Enterprise.",[12,23600,23601,23602,23605],{},"Para instalar: ",[231,23603,23604],{},"curl -sSL https:\u002F\u002Fget.heroctl.com\u002Finstall.sh | sh"," en un servidor Linux con Docker. Para alta disponibilidad real, el mismo comando en tres servidores — forman quórum automáticamente.",[12,23607,23608,23609,23611],{},"Para entender la motivación detrás de eso, lee ",[3337,23610,6546],{"href":6545}," — explica los tres caminos que existían en 2026, la laguna que cada uno dejaba, y lo que intentamos llenar.",[12,23613,23614],{},"Si estás en Nomad y quieres conversar sobre migración, escribe. Si estás en Nomad y estás bien, quédate en Nomad — y aprovecha para leer el contrato con más atención la próxima vez que llegue una renovación. Esa es la verdadera lección de agosto de 2023.",{"title":229,"searchDepth":244,"depth":244,"links":23616},[23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,23627],{"id":23060,"depth":244,"text":23061},{"id":23083,"depth":244,"text":23084},{"id":23111,"depth":244,"text":23112},{"id":23142,"depth":244,"text":23143},{"id":23164,"depth":244,"text":23165},{"id":23198,"depth":244,"text":23199},{"id":23241,"depth":244,"text":23242},{"id":23424,"depth":244,"text":23425},{"id":23498,"depth":244,"text":23499},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-02-19","HashiCorp cambió la licencia de Nomad en agosto de 2023 y fue adquirida por IBM en febrero de 2025. Para quien está adoptando hoy, es un asterisco grande.",{},"\u002Fes\u002Fblog\u002Fheroctl-vs-nomad",{"title":23049,"description":23629},{"loc":23631},"es\u002Fblog\u002Fheroctl-vs-nomad",[23636,23637,23638,23639,8775,6393],"nomad","hashicorp","ibm","bsl","rh5tXrxtP-HjSkmCngokJp_Va2GtGUD8ngE8A5hEcl4",{"id":23642,"title":23643,"author":7,"body":23644,"category":8761,"cover":3380,"date":24183,"description":24184,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":24185,"navigation":411,"path":24186,"readingTime":8766,"seo":24187,"sitemap":24188,"stem":24189,"tags":24190,"__hash__":24195},"blog_es\u002Fes\u002Fblog\u002Frender-vs-railway-vs-fly-io.md","Render vs Railway vs Fly.io: comparativo 2026",{"type":9,"value":23645,"toc":24171},[23646,23649,23652,23655,23659,23662,23673,23676,23679,23682,23686,23697,23703,23709,23715,23721,23727,23731,23734,23739,23744,23749,23754,23759,23763,23766,23775,23780,23791,23796,23801,23803,23994,23997,24001,24004,24010,24016,24022,24028,24031,24035,24038,24044,24050,24056,24062,24066,24069,24075,24081,24087,24093,24095,24101,24107,24116,24122,24128,24134,24144,24146,24149,24152,24154,24159,24168],[12,23647,23648],{},"En agosto de 2022 Salesforce anunció el fin del plan gratuito de Heroku. La decisión fue escrita en dos líneas en un post de blog corporativo, se volvió meme en tres horas, y en tres meses estaba reescribiendo el mapa de PaaS hospedado para todo dev indie del mundo. Los devs de mercado emergente recibieron el golpe doble: perdieron el tier gratis y vieron al dólar subir de R$5,20 a R$5,90 en el mismo período.",[12,23650,23651],{},"Tres productos tomaron la mayor parte de la herencia: Render, Railway y Fly.io. Cada uno apuesta por una filosofía distinta — precio fijo predecible, pay-as-you-go con UI bonita, o edge multi-región con primitivas de bajo nivel. Para dev de mercado emergente, la elección mezcla DX, coste en USD que se convierte en moneda local, latencia hacia São Paulo, y el techo de escala antes de que el proyecto empiece a doler en el bolsillo.",[12,23653,23654],{},"Este artículo es el mapa honesto. Sin ranking de \"mejor\", porque no existe — existe el mejor para cada etapa. Y al final de la línea, cuando los tres se vuelven caros, existe el camino del auto-hospedado, que es donde HeroCtl entra. Pero vamos por partes.",[19,23656,23658],{"id":23657},"la-herencia-de-heroku","La herencia de Heroku",[12,23660,23661],{},"Para entender lo que cada uno copió y lo que cada uno descartó, vale la pena recordar lo que Heroku hizo bien en sus diez años de gloria.",[12,23663,23664,23665,23668,23669,23672],{},"La primera cosa fue ",[231,23666,23667],{},"git push heroku main",". Aquel comando se volvió el patrón mental de deploy para una generación entera de devs. No había pipeline para configurar, no había registro de imagen para poblar, no había archivo de orquestación para escribir. Empujabas código al repositorio remoto y la plataforma se encargaba del resto — buildpack detectaba el lenguaje, instalaba dependencias, subía el proceso. Render y Railway heredaron eso casi intacto. Fly.io lo cambió por ",[231,23670,23671],{},"fly deploy",", que tiene la misma cara pero trabaja con imagen de contenedor explícita.",[12,23674,23675],{},"La segunda cosa fue la noción de \"dyno\" como unidad de cobro y escala. No pensabas en servidor, vCPU o RAM — pensabas en cuántos procesos web y cuántos workers. Render mantuvo esa simplificación en el plan Starter. Railway abandonó y cobra por el recurso real consumido. Fly.io cambió dyno por VM con tamaño declarado.",[12,23677,23678],{},"La tercera cosa fue el marketplace de addons: Postgres, Redis, MongoDB, e-mail transaccional, todo a un clic. Esa es la pieza donde los tres sucesores divergen más. Render tiene algunos addons gestionados nativos. Railway tiene un marketplace de templates que cubre lo básico. Fly.io te empuja a correr tu propio Postgres en una app dedicada, con toda la responsabilidad que eso trae.",[12,23680,23681],{},"Y la cuarta cosa, la dolorosa, fue el vendor lock-in disfrazado de simplicidad. Quien tenía cincuenta servicios en Heroku descubrió en 2022 que migrar costaría meses. Los tres sucesores prometen ser mejores en ese aspecto; veremos.",[19,23683,23685],{"id":23684},"render-el-heroku-20-predecible","Render: el \"Heroku 2.0 predecible\"",[12,23687,23688,23689,23692,23693,23696],{},"Render es el sucesor más conservador. La premisa es simple: describes el servicio en un archivo ",[231,23690,23691],{},"render.yaml"," o por el panel, conectas el repositorio, y cada push a ",[231,23694,23695],{},"main"," dispara un deploy. Build, certificado TLS, dominio personalizado, todo automático.",[12,23698,23699,23702],{},[27,23700,23701],{},"Filosofía."," Precios fijos por instancia. La instancia Starter más barata cuesta US$7\u002Fmes — y cuesta US$7\u002Fmes independientemente de que hagas cinco requests por día o cincuenta mil. Existe un plan free, pero con asterisco grande: el servicio duerme tras quince minutos sin tráfico y tarda unos treinta segundos en despertar en el primer request. Es exactamente el mismo tradeoff del Heroku free de 2015. Funciona para portfolio, no funciona para producto serio.",[12,23704,23705,23708],{},[27,23706,23707],{},"Puntos fuertes."," La predictibilidad del presupuesto es el gran atractivo para equipo pequeño. Sabes que tres servicios Starter van a costar US$21\u002Fmes, punto. No hay sorpresa de fin de mes porque un cron corrió en loop. Postgres y Redis gestionados existen como productos propios, con backup automático y versión reciente. El panel es limpio, se enfoca en hacer pocas cosas bien. Latencia hacia São Paulo desde el datacenter de Ohio queda en torno a 120ms — no es ideal, pero es viable para app web típico donde el cuello de botella suele ser query de base de datos.",[12,23710,23711,23714],{},[27,23712,23713],{},"Puntos débiles."," El free tier durmiendo es triste para cualquier cosa que no sea vitrina personal. Escalar cuesta caro porque es lineal: cuatro instancias Starter cuestan cuatro veces US$7. No hay multi-region nativo en el plan básico — quedas preso a la región que elegiste. CDN y edge computing son limitados; quien necesita cache geográfico pesado va a sufrir. Y el Postgres gestionado empieza en US$7\u002Fmes, así que el piso real de una app con base es US$14\u002Fmes, lo que para MVP en etapa cero de ingreso ya incomoda.",[12,23716,23717,23720],{},[27,23718,23719],{},"Coste en moneda local."," App simple sin base: US$7\u002Fmes = R$36 a R$40 dependiendo del cambio. Con Postgres mínimo: US$14\u002Fmes = R$72 a R$80. Versión de producción con dos instancias web y Postgres Standard (US$20\u002Fmes): US$34\u002Fmes = R$170 a R$190. Suma dominio, e-mail transaccional, monitoring y estás en R$300\u002Fmes fácil para un SaaS pequeño. No es caro por el estándar americano. Es caro por el estándar local de quien saca el salario del propio MRR.",[12,23722,23723,23726],{},[27,23724,23725],{},"Cuándo tiene sentido."," Indie hacker que ya está en Heroku y quiere migrar con el mínimo de fricción mental. Equipo de una a tres personas que valora presupuesto predecible más que coste mínimo absoluto. App web tradicional sin requisitos de baja latencia geográfica. Proyecto donde prefieres pagar US$30\u002Fmes y no pensar más a pagar US$10\u002Fmes con posibilidad de explotar a US$80 en un mes malo.",[19,23728,23730],{"id":23729},"railway-el-pay-as-you-go-con-ux-premium","Railway: el \"pay-as-you-go con UX premium\"",[12,23732,23733],{},"Railway es el sucesor que se atrevió a invertir el modelo de cobro. En lugar de instancia fija, pagas por el recurso real consumido — vCPU, RAM, network egress, storage. La premisa es que apps pequeñas y jobs intermitentes salen más baratos en el pay-as-you-go que en el instance-based.",[12,23735,23736,23738],{},[27,23737,23701],{}," Cobro granular por uso real. No eliges tamaño de máquina, eliges la app y Railway decide cuánto recurso entregar conforme la demanda, dentro de un techo. UI excelente — probablemente la más bonita del segmento PaaS hospedado. Templates one-click cubren decenas de combinaciones: Postgres, Redis, MongoDB, MeiliSearch, n8n, Strapi.",[12,23740,23741,23743],{},[27,23742,23707],{}," La UX gana en el primer contacto. En quince minutos tienes una app corriendo con base, Redis y dashboard de logs en tiempo real. El marketplace de templates es amigable para quien no quiere escribir Dockerfile. Para apps low-traffic el pay-as-you-go puede salir mucho más barato que instancia fija de Render — un cron que corre diez segundos por día solo paga esos diez segundos, no veinticuatro horas.",[12,23745,23746,23748],{},[27,23747,23713],{}," Coste imprevisible es el talón. Railway tiene techo suave de gasto, pero no rígido por defecto — un job en loop infinito puede quemar US$50 en un fin de semana antes de que percibas. El pricing tiene letra pequeña: el plan Hobby (US$5\u002Fmes) incluye US$5 de uso, así que técnicamente empiezas desde cero todo mes, pero la cuenta puede pasar de eso fácil. El plan gratuito original fue removido en 2023 — otra repetición del patrón Heroku. Datacenter es US-only, latencia hacia SP queda en los mismos 120ms de Render. Y hubo histórico de cambios de pricing que tomaron usuarios por sorpresa, tipo la remoción del trial más generoso a mediados de 2023.",[12,23750,23751,23753],{},[27,23752,23719],{}," Hobby plan: US$5\u002Fmes fijo = R$25 a R$28. Pero el uso real suele empujar la cuenta a US$10-20\u002Fmes en una app con base y workers ligeros = R$50 a R$110. En mes malo, con pico de tráfico, es fácil ver la cuenta acercarse a US$30-40 = R$150 a R$220. La segunda desviación estándar es lo que asusta.",[12,23755,23756,23758],{},[27,23757,23725],{}," Equipo pequeño en fase de experimentación, lanzando decenas de tests por semana, donde la mayoría nunca pega tráfico y sería desperdicio pagar instancia fija. Apps low-traffic genuinamente pequeñas donde pay-per-use sale más barato a largo plazo. Devs que valoran UI bonita y flujo de deploy sin fricción por encima de predictibilidad rígida de presupuesto. Proyectos personales que corren en ráfaga.",[19,23760,23762],{"id":23761},"flyio-el-edge-multi-region-para-workloads-serios","Fly.io: el \"edge multi-region para workloads serios\"",[12,23764,23765],{},"Fly.io es el más técnico de los tres. La premisa es distinta desde la base: tu app no corre en una región, corre en varias. Cuando un usuario en Brasil accede, el request pega en la región más cercana — y Fly.io tiene punto en São Paulo, el GRU. Para latencia percibida por el usuario brasileño, eso es la cosa más importante del mercado de PaaS hoy.",[12,23767,23768,23770,23771,23774],{},[27,23769,23701],{}," Aplicación global por defecto. VMs reales (no contenedores compartidos) sobre Firecracker. Primitivas de bajo nivel — lidias con ",[231,23772,23773],{},"fly.toml",", con volúmenes persistentes regionales, con red privada entre apps vía WireGuard, con IPs anycast. Más poder, más responsabilidad.",[12,23776,23777,23779],{},[27,23778,23707],{}," El datacenter GRU es ventaja real y mensurable: latencia para usuario en São Paulo cae de 120ms (Render\u002FRailway vía US) a 30-60ms. Para app interactivo, eso es la diferencia entre \"rápido\" e \"instantáneo\". Multi-region es nativo — corres el mismo binario en tres continentes, y el enrutamiento pega en la región más cercana al usuario. Volúmenes persistentes regionales permiten patterns como Postgres con Litestream replicando para storage de objeto. El pricing empieza muy barato: US$1.94\u002Fmes por la menor VM (shared-cpu-1x, 256MB), más fracciones de céntimo por GB transferido.",[12,23781,23782,23784,23785,571,23788,23790],{},[27,23783,23713],{}," Curva de aprendizaje real. ",[231,23786,23787],{},"flyctl",[231,23789,23773],{},", conceptos de Machines vs Apps, redes WireGuard — todo eso tienes que digerir. No es \"abre panel y haz clic en deploy\", es \"lee la doc por una tarde\". Pricing variable tipo Railway, con la misma trampa: app que crece de repente puede triplicar el coste en un mes. La comunidad es menor que Render\u002FRailway, especialmente en PT-BR — encontrar tutorial en portugués reciente es tarea. Y hubo incidentes de estabilidad reportados públicamente en 2023-2024 que afectaron confianza de la base; mejoraron, pero la memoria aún pesa.",[12,23792,23793,23795],{},[27,23794,23719],{}," App pequeño con VM mínima y storage modesto: US$2-6\u002Fmes = R$10 a R$32. Postgres corrido como app dedicada (eres responsable del backup): más US$2-10\u002Fmes = R$10 a R$50. App producción serio con dos regiones y bandwidth real: US$15-40\u002Fmes = R$80 a R$220. El rango bajo es imbatible para proyecto personal; el rango alto empieza a competir con auto-hospedado en VPS dedicada.",[12,23797,23798,23800],{},[27,23799,23725],{}," B2B SaaS con clientes distribuidos en múltiples regiones — app que necesita estar en US-East y en GRU simultáneamente sin que operes dos clusters. App donde latencia para usuario brasileño es diferencial competitivo. Equipo cómodo con primitivas tipo VM, red mesh, storage block regional — típicamente devs que tienen background en DevOps o que migraron de bare-metal. Proyecto personal de hobby donde los US$2\u002Fmes pagan cinco apps de una vez.",[19,23802,17389],{"id":17388},[119,23804,23805,23818],{},[122,23806,23807],{},[125,23808,23809,23811,23813,23815],{},[128,23810,2983],{},[128,23812,15024],{},[128,23814,15027],{},[128,23816,23817],{},"Fly.io",[141,23819,23820,23834,23848,23862,23876,23889,23903,23914,23926,23940,23954,23968,23982],{},[125,23821,23822,23825,23828,23831],{},[146,23823,23824],{},"Coste mínimo USD\u002Fmes (app real)",[146,23826,23827],{},"US$7 (Starter)",[146,23829,23830],{},"US$5 (Hobby plan) + uso",[146,23832,23833],{},"US$2-3 (shared-cpu-1x)",[125,23835,23836,23839,23842,23845],{},[146,23837,23838],{},"Coste mínimo R$\u002Fmes (cambio R$5,50)",[146,23840,23841],{},"~R$40",[146,23843,23844],{},"~R$30 + uso variable",[146,23846,23847],{},"~R$15",[125,23849,23850,23853,23856,23859],{},[146,23851,23852],{},"Modelo de cobro",[146,23854,23855],{},"Instancia fija",[146,23857,23858],{},"Pay-as-you-go",[146,23860,23861],{},"VM declarada + uso",[125,23863,23864,23867,23870,23873],{},[146,23865,23866],{},"Latencia hacia São Paulo",[146,23868,23869],{},"~120ms (Ohio)",[146,23871,23872],{},"~120ms (US)",[146,23874,23875],{},"~30-60ms (GRU)",[125,23877,23878,23881,23884,23886],{},[146,23879,23880],{},"Multi-region nativo",[146,23882,23883],{},"No en el plan base",[146,23885,3059],{},[146,23887,23888],{},"Sí, central en el producto",[125,23890,23891,23894,23897,23900],{},[146,23892,23893],{},"Free tier real",[146,23895,23896],{},"Sí, con sleep",[146,23898,23899],{},"Removido en 2023",[146,23901,23902],{},"No, pero piso muy bajo",[125,23904,23905,23907,23909,23911],{},[146,23906,14426],{},[146,23908,3059],{},[146,23910,3059],{},[146,23912,23913],{},"Sí (GRU)",[125,23915,23916,23919,23921,23923],{},[146,23917,23918],{},"Preview deploys por PR",[146,23920,3065],{},[146,23922,3065],{},[146,23924,23925],{},"Sí, vía CLI",[125,23927,23928,23931,23934,23937],{},[146,23929,23930],{},"Postgres gestionado",[146,23932,23933],{},"Sí, US$7\u002Fmes",[146,23935,23936],{},"Sí, vía template",[146,23938,23939],{},"No nativo (corres tú)",[125,23941,23942,23945,23948,23951],{},[146,23943,23944],{},"Auto-scaling",[146,23946,23947],{},"Manual en el Starter",[146,23949,23950],{},"Sí, vertical y horizontal",[146,23952,23953],{},"Sí, vía Machines API",[125,23955,23956,23959,23962,23965],{},[146,23957,23958],{},"Lock-in de plataforma",[146,23960,23961],{},"Medio (algunos addons propietarios)",[146,23963,23964],{},"Alto (templates personalizados)",[146,23966,23967],{},"Bajo (Dockerfile estándar)",[125,23969,23970,23973,23976,23979],{},[146,23971,23972],{},"Foco de la audiencia",[146,23974,23975],{},"Ex-Heroku predecible",[146,23977,23978],{},"Indie hacker UI-first",[146,23980,23981],{},"Dev técnico edge-first",[125,23983,23984,23986,23989,23991],{},[146,23985,14473],{},[146,23987,23988],{},"Pequeña, creciendo",[146,23990,4920],{},[146,23992,23993],{},"Muy pequeña",[12,23995,23996],{},"La tabla esconde matiz que vale explicitar: ninguno de los tres es \"el mejor\" en todo. Render gana en predictibilidad. Railway gana en UX. Fly.io gana en performance para usuario brasileño. La elección es función de lo que estás optimizando.",[19,23998,24000],{"id":23999},"lo-que-los-tres-tienen-en-comun-y-donde-heroctl-entra","Lo que los tres tienen en común (y dónde HeroCtl entra)",[12,24002,24003],{},"Cuatro puntos los tres comparten, y cada uno de ellos es un motivo para eventualmente salir.",[12,24005,24006,24009],{},[27,24007,24008],{},"Primero: cobro en USD."," Ninguno de los tres factura en moneda local. Cambio sube, tu cuenta sube junto, y descubres en febrero que la infra que costaba R$300 en enero cuesta R$340 sin ningún cambio técnico. Para equipo bootstrapped sin protección cambiaria, eso es exposición que nadie pidió tener.",[12,24011,24012,24015],{},[27,24013,24014],{},"Segundo: no controlas el servidor."," No eliges el kernel, no tienes acceso SSH, no corres proceso en background fuera de lo que la plataforma permite. Para noventa por ciento de los casos eso es ventaja. Para los diez por ciento restantes — cuando necesitas fine-tuning, daemon personalizado, alguna capability específica del sistema operativo — estás limitado.",[12,24017,24018,24021],{},[27,24019,24020],{},"Tercero: free tiers menguando año tras año."," Heroku mató el free en 2022. Railway removió el trial generoso en 2023. Render mantiene free con sleep pero ha reducido límites. El patrón es claro: el free tier sirve para adquirir dev en etapa cero de ingreso; cuando el producto crece, la empresa necesita monetizar y el free encoge. No es traición, es economía. Pero implica que tu estrategia de largo plazo no puede depender de que el free continúe como está.",[12,24023,24024,24027],{},[27,24025,24026],{},"Cuarto y más importante: cuando la startup crece, el coste escala desproporcionadamente."," App pequeño US$15\u002Fmes es despreciable. App real con cinco servicios, dos bases, Redis, y dos ambientes (staging + prod) empieza en US$80-150\u002Fmes — entre R$450 y R$850. Suma workers, jobs en background, monitoring, y pasas de US$200\u002Fmes fácil. Es en ese punto que el auto-hospedado deja de ser hobby de DevOps y se vuelve economía clara.",[12,24029,24030],{},"El rango típico donde el tradeoff cambia: cuando tu PaaS hospedado pasa de US$50\u002Fmes de gastos consistentes, tres VPS Hetzner de US$5 cada uno (~R$80 total) corriendo una plataforma de orquestación empiezan a hacer sentido financiero. Cambias conveniencia por economía, y ganas control del servidor de bono. HeroCtl está diseñado para ese rango: instalación simple, alta disponibilidad real entre múltiples servidores, certificados automáticos, panel web. Sin ceremonia operacional, sin equipo de SRE.",[19,24032,24034],{"id":24033},"decision-por-etapa-del-proyecto","Decisión por etapa del proyecto",[12,24036,24037],{},"La pregunta correcta no es \"cuál es el mejor PaaS\", es \"cuál es el mejor para la etapa donde estoy ahora\".",[12,24039,24040,24043],{},[27,24041,24042],{},"Etapa hobby, cero ingreso."," Render free tier (con sleep), o Fly.io aprovechando el rango mínimo (US$2-3\u002Fmes cubre proyecto personal), o un VPS de US$5 mensuales con Coolify corriendo solo si te gusta tocar. Railway perdió posición aquí después de remover el tier gratis original.",[12,24045,24046,24049],{},[27,24047,24048],{},"Etapa indie hacker, hasta US$5k MRR."," Render si priorizas presupuesto predecible y la app tiene perfil \"instancia corre 24\u002F7 con tráfico constante\". Railway si estás experimentando mucho, quieres UI bonita, y el pay-as-you-go te va a favorecer. Coste en ese rango queda en US$15-50\u002Fmes, gestionable.",[12,24051,24052,24055],{},[27,24053,24054],{},"Etapa startup early, US$5k a US$50k MRR."," Hora de evaluar con seriedad. Si latencia hacia usuario brasileño importa (B2C, app interactivo), Fly.io se vuelve candidato fuerte por el GRU. Si el equipo ya tiene un dev cómodo con infra básica, auto-hospedado simple (Coolify en un servidor, o HeroCtl en tres para alta disponibilidad) empieza a pagar. La cuenta en ese rango en PaaS hospedado corre en US$80-300\u002Fmes — en auto-hospedado, R$150-400\u002Fmes con más headroom.",[12,24057,24058,24061],{},[27,24059,24060],{},"Etapa startup con primer cliente B2B serio, SLA exigido."," Aquí el PaaS hospedado empieza a romper de otras maneras: necesitas SLA contractual, redundancia en múltiples servidores, ventana de mantenimiento predecible, logs de auditoría. Render y Railway no ofrecen SLA fuerte en el plan estándar. Fly.io ofrece, pero la multi-region implica complejidad operacional que el equipo va a tener que aprender de todos modos. Ese es el punto donde HeroCtl con cluster de tres servidores entra como alternativa: alta disponibilidad real, panel administrativo, auditoría, sin la mensualidad de US$300+ del PaaS hospedado para el mismo nivel de robustez. La otra opción es el camino opuesto: AWS gestionado si algún cliente jala requisitos de compliance específicos.",[19,24063,24065],{"id":24064},"cuando-no-salir-de-render-railway-o-flyio","Cuándo NO salir de Render, Railway o Fly.io",[12,24067,24068],{},"Migración cuesta caro, y en la mayor parte de los casos es optimización prematura. Cuatro situaciones claras para quedarse donde estás.",[12,24070,24071,24074],{},[27,24072,24073],{},"Equipo de una o dos personas sin nada de tiempo para cosa operacional."," Si eres fundador solo en el producto y cada hora gastada en infra es una hora no gastada en ventas, mantener el PaaS es decisión correcta. R$200\u002Fmes de hospedado es más barato que diecisiete horas tuyas en el mes tocando servidor.",[12,24076,24077,24080],{},[27,24078,24079],{},"Coste de plataforma es despreciable comparado con el ingreso."," Regla simple: si la infra es menos de dos por ciento del MRR, no optimices. SaaS de US$50k MRR gastando US$500\u002Fmes de hospedado está pagando uno por ciento de infra. Es excelente. Tocar ahí es micromizar para ahorrar monedas.",[12,24082,24083,24086],{},[27,24084,24085],{},"Usas addon propietario sin sustituto fácil."," Si dependes de algún addon específico de Railway que no tiene equivalente obvio fuera — algún template personalizado con integración propietaria, alguna feature única — la migración no es solo re-deploy, es re-arquitectura. Evalúa el coste total antes.",[12,24088,24089,24092],{},[27,24090,24091],{},"Migración tomaría más de dos semanas y la empresa no puede parar para eso."," Hay momentos en que el producto está en hipercrecimiento, o en ciclo crítico de funding, o simplemente en sprint de feature que importa al cliente. No migres infra en esas ventanas. Anota la deuda técnica y vuelve después.",[19,24094,3226],{"id":3225},[12,24096,24097,24100],{},[27,24098,24099],{},"¿Puedo usar Render para producción y Railway para staging?","\nPuedes, y hay gente que lo hace. La justificación es simple: producción exige predictibilidad (Render brilla ahí), staging tiene tráfico ráfaga e idealmente debería costar poco cuando nadie está usando (Railway pay-as-you-go gana). El coste de mantener dos proveedores es el overhead mental de dos dashboards y dos conjuntos de credenciales. Tiene sentido para equipo disciplinado, estorba para equipo pequeño que prefiere monocultura.",[12,24102,24103,24106],{},[27,24104,24105],{},"¿Fly.io GRU region es confiable?","\nHoy sí, con asterisco. Funciona bien desde 2023, latencia medida hacia SP\u002FRJ es lo que promete (30-60ms típicamente). El asterisco es que GRU es una región menor en el portafolio de Fly, así que capacidad puede quedar apretada en picos y features nuevas suelen llegar a US-East primero. Para producción seria, vale correr en al menos dos regiones (GRU + una US) con failover.",[12,24108,24109,24112,24113,24115],{},[27,24110,24111],{},"¿Cómo migro de Render a HeroCtl sin downtime?","\nHoja de ruta pragmática: provisiona tres VPS, instala HeroCtl, sube la aplicación en paralelo apuntando a un dominio temporal. Replica la base con ",[231,24114,5736],{}," + carga inicial, después mantén en sincronía con replicación lógica hasta el switchover. Cuando esté listo, cambia el DNS del dominio principal al nuevo cluster con TTL bajo. La ventana de riesgo queda alrededor del TTL del DNS — típicamente cinco a diez minutos. Bases pequeñas (hasta algunos GB) migran en una tarde; bases grandes piden ventana coordinada.",[12,24117,24118,24121],{},[27,24119,24120],{},"¿Postgres gestionado en esos tres es bueno?","\nRender Postgres es decente, con backup automático y versión actualizada — equivalente al Heroku Postgres clásico. Railway Postgres vía template funciona, pero el backup es más manual y la configuración default es conservadora. Fly.io no tiene Postgres gestionado propio; corres como app, lo que da control y responsabilidad. Para equipo que no quiere cuidar de base, Render lleva en ese aspecto. Para equipo que prefiere control, Fly.io.",[12,24123,24124,24127],{},[27,24125,24126],{},"¿Cuál de esos tiene soporte en portugués?","\nNinguno oficialmente. Documentación es toda en inglés, soporte por chat\u002Fe-mail es en inglés. Hay comunidades no-oficiales en PT-BR en Discord y en Twitter para cada uno, pero la mayoría de los tickets serios los abres en inglés. Para equipo incómodo con eso, es variable que pesa.",[12,24129,24130,24133],{},[27,24131,24132],{},"¿Y performance para app Rails \u002F Django \u002F Node?","\nPara los tres frameworks los tres PaaS funcionan bien. Render tiene buildpack Rails maduro y corre Sidekiq fácil. Railway detecta Django y Node automáticamente vía templates. Fly.io tiene documentación específica para Rails y para Phoenix, con deploy guides oficiales. La diferencia práctica aparece en detalles: Rails con asset pipeline pesado queda más rápido en Render por el build cache predecible; Node con workers en background gana en Railway por el pay-as-you-go; cualquier framework gana en Fly.io si el usuario está en Brasil por el GRU.",[12,24135,24136,24139,24140,24143],{},[27,24137,24138],{},"¿Preview deploys por PR funcionan en los tres?","\nSí en los tres, con matices. Render tiene el mejor: cada PR se vuelve una URL temporal automáticamente, sin configuración extra. Railway ofrece vía integración con el repositorio, configuración simple. Fly.io hace vía CLI (",[231,24141,24142],{},"fly deploy --config preview.toml",") y exige un poco más de setup manual o un workflow de CI personalizado. Para equipo que prioriza preview deploys como parte del code review, Render es el más fluido.",[19,24145,3310],{"id":3309},[12,24147,24148],{},"La elección entre Render, Railway y Fly.io no tiene respuesta universal. Render es el conservador predecible. Railway es el experimentador con UI bonita. Fly.io es el técnico con ventaja real de latencia para Brasil. Los tres son honestos sobre lo que son, y los tres tienen el mismo destino estructural: a partir de cierto punto de crecimiento, el coste en USD escala más rápido que tu ingreso en moneda local, y el auto-hospedado empieza a tener sentido.",[12,24150,24151],{},"Cuando ese punto llegue, considera HeroCtl. Tres servidores Linux, alta disponibilidad real entre ellos, certificados automáticos, panel web embebido, sin ceremonia operacional. Plan Community gratuito para siempre, planes Business y Enterprise para cuando el equipo necesite SSO, auditoría y soporte con SLA. Sin cambio retroactivo de contrato.",[12,24153,22434],{},[224,24155,24157],{"className":24156,"code":5318,"language":2530},[2528],[231,24158,5318],{"__ignoreMap":229},[12,24160,24161,24162,24164,24165,24167],{},"Si quieres leer antes, dos posts complementarios: ",[3337,24163,19774],{"href":19773}," cubre la tesis general de cuándo abandonar el PaaS hospedado, y ",[3337,24166,15787],{"href":14883}," entra en el mérito de qué orquestador tiene sentido para equipo pequeño fuera de los tres PaaS de este artículo.",[12,24169,24170],{},"La elección buena es la que cabe en tu etapa ahora, no la que parece sofisticada. Empieza simple, migra cuando el coste lo justifique, y nunca antes.",{"title":229,"searchDepth":244,"depth":244,"links":24172},[24173,24174,24175,24176,24177,24178,24179,24180,24181,24182],{"id":23657,"depth":244,"text":23658},{"id":23684,"depth":244,"text":23685},{"id":23729,"depth":244,"text":23730},{"id":23761,"depth":244,"text":23762},{"id":17388,"depth":244,"text":17389},{"id":23999,"depth":244,"text":24000},{"id":24033,"depth":244,"text":24034},{"id":24064,"depth":244,"text":24065},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"2026-02-12","Los tres PaaS hospedados que más devs usan para escapar de Heroku. Cada uno tiene tradeoff distinto. Análisis honesto de cuándo quedarse en cada uno y cuándo partir hacia auto-hospedado.",{},"\u002Fes\u002Fblog\u002Frender-vs-railway-vs-fly-io",{"title":23643,"description":24184},{"loc":24186},"es\u002Fblog\u002Frender-vs-railway-vs-fly-io",[24191,24192,24193,24194,8775],"render","railway","fly-io","paas","rbCct_DpiO_5MQUmW4Va9BUhQ0K-LeWLQ1ZbuFX6TMM",{"id":24197,"title":24198,"author":7,"body":24199,"category":8761,"cover":3380,"date":25342,"description":25343,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":25344,"navigation":411,"path":25345,"readingTime":4402,"seo":25346,"sitemap":25347,"stem":25348,"tags":25349,"__hash__":25353},"blog_es\u002Fes\u002Fblog\u002Falternativa-vercel-auto-hospedada.md","Alternativa a Vercel: alojar Next.js sin lock-in",{"type":9,"value":24200,"toc":25315},[24201,24204,24207,24211,24214,24246,24249,24252,24256,24260,24263,24266,24269,24273,24276,24279,24290,24301,24318,24329,24333,24336,24339,24363,24366,24370,24373,24377,24380,24386,24392,24398,24401,24405,24408,24411,24422,24425,24428,24432,24435,24438,24444,24447,24450,24454,24457,24674,24677,24681,24684,24690,24696,24702,24708,24711,24715,24718,24722,24760,24763,24767,24781,24825,24832,24941,24944,24948,24951,24990,24993,24997,25000,25036,25040,25043,25050,25053,25057,25060,25091,25094,25098,25101,25122,25125,25129,25132,25137,25156,25161,25177,25183,25186,25188,25194,25203,25217,25227,25249,25264,25270,25272,25275,25278,25281,25297,25300,25309,25312],[12,24202,24203],{},"Vercel es el mejor producto de DX que existe para Next.js. Build automático en cada push, preview deploys con URL única por commit, edge runtime que corre cerca del usuario, ISR funcionando con una línea de configuración, analytics y Web Vitals integrados sin instalar nada. Para quien empieza una aplicación Next.js en solitario, es objetivamente la mejor elección técnica.",[12,24205,24206],{},"La cuenta empieza a doler en tres puntos previsibles. Este post mapea esos puntos con números reales, defiende a Vercel donde acierta y muestra tres rutas de salida — cada una con su trade-off. Al final, un paso a paso de migración técnica y un cálculo concreto de cuánto ahorra un equipo al salir.",[19,24208,24210],{"id":24209},"donde-vercel-acierta","Donde Vercel acierta",[12,24212,24213],{},"Vale empezar por la parte difícil de admitir. Vercel resuelve problemas reales que otros proveedores no resuelven con la misma elegancia:",[2735,24215,24216,24222,24228,24234,24240],{},[70,24217,24218,24221],{},[27,24219,24220],{},"Zero-config para Next.js."," El equipo de Vercel mantiene el framework. Cada nueva release tiene soporte probado en el proveedor antes de volverse GA. No necesitas configurar adapter, runtime, build cache, nada.",[70,24223,24224,24227],{},[27,24225,24226],{},"Preview deploys por commit."," Cada pull request abre una URL pública aislada con el build de ese commit. Diseñador revisa, PM aprueba, QA prueba — sin levantar staging compartido.",[70,24229,24230,24233],{},[27,24231,24232],{},"Edge functions globales."," El código corre en más de 30 regiones simultáneamente. Para usuarios en São Paulo, la latencia de cold start es menor que la de muchos servidores dedicados en GRU.",[70,24235,24236,24239],{},[27,24237,24238],{},"ISR y SSG out-of-the-box."," Página estática con revalidación programada funciona sin configurar CDN externa, sin invalidación manual.",[70,24241,24242,24245],{},[27,24243,24244],{},"Analytics y Web Vitals nativos."," Sin instalar script de tercero, sin añadir peso al bundle, métricas reales de Core Web Vitals en producción.",[12,24247,24248],{},"Para un solo dev con un SaaS de US$5k MRR, con app pequeña y tráfico controlado, Vercel cuesta US$20\u002Fmes y libera al desarrollador para escribir producto. Es la elección correcta. No hay ironía en esa frase.",[12,24250,24251],{},"El problema es lo que pasa después de que el producto crece.",[19,24253,24255],{"id":24254},"los-tres-puntos-donde-duele","Los tres puntos donde duele",[368,24257,24259],{"id":24258},"punto-1-coste-escalado-en-usd","Punto 1 — Coste escalado en USD",[12,24261,24262],{},"El plan Pro cuesta US$20 por desarrollador al mes como piso. Equipo de cinco personas empieza en US$100\u002Fmes solo de licencia, antes de cualquier tráfico o compute.",[12,24264,24265],{},"A partir de ahí el coste es por uso. Las funciones serverless cobran por GB-segundo de ejecución más invocación por petición. Tráfico de salida cobra por GB. Vercel KV, Vercel Postgres, Vercel Blob — cada servicio gestionado tiene su tabla de precios, todas en USD.",[12,24267,24268],{},"La consecuencia operacional es factura imprevisible. Tráfico estacional — Black Friday, lanzamiento de feature, mención en prensa — multiplica por diez el coste de ese mes. Para startup con revenue local y coste en dólar, el spread de margen desaparece primero. Para agencia que cobra al cliente en local y paga infra en dólar, el margen desaparece después.",[368,24270,24272],{"id":24271},"punto-2-lock-in-de-primitivas","Punto 2 — Lock-in de primitivas",[12,24274,24275],{},"Este es el punto que nadie ve hasta que necesita salir.",[12,24277,24278],{},"ISR (Incremental Static Regeneration) es una feature de Next.js, pero la implementación optimizada de Vercel usa CDN propietaria con invalidación de tag global. Auto-hospedado, ISR funciona localmente — cada nodo tiene su copia de la caché en disco. Para invalidar una tag en tres nodos necesitas orquestación explícita.",[12,24280,24281,24282,24285,24286,24289],{},"Edge runtime usa primitivas al estilo CloudFlare Workers — ",[231,24283,24284],{},"fetch"," global, sin acceso a ",[231,24287,24288],{},"fs",", sin módulos Node nativos. Código escrito para edge no corre directamente en Node tradicional sin refactor.",[12,24291,24292,24293,24296,24297,24300],{},"Image Optimization corre en la infra de Vercel. Le mandas ",[231,24294,24295],{},"\u003CImage src=\"\u002Ffoo.jpg\" \u002F>"," y el proveedor entrega WebP redimensionado, con caché global. Auto-hospedado, necesitas correr ",[231,24298,24299],{},"sharp"," en el build, o usar un proxy de imagen dedicado, o desactivar la feature.",[12,24302,24303,24304,2630,24307,24309,24310,24313,24314,24317],{},"Vercel KV, Postgres y Blob son wrappers de Upstash Redis, Neon Postgres y almacenamiento S3-compatible con SDK propio. Migrar de ",[231,24305,24306],{},"@vercel\u002Fkv",[231,24308,7367],{}," directo es una tarde de refactor. Migrar de ",[231,24311,24312],{},"@vercel\u002Fpostgres"," a cliente estándar es otra tarde. Migrar de ",[231,24315,24316],{},"@vercel\u002Fblob"," a S3 implica revisar cada upload en la app.",[12,24319,24320,24321,24324,24325,24328],{},"Ninguna de esas barreras es infranqueable. Pero salir de Vercel no es ",[231,24322,24323],{},"git remote set-url"," seguido de ",[231,24326,24327],{},"vercel logout",". Es un sprint de refactor para una app de tamaño medio.",[368,24330,24332],{"id":24331},"punto-3-bandwidth-y-funciones-fuera-de-control","Punto 3 — Bandwidth y funciones fuera de control",[12,24334,24335],{},"Vercel no tiene cap rígido por defecto en el plan Pro. Defines alertas de presupuesto, pero la aplicación sigue sirviendo hasta alcanzar el límite — y el límite es configurable hacia arriba, no hacia abajo.",[12,24337,24338],{},"Los tres escenarios malos son previsibles:",[2735,24340,24341,24347,24353],{},[70,24342,24343,24346],{},[27,24344,24345],{},"DDoS leve."," Mil peticiones por segundo durante una hora golpean en volumen de bandwidth e invocación que rutinariamente pasa de US$200 en un plan normal. Vercel tiene protección contra ataques masivos, pero el umbral para activar la defensa es alto.",[70,24348,24349,24352],{},[27,24350,24351],{},"Post viral."," Tu página entra en Hacker News o el front de Reddit, y quinientas mil personas acceden en un día. El coste cae sobre ti, no sobre el anunciante.",[70,24354,24355,24358,24359,24362],{},[27,24356,24357],{},"Bug en loop."," Función en producción con ",[231,24360,24361],{},"setInterval"," que olvidaste limpiar, o ruta que se llama a sí misma recursivamente en SSR — descubierto en la factura.",[12,24364,24365],{},"Descubres el destrozo cuando llega la tarjeta. El camino de recurso existe, pero es caso a caso y depende de la buena voluntad del proveedor. No es una garantía contractual de techo.",[19,24367,24369],{"id":24368},"las-tres-rutas-de-salida","Las tres rutas de salida",[12,24371,24372],{},"Salir de Vercel no significa saltar a Kubernetes. Hay un espectro, y cada peldaño cambia una cosa por otra.",[368,24374,24376],{"id":24375},"ruta-a-hospedado-mas-previsible","Ruta A — Hospedado, más previsible",[12,24378,24379],{},"Render, Railway y Fly.io ocupan esa franja. Sigues pagando por instancia en USD, sigues confiando en el proveedor para disponibilidad, sigues teniendo panel web y CI\u002FCD integrado. La diferencia es el modelo de cobro.",[12,24381,24382,24385],{},[27,24383,24384],{},"Render."," Precio fijo por instancia al mes. Web service básico US$7\u002Fmes, instancia mayor US$25-85\u002Fmes. Latencia decente para São Paulo vía Render-Cloud en la región este de EE.UU. Tiene free tier limitado para proyectos personales. Soporte para Next.js standalone directo, sin adapter custom.",[12,24387,24388,24391],{},[27,24389,24390],{},"Railway."," Modelo por uso (CPU + memoria + bandwidth) con cap configurable. Precio previsible porque defines el techo. Buena para MVP corriendo barato, escala hacia arriba cuando lo necesita. UX de consola es excelente.",[12,24393,24394,24397],{},[27,24395,24396],{},"Fly.io."," Multi-region edge sin cobro separado por función. Subes la aplicación y corre en N regiones con el mismo precio. Para app que necesita presencia global pero no quiere pagar tabla de función, es la elección más obvia.",[12,24399,24400],{},"Trade-off de la Ruta A: sigues pagando en USD, sigues dependiendo de un único proveedor para disponibilidad, sigues teniendo que aceptar su tabla de precios cuando cambia. Pero saliste del modelo serverless-por-invocación y ganaste previsibilidad de coste. Para muchos equipos, es suficiente.",[368,24402,24404],{"id":24403},"ruta-b-auto-hospedado-simple","Ruta B — Auto-hospedado simple",[12,24406,24407],{},"Los paneles de orquestación modernos se volvieron categoría en los últimos dos años. Coolify, Dokploy, Kamal — cada uno con su filosofía, todos compartiendo el mismo modelo: instala panel en un servidor único, conecta repositorio, despliega aplicación.",[12,24409,24410],{},"Los números cambian de régimen en esa ruta. Un servidor cloud en Hetzner cuesta alrededor de €5\u002Fmes. Ese servidor único aloja cómodamente cinco aplicaciones Next.js de tamaño medio, más una base Postgres pequeña, más un Redis. La DX baja a \"instala panel, conecta repo, elige dominio, despliega\". No tiene build cache global, no tiene preview deploy automático en cada commit (depende de configuración extra), no tiene edge global.",[12,24412,24413,24414,24417,24418,24421],{},"El detalle técnico que hace viable la ruta es el build standalone de Next.js. Añadiendo ",[231,24415,24416],{},"output: 'standalone'"," en ",[231,24419,24420],{},"next.config.js",", el build genera un servidor Node compacto con todas las dependencias necesarias copiadas dentro. La imagen Docker resultante queda alrededor de 150 MB. Cada instancia de la aplicación consume aproximadamente 100 MB de RAM en idle, escalando según tráfico. Cinco apps Next.js en un servidor de 4 GB sobra memoria.",[12,24423,24424],{},"Trade-off de la Ruta B: pierdes edge global. Usuario en Tokio accediendo a tu app en SP va a sentir latencia. Pierdes preview deploy automático por commit (necesita configurarse manualmente, o usar panel que lo soporte). Ganas previsibilidad total de coste: la factura del servidor es la misma todos los meses, independiente del tráfico.",[12,24426,24427],{},"Para equipo con clientes locales, la pérdida de edge global es, en la práctica, irrelevante. Latencia São Paulo → São Paulo es menor que latencia São Paulo → Vercel-edge-São Paulo, en la mayoría de las mediciones.",[368,24429,24431],{"id":24430},"ruta-c-auto-hospedado-con-alta-disponibilidad","Ruta C — Auto-hospedado con alta disponibilidad",[12,24433,24434],{},"Aquí vive HeroCtl. La diferencia con la Ruta B es el tipo de garantía que puedes dar al cliente.",[12,24436,24437],{},"Los paneles auto-hospedados simples son, por construcción, single-server. Cuando ese servidor cae, el cliente cae con él. Para app personal o MVP, es aceptable. Para contrato B2B con SLA escrito, no lo es.",[12,24439,24440,24441,24443],{},"La Ruta C elimina ese punto único de falla colocando 3 o 4 servidores en un mismo cluster, con plano de control replicado entre ellos. Si un servidor muere, los otros siguen sirviendo — y el cluster reagenda automáticamente los contenedores que estaban en el nodo muerto a otros nodos saludables. La elección de nuevo coordinador toma cerca de 7 segundos después de un ",[231,24442,23217],{}," en el servidor que estaba liderando.",[12,24445,24446],{},"Router integrado emite certificados Let's Encrypt automáticamente, hace rolling update sin ventana de mantenimiento, hace health check en cada contenedor. No montas cinco productos para tener ingress + TLS + métricas + logs — viene todo en el mismo binario.",[12,24448,24449],{},"La franja de aplicación es específica: cuando la startup necesita SLA escrito de cliente (generalmente por encima de US$10k MRR o en contrato B2B serio), la Ruta B empieza a quedar arriesgada. Un único servidor, incluso confiable, es una narrativa difícil de defender cuando el cliente pregunta \"¿y si ese servidor cae?\". La Ruta C resuelve eso sin volverse Kubernetes.",[19,24451,24453],{"id":24452},"lado-a-lado","Lado a lado",[12,24455,24456],{},"La tabla es la versión honesta de la decisión. No hay columna sin matiz.",[119,24458,24459,24475],{},[122,24460,24461],{},[125,24462,24463,24465,24467,24469,24471,24473],{},[128,24464,2983],{},[128,24466,15030],{},[128,24468,15024],{},[128,24470,15027],{},[128,24472,2771],{},[128,24474,2995],{},[141,24476,24477,24497,24513,24529,24546,24563,24580,24594,24608,24627,24641,24657],{},[125,24478,24479,24482,24485,24488,24491,24494],{},[146,24480,24481],{},"Coste mínimo USD\u002Fmes",[146,24483,24484],{},"~US$20\u002Fdev",[146,24486,24487],{},"~US$7",[146,24489,24490],{},"~US$5",[146,24492,24493],{},"~US$6 (1 VPS)",[146,24495,24496],{},"~US$24 (3-4 VPS)",[125,24498,24499,24502,24504,24506,24509,24511],{},[146,24500,24501],{},"Coste previsible",[146,24503,3059],{},[146,24505,3065],{},[146,24507,24508],{},"Sí (con cap)",[146,24510,3065],{},[146,24512,3065],{},[125,24514,24515,24518,24521,24523,24525,24527],{},[146,24516,24517],{},"Edge global",[146,24519,24520],{},"Sí (30+ regiones)",[146,24522,3059],{},[146,24524,3059],{},[146,24526,3059],{},[146,24528,3059],{},[125,24530,24531,24534,24537,24540,24542,24544],{},[146,24532,24533],{},"ISR Next.js",[146,24535,24536],{},"Nativo, optimizado",[146,24538,24539],{},"Funciona local",[146,24541,24539],{},[146,24543,24539],{},[146,24545,24539],{},[125,24547,24548,24551,24554,24557,24559,24561],{},[146,24549,24550],{},"Image Optimization",[146,24552,24553],{},"Hospedado",[146,24555,24556],{},"Build\u002Fproxy",[146,24558,24556],{},[146,24560,24556],{},[146,24562,24556],{},[125,24564,24565,24568,24571,24574,24576,24578],{},[146,24566,24567],{},"Preview deploys",[146,24569,24570],{},"Automático por commit",[146,24572,24573],{},"Manual\u002Fbranch",[146,24575,24573],{},[146,24577,3078],{},[146,24579,3078],{},[125,24581,24582,24584,24586,24588,24590,24592],{},[146,24583,16381],{},[146,24585,3065],{},[146,24587,3065],{},[146,24589,3065],{},[146,24591,3065],{},[146,24593,3065],{},[125,24595,24596,24598,24600,24602,24604,24606],{},[146,24597,7104],{},[146,24599,3065],{},[146,24601,3062],{},[146,24603,3062],{},[146,24605,3059],{},[146,24607,7017],{},[125,24609,24610,24613,24616,24619,24622,24624],{},[146,24611,24612],{},"SLA contractual",[146,24614,24615],{},"99,99% (Enterprise)",[146,24617,24618],{},"99,95%",[146,24620,24621],{},"99,9%",[146,24623,11997],{},[146,24625,24626],{},"Configurable (tú operas)",[125,24628,24629,24631,24633,24635,24637,24639],{},[146,24630,16336],{},[146,24632,3065],{},[146,24634,3065],{},[146,24636,3065],{},[146,24638,3059],{},[146,24640,3065],{},[125,24642,24643,24646,24648,24650,24652,24654],{},[146,24644,24645],{},"Soporte en español",[146,24647,3059],{},[146,24649,3059],{},[146,24651,3059],{},[146,24653,7228],{},[146,24655,24656],{},"Sí (Business)",[125,24658,24659,24662,24665,24667,24669,24672],{},[146,24660,24661],{},"Lock-in de primitivas",[146,24663,24664],{},"Alto (KV\u002FPostgres\u002FBlob\u002FEdge)",[146,24666,7162],{},[146,24668,7162],{},[146,24670,24671],{},"Ninguno",[146,24673,24671],{},[12,24675,24676],{},"La columna que importa cambia según la etapa. Solo dev mira la primera línea. Equipo creciendo mira \"coste previsible\". Startup con cliente B2B mira \"SLA contractual\" y \"alta disponibilidad real\".",[19,24678,24680],{"id":24679},"cuando-quedarse-en-vercel","Cuándo quedarse en Vercel",[12,24682,24683],{},"La honestidad es el mecanismo de defensa de cualquier comparativa. Cuatro escenarios donde salir es perjuicio:",[12,24685,24686,24689],{},[27,24687,24688],{},"Solo dev haciendo SaaS pequeño en USD con revenue saludable."," Si la aplicación ya cobra en dólar y el revenue pasa de US$30k MRR, US$100-300\u002Fmes de Vercel es ruido contable. El tiempo gastado migrando vale más que el ahorro.",[12,24691,24692,24695],{},[27,24693,24694],{},"Marketing site Next.js de baja complejidad."," Página estática con formulario de contacto. Vercel hace eso gratis en el plan Hobby, y el tier gratuito no tiene límite duro para ese perfil de tráfico. Cambiar a auto-hospedado es mover el problema en lugar de resolverlo.",[12,24697,24698,24701],{},[27,24699,24700],{},"Equipo pequeño sin nadie para cuidar de infra, con revenue justificándolo."," Vercel es, en el fondo, tercerización de operación. Si tu margen soporta el precio, y tu único dev sénior necesita estar escribiendo producto, mantener Vercel es decisión de asignación de tiempo, no de tecnología.",[12,24703,24704,24707],{},[27,24705,24706],{},"Edge global crítico para UX."," Aplicación con usuarios en tres continentes donde latencia por debajo de 50ms globalmente es parte del producto. Auto-hospedado con presencia global es caro y operacionalmente complicado. Vercel resuelve.",[12,24709,24710],{},"Si estás en cualquiera de esos cuatro perfiles, cierra esta pestaña y vuelve al código. El resto del post no es para ti todavía.",[19,24712,24714],{"id":24713},"migracion-tecnica-de-vercel-a-auto-hospedado","Migración técnica de Vercel a auto-hospedado",[12,24716,24717],{},"Para quien decidió salir, el camino tiene siete pasos. Cada uno toma entre una tarde y dos días, dependiendo del tamaño de la app.",[368,24719,24721],{"id":24720},"_1-inventario","1. Inventario",[12,24723,24724,24725,24728,24729,6562,24731,571,24733,571,24735,571,24737,571,24740,24743,24744,24747,24748,24751,24752,24755,24756,24759],{},"Antes de mover cualquier cosa, mapea lo que está en uso. Lista de variables de entorno del proyecto Vercel — copia todo en un archivo ",[231,24726,24727],{},".env.example"," versionado. Lista de dependencias Vercel-only que aparecen en ",[231,24730,8506],{},[231,24732,24306],{},[231,24734,24312],{},[231,24736,24316],{},[231,24738,24739],{},"@vercel\u002Fanalytics",[231,24741,24742],{},"@vercel\u002Fspeed-insights",". Lista de features Next.js que dependen de runtime específico: ISR (busca por ",[231,24745,24746],{},"revalidate"," en el código), middleware (¿existe ",[231,24749,24750],{},"middleware.ts"," en la raíz?), edge runtime (",[231,24753,24754],{},"export const runtime = 'edge'","), Image Optimization (",[231,24757,24758],{},"\u003CImage \u002F>"," en cuántas rutas?).",[12,24761,24762],{},"El inventario no cambia nada. Pero decide el orden de los siguientes pasos.",[368,24764,24766],{"id":24765},"_2-build-standalone","2. Build standalone",[12,24768,2662,24769,24417,24771,24773,24774,24777,24778,622],{},[231,24770,24416],{},[231,24772,24420],{},". Ese modo hace que el build copie a ",[231,24775,24776],{},".next\u002Fstandalone\u002F"," solo las dependencias de producción realmente usadas, más un servidor Node mínimo (",[231,24779,24780],{},"server.js",[224,24782,24784],{"className":374,"code":24783,"language":376,"meta":229,"style":229},"\u002F\u002F next.config.js\nmodule.exports = {\n  output: 'standalone',\n  \u002F\u002F demás opciones\n}\n",[231,24785,24786,24791,24805,24816,24821],{"__ignoreMap":229},[234,24787,24788],{"class":236,"line":237},[234,24789,24790],{"class":240},"\u002F\u002F next.config.js\n",[234,24792,24793,24796,24798,24801,24803],{"class":236,"line":244},[234,24794,24795],{"class":251},"module",[234,24797,101],{"class":387},[234,24799,24800],{"class":251},"exports",[234,24802,424],{"class":383},[234,24804,505],{"class":387},[234,24806,24807,24810,24813],{"class":236,"line":271},[234,24808,24809],{"class":387},"  output: ",[234,24811,24812],{"class":255},"'standalone'",[234,24814,24815],{"class":387},",\n",[234,24817,24818],{"class":236,"line":415},[234,24819,24820],{"class":240},"  \u002F\u002F demás opciones\n",[234,24822,24823],{"class":236,"line":434},[234,24824,1362],{"class":387},[12,24826,24827,24828,24831],{},"Build local con ",[231,24829,24830],{},"next build"," produce una carpeta de unos 150 MB. Dockerfile queda corto:",[224,24833,24835],{"className":20757,"code":24834,"language":20759,"meta":229,"style":229},"FROM node:20-alpine AS builder\nWORKDIR \u002Fapp\nCOPY package.json pnpm-lock.yaml .\u002F\nRUN corepack enable && pnpm install --frozen-lockfile\nCOPY . .\nRUN pnpm build\n\nFROM node:20-alpine\nWORKDIR \u002Fapp\nCOPY --from=builder \u002Fapp\u002F.next\u002Fstandalone .\u002F\nCOPY --from=builder \u002Fapp\u002F.next\u002Fstatic .\u002F.next\u002Fstatic\nCOPY --from=builder \u002Fapp\u002Fpublic .\u002Fpublic\nEXPOSE 3000\nCMD [\"node\", \"server.js\"]\n",[231,24836,24837,24848,24854,24861,24868,24874,24881,24885,24892,24898,24905,24912,24919,24925],{"__ignoreMap":229},[234,24838,24839,24841,24844,24846],{"class":236,"line":237},[234,24840,20766],{"class":383},[234,24842,24843],{"class":387}," node:20-alpine ",[234,24845,20772],{"class":383},[234,24847,20775],{"class":387},[234,24849,24850,24852],{"class":236,"line":244},[234,24851,20780],{"class":383},[234,24853,20783],{"class":387},[234,24855,24856,24858],{"class":236,"line":271},[234,24857,20788],{"class":383},[234,24859,24860],{"class":387}," package.json pnpm-lock.yaml .\u002F\n",[234,24862,24863,24865],{"class":236,"line":415},[234,24864,20796],{"class":383},[234,24866,24867],{"class":387}," corepack enable && pnpm install --frozen-lockfile\n",[234,24869,24870,24872],{"class":236,"line":434},[234,24871,20788],{"class":383},[234,24873,20806],{"class":387},[234,24875,24876,24878],{"class":236,"line":459},[234,24877,20796],{"class":383},[234,24879,24880],{"class":387}," pnpm build\n",[234,24882,24883],{"class":236,"line":464},[234,24884,412],{"emptyLinePlaceholder":411},[234,24886,24887,24889],{"class":236,"line":479},[234,24888,20766],{"class":383},[234,24890,24891],{"class":387}," node:20-alpine\n",[234,24893,24894,24896],{"class":236,"line":484},[234,24895,20780],{"class":383},[234,24897,20783],{"class":387},[234,24899,24900,24902],{"class":236,"line":490},[234,24901,20788],{"class":383},[234,24903,24904],{"class":387}," --from=builder \u002Fapp\u002F.next\u002Fstandalone .\u002F\n",[234,24906,24907,24909],{"class":236,"line":508},[234,24908,20788],{"class":383},[234,24910,24911],{"class":387}," --from=builder \u002Fapp\u002F.next\u002Fstatic .\u002F.next\u002Fstatic\n",[234,24913,24914,24916],{"class":236,"line":529},[234,24915,20788],{"class":383},[234,24917,24918],{"class":387}," --from=builder \u002Fapp\u002Fpublic .\u002Fpublic\n",[234,24920,24921,24923],{"class":236,"line":535},[234,24922,20861],{"class":383},[234,24924,20864],{"class":387},[234,24926,24927,24929,24931,24934,24936,24939],{"class":236,"line":546},[234,24928,20869],{"class":383},[234,24930,20872],{"class":387},[234,24932,24933],{"class":255},"\"node\"",[234,24935,571],{"class":387},[234,24937,24938],{"class":255},"\"server.js\"",[234,24940,9534],{"class":387},[12,24942,24943],{},"Imagen final alrededor de 180 MB. Corre igual en cualquier entorno que soporte contenedor.",[368,24945,24947],{"id":24946},"_3-sustitucion-de-almacenamiento","3. Sustitución de almacenamiento",[12,24949,24950],{},"Cada servicio gestionado de Vercel tiene alternativa directa:",[2735,24952,24953,24964,24978],{},[70,24954,24955,24958,24959,2630,24961,24963],{},[27,24956,24957],{},"Vercel KV → Redis."," Levantas un Redis en el cluster (HeroCtl lo corre como job común) o usas Upstash hospedado. Cliente cambia de ",[231,24960,24306],{},[231,24962,7367],{},". La API es parecida; el adapter se puede esconder detrás de una función.",[70,24965,24966,24969,24970,2630,24972,5839,24975,101],{},[27,24967,24968],{},"Vercel Postgres → Postgres."," Postgres en el cluster (job común) o Supabase\u002FNeon hospedados. Migration scripts siguen iguales. Cliente cambia de ",[231,24971,24312],{},[231,24973,24974],{},"pg",[231,24976,24977],{},"postgres.js",[70,24979,24980,24983,24984,2630,24986,24989],{},[27,24981,24982],{},"Vercel Blob → S3-compatible."," CloudFlare R2 (sin cobro de salida), Backblaze B2, o MinIO en el propio cluster. Cliente cambia de ",[231,24985,24316],{},[231,24987,24988],{},"@aws-sdk\u002Fclient-s3"," apuntando al endpoint custom.",[12,24991,24992],{},"La regla general: haz la sustitución en una rama separada, con tests de integración corriendo contra el servicio nuevo, antes de tocar producción.",[368,24994,24996],{"id":24995},"_4-image-optimization","4. Image Optimization",[12,24998,24999],{},"Tres caminos, elige uno:",[2735,25001,25002,25013,25021],{},[70,25003,25004,25009,25010,25012],{},[27,25005,25006,25008],{},[231,25007,24299],{}," directo en el servidor."," Next.js detecta ",[231,25011,24299],{}," instalado y lo usa para Image Optimization local. Funciona, pero consume CPU del mismo proceso que sirve la aplicación.",[70,25014,25015,25020],{},[27,25016,25017,101],{},[231,25018,25019],{},"next-image-export-optimizer"," Pre-optimiza todas las imágenes en el build. Bueno para blog o site con imágenes estáticas. Inviable para app con upload de usuario.",[70,25022,25023,2578,25026,5839,25029,25032,25033,25035],{},[27,25024,25025],{},"Proxy de imagen dedicado.",[231,25027,25028],{},"imgproxy",[231,25030,25031],{},"imageflow"," corriendo como servicio separado. URL del ",[231,25034,24758],{}," apunta a ese proxy. Resuelve cualquier caso de uso, cuesta un job más en el cluster.",[368,25037,25039],{"id":25038},"_5-isr","5. ISR",[12,25041,25042],{},"Auto-hospedado, ISR funciona — Next.js standalone implementa la caché local en disco. El punto frágil es la invalidación multi-region.",[12,25044,25045,25046,25049],{},"Cluster con 3 nodos significa 3 copias de la caché en disco, cada una con expiración propia. Para blog o site cuyo contenido cambia algunas veces al día, eso es aceptable: la inconsistencia de algunos segundos entre nodos es invisible para el usuario. Para dashboard de e-commerce con precio actualizando cada minuto, necesitas invalidación coordinada — generalmente vía webhook que llama ",[231,25047,25048],{},"revalidatePath"," en todos los nodos simultáneamente.",[12,25051,25052],{},"La mayoría de los casos cae en el primer perfil. No se vuelve el problema que parece a primera vista.",[368,25054,25056],{"id":25055},"_6-cicd","6. CI\u002FCD",[12,25058,25059],{},"Cambiar el auto-deploy de Vercel por pipeline propio:",[2735,25061,25062,25075,25081],{},[70,25063,25064,25067,25068,571,25071,25074],{},[27,25065,25066],{},"Build:"," GitHub Actions (o GitLab CI, o Jenkins) corre en cada push. ",[231,25069,25070],{},"pnpm install",[231,25072,25073],{},"pnpm build",", genera imagen Docker.",[70,25076,25077,25080],{},[27,25078,25079],{},"Push:"," registry de imagen (ECR, Docker Hub, GHCR). Tag por commit SHA o fecha.",[70,25082,25083,25086,25087,25090],{},[27,25084,25085],{},"Deploy:"," llamada de API contra el orquestrador (",[231,25088,25089],{},"heroctl deploy job.json"," o equivalente). Rolling update sin downtime.",[12,25092,25093],{},"Tiempo de pipeline para app medio queda alrededor de 4-6 minutos. Vercel lo hace en 2-3 minutos. La diferencia es real, pero no es catastrófica.",[368,25095,25097],{"id":25096},"_7-cutover","7. Cutover",[12,25099,25100],{},"Última etapa, y la más delicada:",[2735,25102,25103,25110,25113,25116,25119],{},[70,25104,25105,25106,25109],{},"Sube la versión auto-hospedada apuntando a un dominio temporal (",[231,25107,25108],{},"new.tuapp.com",", por ejemplo).",[70,25111,25112],{},"Corre en paralelo durante 7 días. Usuarios internos prueban. Tráfico de canario dirigido por flag.",[70,25114,25115],{},"Compara métricas: error rate, latencia p95, coste de infra proyectado.",[70,25117,25118],{},"Si la parity está ok, cambia DNS principal para apuntar al nuevo backend. TTL bajo (60s) ayuda en el rollback rápido.",[70,25120,25121],{},"Mantén Vercel encendido por otros 7 días. Solo desactiva el proyecto después de confirmar que nadie está en el DNS antiguo.",[12,25123,25124],{},"Migración total para app medio toma 2-3 semanas con un dev dedicado. Para app pequeño, una semana. Para monolito Next.js gigante con 50 rutas y middleware complejo, un trimestre.",[19,25126,25128],{"id":25127},"calculo-concreto","Cálculo concreto",[12,25130,25131],{},"Números para cerrar el argumento. Equipo de cinco devs con aplicación Next.js de tamaño medio (50 rutas, base Postgres, storage de imágenes, tráfico de 2 millones de peticiones\u002Fmes).",[12,25133,25134],{},[27,25135,25136],{},"Escenario Vercel:",[2735,25138,25139,25142,25145,25148,25151],{},[70,25140,25141],{},"5 × Pro (US$20\u002Fdev\u002Fmes) = US$100\u002Fmes",[70,25143,25144],{},"Bandwidth e function invocations (estimación con tráfico informado): US$50-200\u002Fmes",[70,25146,25147],{},"Vercel Postgres (instancia producción pequeña): US$30\u002Fmes",[70,25149,25150],{},"Vercel Blob (50 GB almacenado, 100 GB transferencia): US$20\u002Fmes",[70,25152,25153],{},[27,25154,25155],{},"Total: US$200-400\u002Fmes",[12,25157,25158],{},[27,25159,25160],{},"Escenario HeroCtl Community en 4 servidores Hetzner:",[2735,25162,25163,25166,25169,25172],{},[70,25164,25165],{},"4 × CX22 (€5,18\u002Fmes cada uno) = €21\u002Fmes",[70,25167,25168],{},"CloudFlare R2 (50 GB almacenado, sin cobro de salida): ~€5\u002Fmes",[70,25170,25171],{},"Postgres corriendo como job en el propio cluster: cero adicional",[70,25173,25174],{},[27,25175,25176],{},"Total: €25-30\u002Fmes",[12,25178,25179,25182],{},[27,25180,25181],{},"Diferencia: ~US$170-370\u002Fmes."," En 12 meses, US$2.000 a US$4.500 de ahorro. Equivalente a un mes de salario de dev en muchos mercados.",[12,25184,25185],{},"El ahorro paga una migración hecha en cuatro semanas en el primer año, y queda disponible como margen operacional en los siguientes.",[19,25187,7352],{"id":7351},[12,25189,25190,25193],{},[27,25191,25192],{},"¿HeroCtl corre Next.js directo?","\nSí. Build standalone genera imagen Docker, y HeroCtl orquesta cualquier imagen. No tiene adapter custom, no tiene template específico — el Dockerfile mostrado arriba funciona sin modificación.",[12,25195,25196,25199,25200,25202],{},[27,25197,25198],{},"¿E ISR sin CDN global?","\nFunciona localmente en cada nodo del cluster. Cluster con 3 nodos significa 3 cachés independientes con expiración propia. Para invalidación coordinada multi-nodo, usas ",[231,25201,25048],{}," llamado vía webhook en todos los nodos. Para la mayoría de los casos (blog, site institucional, dashboard con revalidación cada minuto), la inconsistencia transitoria es invisible.",[12,25204,25205,25208,25209,25212,25213,25216],{},[27,25206,25207],{},"¿Cómo hago preview deploys?","\nHeroCtl no tiene preview deploy automático por commit nativo, pero soporta múltiples versiones del mismo job corriendo lado a lado. Configuración común: pipeline crea un job con sufijo de la rama (",[231,25210,25211],{},"mi-app-feature-x","), con dominio temporal (",[231,25214,25215],{},"feature-x.preview.tuapp.com","), TLS automático por el router integrado. Cuando la rama se mergea y se borra, el job se despromueve. Quien quiere DX exacta de Vercel monta eso en 100-200 líneas de pipeline.",[12,25218,25219,25222,25223,25226],{},[27,25220,25221],{},"¿Sobreviven las edge functions?","\nLas edge functions usan primitivas al estilo CloudFlare Workers y no corren en Node tradicional. Auto-hospedado, las conviertes en rutas server-side normales (",[231,25224,25225],{},"export const runtime = 'nodejs'",") o las separas en servicios propios. El refactor es por archivo, generalmente entre 10 minutos y 2 horas dependiendo del código.",[12,25228,25229,25232,25234,25235,25238,25239,1523,25241,25243,25244,21703,25246,25248],{},[27,25230,25231],{},"¿Y si uso Vercel Postgres?",[231,25233,24312],{}," es wrapper de Neon Postgres. Cambias a ",[231,25236,25237],{},"@neondatabase\u002Fserverless"," (mantienes Neon hospedado), o ",[231,25240,24974],{},[231,25242,24977],{}," apuntando a un Postgres en el cluster. Schema migra directo vía ",[231,25245,5736],{},[231,25247,21218],{},". Para 95% de las apps, es una tarde de trabajo.",[12,25250,25251,25254,25255,25257,25258,25260,25261,25263],{},[27,25252,25253],{},"¿Vercel Image Optimization tiene sustituto?","\nTres opciones: ",[231,25256,24299],{}," directo en el servidor (funciona, consume CPU local), ",[231,25259,25019],{}," en el build (bueno para imágenes estáticas), proxy dedicado tipo ",[231,25262,25028],{}," corriendo como servicio separado (resuelve cualquier caso). Para app con upload de usuario, la tercera opción es la mejor.",[12,25265,25266,25269],{},[27,25267,25268],{},"¿Cuánto tarda la migración para app medio?","\nAplicación Next.js con 50 rutas, Postgres, storage y middleware: 2-3 semanas con un dev dedicado siguiendo el paso a paso de este post. Aplicación pequeña (10-15 rutas, sin storage gestionado): una semana. Monolito gigante con middleware complejo y dependencia fuerte de edge runtime: trimestre entero.",[19,25271,3310],{"id":3309},[12,25273,25274],{},"Vercel es una buena elección. Para muchos casos, es la elección correcta. El punto de este post no es \"Vercel es malo\" — es \"Vercel no es la única elección\". La mayoría de los equipos que miran la factura mensual y suspiran no están mirando hacia afuera porque su producto sea peor. Están mirando porque el ahorro, a escala de empresa, es lo suficientemente grande como para pagar una migración hecha con calma y que sobre caja.",[12,25276,25277],{},"La elección entre las tres rutas depende de dónde estás. Render y Railway resuelven el problema de previsibilidad sin cambiar mucho el modelo operacional. Coolify y Dokploy resuelven el coste radicalmente, a cambio de un único servidor. HeroCtl resuelve el coste y mantiene la alta disponibilidad real, a cambio de operar 3-4 servidores.",[12,25279,25280],{},"Si quieres probar la Ruta C en el camino más corto:",[224,25282,25283],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,25284,25285],{"__ignoreMap":229},[234,25286,25287,25289,25291,25293,25295],{"class":236,"line":237},[234,25288,1220],{"class":247},[234,25290,2958],{"class":251},[234,25292,5329],{"class":255},[234,25294,2964],{"class":383},[234,25296,2967],{"class":247},[12,25298,25299],{},"Levantas 3 servidores pequeños, instalas en cada uno, apuntas el dominio. Subes la aplicación Next.js como job. Verificas que el router integrado emitió certificado, que el rolling update funcionó, que matar un servidor no derribó el site. Después decides si el ahorro compensa.",[12,25301,25302,25303,25305,25306,25308],{},"Para leer más: ",[3337,25304,21746],{"href":6545}," explica la tesis general detrás del producto, y ",[3337,25307,19774],{"href":19773}," cubre la franja de uso adyacente — cuándo quieres DX tipo Heroku corriendo en tu infra, sin necesitar el nivel de HA de HeroCtl.",[12,25310,25311],{},"La intención, como siempre, es la misma: orquestación de contenedores, sin ceremonia.",[3351,25313,25314],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}",{"title":229,"searchDepth":244,"depth":244,"links":25316},[25317,25318,25323,25328,25329,25330,25339,25340,25341],{"id":24209,"depth":244,"text":24210},{"id":24254,"depth":244,"text":24255,"children":25319},[25320,25321,25322],{"id":24258,"depth":271,"text":24259},{"id":24271,"depth":271,"text":24272},{"id":24331,"depth":271,"text":24332},{"id":24368,"depth":244,"text":24369,"children":25324},[25325,25326,25327],{"id":24375,"depth":271,"text":24376},{"id":24403,"depth":271,"text":24404},{"id":24430,"depth":271,"text":24431},{"id":24452,"depth":244,"text":24453},{"id":24679,"depth":244,"text":24680},{"id":24713,"depth":244,"text":24714,"children":25331},[25332,25333,25334,25335,25336,25337,25338],{"id":24720,"depth":271,"text":24721},{"id":24765,"depth":271,"text":24766},{"id":24946,"depth":271,"text":24947},{"id":24995,"depth":271,"text":24996},{"id":25038,"depth":271,"text":25039},{"id":25055,"depth":271,"text":25056},{"id":25096,"depth":271,"text":25097},{"id":25127,"depth":244,"text":25128},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-02-04","Vercel cobra en USD, escala el coste serverless por petición y te empuja hacia sus primitivas. Para equipos hispanohablantes, la cuenta se pone fea rápido. Cómo ejecutar Next.js fuera.",{},"\u002Fes\u002Fblog\u002Falternativa-vercel-auto-hospedada",{"title":24198,"description":25343},{"loc":25345},"es\u002Fblog\u002Falternativa-vercel-auto-hospedada",[25350,25351,22492,14948,25352],"vercel","next-js","lock-in","-sHgkhm0KOi3vV3K5ZmOuvHPJSTctuyqQrWhDSy_tdw",{"id":25355,"title":25356,"author":7,"body":25357,"category":8761,"cover":3380,"date":25895,"description":25896,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":25897,"navigation":411,"path":25898,"readingTime":4402,"seo":25899,"sitemap":25900,"stem":25901,"tags":25902,"__hash__":25907},"blog_es\u002Fes\u002Fblog\u002Fheroctl-vs-kamal.md","HeroCtl vs Kamal: cuando necesitas más de un servidor",{"type":9,"value":25358,"toc":25878},[25359,25362,25368,25371,25375,25378,25381,25388,25394,25397,25401,25404,25424,25427,25430,25434,25437,25441,25444,25447,25450,25454,25460,25463,25477,25480,25484,25487,25490,25493,25497,25500,25503,25510,25514,25517,25537,25540,25543,25547,25550,25553,25556,25559,25562,25564,25676,25679,25683,25686,25692,25702,25708,25714,25718,25721,25731,25743,25756,25764,25791,25800,25802,25812,25818,25824,25830,25842,25851,25857,25859,25862,25865,25870,25873],[12,25360,25361],{},"En 2023 37signals publicó números que no combinaban con el discurso de la industria. La empresa salió de la nube pública para hospedar los propios productos en servidores dedicados, proyectó economía anual de aproximadamente tres millones de dólares y abrió el ferramental que usó para hacer esa migración. Ese ferramental ganó nombre — Kamal — y se volvió referencia rápida para un tipo de equipo que estaba cansado de la complejidad de orquestadores planetarios.",[12,25363,25364,25365,101],{},"DHH, socio de 37signals, popularizó la tesis alrededor de la herramienta con una frase corta: \"you don't need orchestration\". El argumento es elegante, factual y — para la mayoría de los equipos que él describe — verdadero. Deploy de aplicación Rails se había vuelto un máster en sistemas distribuidos sin que nadie hubiera pedido eso. Kamal es la respuesta legítima a una frustración legítima, y ocupa un nicho propio dentro del ",[3337,25366,25367],{"href":19773},"segmento de Heroku auto-hospedado en 2026",[12,25369,25370],{},"Este post no es sobre derrumbar esa tesis. Es sobre el momento exacto en el que deja de describir tu realidad. En algún punto entre el primer y el décimo cliente serio, la frase cambia de \"no necesitas orquestación\" a \"pasaste a necesitar y aún no te diste cuenta\". El síntoma suele ser un email a las tres de la mañana.",[19,25372,25374],{"id":25373},"la-filosofia-kamal-como-merece-ser-descrita","La filosofía Kamal, como merece ser descrita",[12,25376,25377],{},"Antes de cualquier crítica, vale la pena registrar lo que Kamal acierta — porque acierta mucho.",[12,25379,25380],{},"Tienes una aplicación dentro de un Dockerfile. Tienes una lista de servidores donde quieres que corra. Kamal toma esa lista, conecta a cada servidor por SSH, baja la imagen nueva, cambia el contenedor viejo por el nuevo y actualiza el router interno. No hay plano de control persistente. No hay agente residente en cada servidor con proceso propio. No hay base de datos de estado fuera del conjunto de servidores que ya tenías.",[12,25382,25383,25384,25387],{},"La configuración vive en un único archivo ",[231,25385,25386],{},"deploy.yml"," con tal vez cuarenta líneas. Corres un comando, y Kamal hace el trabajo en paralelo en los hosts. Cuando termina, desaparece — no hay servicio escuchando puerto 8080 esperando comandos futuros. Es deploy como una transacción SSH con checkpoints.",[12,25389,25390,25391,25393],{},"Esa minimización del estado externo es la virtud central. Para equipos de una a tres personas que ejecutan una aplicación monolítica en un único servidor, es difícil ganar. ",[3337,25392,2771],{"href":16704}," y los otros paneles modernos piden una base de datos propia, un agente propio, una interfaz web propia. Kamal pide dos ingredientes: SSH y Docker. Ya tenías los dos.",[12,25395,25396],{},"Estimamos que setenta y cinco por ciento de los equipos de aplicación web nunca necesitan más que eso. Si eres uno de ellos, cierra este post e instala Kamal. En serio.",[19,25398,25400],{"id":25399},"cuando-no-necesitas-orquestacion-es-verdad","Cuándo \"no necesitas orquestación\" es verdad",[12,25402,25403],{},"Algunos marcadores son honestos. Si tu operación cabe en esta lista, Kamal vence cualquier comparación que se pueda hacer con él:",[2735,25405,25406,25409,25412,25415,25418,25421],{},[70,25407,25408],{},"Un servidor único con holgura de recursos",[70,25410,25411],{},"Aplicación monolítica, sin dependencias internas en red privada entre servicios",[70,25413,25414],{},"Tráfico previsible, sin picos que exijan escalado horizontal de emergencia",[70,25416,25417],{},"Ventana de deploy ocasional, con hasta treinta segundos de degradación aceptable",[70,25419,25420],{},"Cliente final que no cobra contrato formal de disponibilidad",[70,25422,25423],{},"Una a tres personas cuidando de la infra, en medio expediente",[12,25425,25426],{},"Para ese perfil, cualquier herramienta con plano de control persistente es overhead injustificado. Kamal es, literalmente, un archivo de configuración más un binario cliente. No hay nada para mantener en el servidor además de Docker que ibas a instalar de cualquier manera.",[12,25428,25429],{},"La elegancia de ese enfoque es tal que muchos equipos con perfil ligeramente mayor que el descrito arriba siguen felices — y están en lo correcto. Migrar a un orquestador antes de que el dolor aparezca es gold-plating de infraestructura. La pregunta correcta no es \"¿tengo cluster?\", es \"¿qué dolor ya no logro ignorar?\".",[19,25431,25433],{"id":25432},"cuando-no-necesitas-orquestacion-empieza-a-doler","Cuándo \"no necesitas orquestación\" empieza a doler",[12,25435,25436],{},"El dolor no llega de una vez. Llega en cuatro etapas, generalmente en ese orden.",[368,25438,25440],{"id":25439},"primera-etapa-el-cliente-exige-sla","Primera etapa: el cliente exige SLA",[12,25442,25443],{},"En algún momento entra un contrato de prestación de servicio con cláusula de disponibilidad. Los números más comunes son 99% (3,65 días de indisponibilidad permitida al año), 99,9% (8,7 horas) y 99,95% (4,4 horas). El cliente quiere ver el número en el contrato.",[12,25445,25446],{},"Aquí Kamal en un único servidor ya no cabe. No porque Kamal sea malo — es porque un servidor único nunca da 99,9% sin maniobra externa. Mantenimiento del proveedor de nube, fallo de disco, actualización de kernel: cada uno de esos eventos consume integralmente tu presupuesto anual de indisponibilidad. En 2026 ningún proveedor serio garantiza 99,9% de uptime para una instancia individual.",[12,25448,25449],{},"La respuesta natural es \"voy a poner dos servidores\". Y es aquí donde Kamal empieza a necesitar andamios externos.",[368,25451,25453],{"id":25452},"segunda-etapa-dos-servidores-y-la-ilusion-del-cluster","Segunda etapa: dos servidores y la ilusión del cluster",[12,25455,25456,25457,25459],{},"Kamal acepta sin reclamar una lista con dos IPs en el ",[231,25458,25386],{},". Pero lo que hace con esa lista no es orquestación — es repetición. Los dos servidores son destinos paralelos de deploy, no miembros de un cluster.",[12,25461,25462],{},"Concretamente: si uno de los dos se cae, Kamal no realoca el tráfico. Kamal no tiene opinión sobre tráfico entre deploys. Necesitas montar, por fuera de él:",[2735,25464,25465,25468,25471,25474],{},[70,25466,25467],{},"Un balanceador de carga (del proveedor de nube o auto-hospedado)",[70,25469,25470],{},"Verificación de salud periódica que retire el servidor inactivo del balance",[70,25472,25473],{},"Resolución de DNS configurada encima del balanceador, no de los servidores directos",[70,25475,25476],{},"Algún mecanismo de notificación cuando algo sale del aire",[12,25478,25479],{},"Son cuatro productos nuevos que pasas a operar. Cada uno tiene su propio panel, su propia cuenta, su propia factura, su propio modo de romper a las tres de la mañana. El ferramental que era un archivo de configuración se volvió un diagrama.",[368,25481,25483],{"id":25482},"tercera-etapa-rolling-update-real-se-vuelve-fragil","Tercera etapa: rolling update real se vuelve frágil",[12,25485,25486],{},"Con dos servidores, Kamal ofrece deploy en secuencia: primero uno, después el otro. Bonito en la descripción. El problema vive en el caso de error.",[12,25488,25489],{},"Imagina que el deploy en el primer servidor sube la versión nueva con éxito, el segundo traba en el medio. Kamal no tiene visión consolidada del estado de los dos servidores después del error. Te quedas con una versión nueva corriendo en un lado, versión vieja corriendo en el otro, y ningún sistema centralizado para reconciliar la divergencia. La reconciliación se vuelve intervención manual: abres los dos servidores, decides qué versión queda, haces rollback o avanzas en lo que falló.",[12,25491,25492],{},"Para un equipo de tres personas, intervenir manualmente una vez por trimestre es tolerable. Para un equipo que entrega cuatro deploys por semana en tres aplicaciones distintas, la divergencia manual se vuelve el trabajo principal de una de las tres personas. Fue exactamente ese el gatillo que motivó a los orquestadores a nacer en los años 2010.",[368,25494,25496],{"id":25495},"cuarta-etapa-criptografia-y-enrutamiento-entre-servicios","Cuarta etapa: criptografía y enrutamiento entre servicios",[12,25498,25499],{},"Tarde o temprano la aplicación crece y gana un segundo servicio — tal vez un worker de cola, tal vez un servicio separado de procesamiento de imágenes, tal vez una API auxiliar consumida por el frontend principal. Esos servicios necesitan conversar entre sí, idealmente con tráfico cifrado y control de quién puede llamar a quién.",[12,25501,25502],{},"Kamal no tiene opinión sobre eso. Es tu trabajo montar — generalmente con proxy externo, certificados emitidos manualmente, reglas de firewall escritas a mano. En un servidor era trivial (todo el mundo es localhost). En tres servidores ejecutando seis servicios, se vuelve un proyecto aparte de una semana.",[12,25504,25505,25506,25509],{},"El router embebido en Kamal (el ",[231,25507,25508],{},"kamal-proxy",") resuelve la parte de tráfico HTTP de entrada con elegancia — terminación TLS, cambio atómico entre versiones, headers bajo control. Pero el tráfico entre servicios, en red privada, es problema tuyo.",[19,25511,25513],{"id":25512},"el-salto-necesario","El salto necesario",[12,25515,25516],{},"Mirando los cuatro puntos arriba en conjunto, queda claro que para cubrirlos necesitas, en la práctica, de:",[67,25518,25519,25522,25525,25528,25531,25534],{},[70,25520,25521],{},"Un plano de control replicado entre múltiples servidores — para que la caída de uno de ellos no tire la capacidad de hacer deploy",[70,25523,25524],{},"Elección automática del servidor que coordina, sin intervención humana",[70,25526,25527],{},"Balanceo y verificación de salud integrados, sin depender de balanceador externo del proveedor",[70,25529,25530],{},"Estado consolidado de los servicios, con reconciliación automática cuando algo diverge",[70,25532,25533],{},"Router integrado con certificados automáticos",[70,25535,25536],{},"Criptografía entre servicios embebida, sin montar un producto más",[12,25538,25539],{},"La tentación de mucho equipo, al llegar a esa lista, es caer en el orquestador planetario y acabar con el asunto. De ahí instala el coloso, escribe trescientas líneas de manifiesto para subir lo que estaba en cuarenta líneas en Kamal, contrata un especialista de salario senior solo para mantener aquello respirando, y descubre que cambió el problema correcto por un problema mayor.",[12,25541,25542],{},"La respuesta razonable es una herramienta que ofrece los seis ítems arriba sin pedir un equipo dedicado. Es exactamente donde HeroCtl vive.",[19,25544,25546],{"id":25545},"heroctl-como-kamal-con-cluster-real","HeroCtl como Kamal con cluster real",[12,25548,25549],{},"La simplicidad conceptual es la misma. Describes el servicio en un archivo de configuración corto — alrededor de cincuenta líneas para una aplicación completa con reglas de enrutamiento, secretos y certificado automático. Sometes el servicio por el cliente de línea de comando o por el panel web embebido. El cluster decide dónde ejecutar.",[12,25551,25552],{},"La diferencia está debajo del capó. En lugar de SSH transaccional, HeroCtl mantiene un plano de control replicado entre tres servidores. Esos tres conversan todo el tiempo para mantener una visión consolidada de todo lo que está corriendo, en qué servidor, en qué versión, con qué salud. Cuando el servidor que coordina se cae, en alrededor de siete segundos uno de los otros dos asume — sin intervención humana, sin alerta de pager para nadie. Los contenedores de la aplicación que corrían en el servidor caído son realocados en los sobrevivientes.",[12,25554,25555],{},"La operación diaria parece exactamente con Kamal: cambias la versión de la imagen, sometes, el cluster orquesta la sustitución. La diferencia aparece en los casos malos. Si el deploy parcial falla en el medio, la reconciliación es automática — el estado deseado está grabado en el plano de control, y los agentes en cada servidor convergen hacia él sin que abras terminal. Si un servidor se cae durante el deploy, los otros asumen el trabajo de él. Si el puerto que iba a ser usado está preso por un contenedor zombi, el cluster espera o redirige — no falla el deploy.",[12,25557,25558],{},"Y el ferramental embebido cubre los otros ítems de la lista: router con certificados Let's Encrypt automáticos, criptografía entre servicios sin montar nada por fuera, panel web para ver lo que está corriendo, métricas y logs centralizados sin stack externa.",[12,25560,25561],{},"La instalación es el mismo gesto que Kamal pide: servidor Linux con Docker, un comando único de setup. No hay requisito nuevo de infraestructura. No hay base de datos externa. No hay servicio gestionado de nube. El cluster vive en los servidores que ya tienes.",[19,25563,23242],{"id":23241},[119,25565,25566,25576],{},[122,25567,25568],{},[125,25569,25570,25572,25574],{},[128,25571,2983],{},[128,25573,2998],{},[128,25575,2995],{},[141,25577,25578,25589,25600,25610,25619,25628,25637,25647,25656,25666],{},[125,25579,25580,25583,25586],{},[146,25581,25582],{},"Filosofía",[146,25584,25585],{},"Deploy SSH minimalista, sin estado externo",[146,25587,25588],{},"Cluster con plano de control replicado",[125,25590,25591,25594,25597],{},[146,25592,25593],{},"Franja ideal de servidores",[146,25595,25596],{},"1 (excelente), 2-3 (con andamios externos)",[146,25598,25599],{},"3 a 500",[125,25601,25602,25604,25607],{},[146,25603,16336],{},[146,25605,25606],{},"No nativa — requiere balanceador externo",[146,25608,25609],{},"Embebida; elección automática en ~7s",[125,25611,25612,25615,25617],{},[146,25613,25614],{},"Panel web",[146,25616,3059],{},[146,25618,23300],{},[125,25620,25621,25623,25626],{},[146,25622,3924],{},[146,25624,25625],{},"Sí, vía router embebido",[146,25627,25625],{},[125,25629,25630,25632,25635],{},[146,25631,23315],{},[146,25633,25634],{},"No nativa",[146,25636,23321],{},[125,25638,25639,25642,25644],{},[146,25640,25641],{},"Métricas persistentes",[146,25643,25634],{},[146,25645,25646],{},"Job interno",[125,25648,25649,25651,25654],{},[146,25650,22806],{},[146,25652,25653],{},"No nativa — recoja por fuera",[146,25655,22329],{},[125,25657,25658,25661,25664],{},[146,25659,25660],{},"Reconciliación automática tras fallo parcial",[146,25662,25663],{},"No — requiere intervención manual",[146,25665,3065],{},[125,25667,25668,25670,25673],{},[146,25669,22839],{},[146,25671,25672],{},"Abierto, sin producto pago asociado",[146,25674,25675],{},"Plan gratuito permanente + Business\u002FEnterprise pagados",[12,25677,25678],{},"La columna de Kamal no es castigo — es honestidad. El producto fue diseñado para un caso de uso específico y lo cumple con elegancia. Cuando tu caso de uso pasa de lo que cubre, la respuesta correcta es cambiar de herramienta, no obligar a Kamal a volverse lo que nunca quiso ser.",[19,25680,25682],{"id":25681},"continua-en-kamal-si","Continúa en Kamal si...",[12,25684,25685],{},"La virtud de una herramienta especializada es admitir dónde gana. Cuatro perfiles en los que recomendamos Kamal sin titubear, aunque HeroCtl exista.",[12,25687,25688,25691],{},[27,25689,25690],{},"Ejecutas un servidor, sin presión de SLA formal."," El coste conceptual de un cluster — entender quórum, plano de control replicado, elección — es injustificado para un servidor único. Kamal te da noventa y nueve por ciento de lo que importa con cinco por ciento del concepto.",[12,25693,25694,25697,25698,25701],{},[27,25695,25696],{},"Eres un equipo de una a tres personas con fuerte cultura Rails y ningún tiempo disponible para aprender ferramental nuevo."," Kamal es, en la práctica, una extensión natural de ",[231,25699,25700],{},"bin\u002Frails",". Adoptarlo cuesta una tarde. Adoptar cualquier otra cosa cuesta una semana — y esa semana, en tu contexto, vale más que la mejora de operación que vendría después.",[12,25703,25704,25707],{},[27,25705,25706],{},"Tus aplicaciones son internas o de staging, donde cinco minutos de indisponibilidad mensual no causan daño real."," La operación de Kamal es tan directa que sigue siendo la mejor elección incluso para equipos grandes que tienen un conjunto de aplicaciones secundarias con tolerancia alta a fallo.",[12,25709,25710,25713],{},[27,25711,25712],{},"Eres DHH."," Con respeto sincero. La tesis de que orquestación es overkill fue defendida por alguien que opera productos públicos con millones de usuarios y prueba diariamente que se puede hacer sin cluster, con apenas servidores dedicados bien configurados. Si estás en un equipo en el que esa filosofía es parte de la identidad, Kamal no es solo herramienta — es declaración. No hay razón técnica para abandonarlo.",[19,25715,25717],{"id":25716},"migracion-de-kamal-a-heroctl-cuando-tiene-sentido","Migración de Kamal a HeroCtl cuando tiene sentido",[12,25719,25720],{},"Para quien llegó al momento en el que el dolor descrito arriba se volvió rutina, la migración es más ligera de lo que parece, porque la mayor parte del trabajo que Kamal ya hacía sigue siendo válido.",[12,25722,9008,25723,25726,25727,25730],{},[27,25724,25725],{},"Dockerfile que Kamal usa para empaquetar la aplicación sirve sin cambio alguno",". HeroCtl consume la misma imagen que Kamal empuja al registry. No hay requisito de adaptar ",[231,25728,25729],{},"ENTRYPOINT",", variables de entorno esperadas, puertos expuestos — el contrato del contenedor es preservado.",[12,25732,25733,25736,25737,25739,25740,25742],{},[27,25734,25735],{},"Variables de entorno migran con las mismas claves."," HeroCtl tiene un sistema de secretos propio, pero el nombre de las variables que la aplicación consume sigue siendo el mismo. Importas el contenido del ",[231,25738,9374],{}," que estaba en el ",[231,25741,25386],{}," directo al vault interno del cluster, y la aplicación no nota el cambio.",[12,25744,25745,25748,25749,25752,25753,25755],{},[27,25746,25747],{},"Volúmenes nombrados se mantienen",", porque Docker es Docker. Si tenías un volumen llamado ",[231,25750,25751],{},"app_storage"," en Kamal para persistir uploads, en HeroCtl sigue llamándose ",[231,25754,25751],{}," y vive en el mismo lugar del servidor. La diferencia es que el cluster sabe dónde está y respeta esa fijación al decidir dónde ejecutar la aplicación.",[12,25757,25758,25763],{},[27,25759,9008,25760,25762],{},[231,25761,25386],{}," no convierte uno a uno",", pero el mapeo conceptual es casi mecánico:",[2735,25765,25766,25773,25779,25785],{},[70,25767,25768,25769,25772],{},"El bloque ",[231,25770,25771],{},"servers"," de Kamal se vuelve la noción de cluster con N nodos en HeroCtl. No listas IPs en el archivo de aplicación — el cluster ya se conoce.",[70,25774,25768,25775,25778],{},[231,25776,25777],{},"proxy"," de Kamal se vuelve la configuración de enrutamiento integrado. En lugar de describir el proxy explícitamente, describes el nombre de dominio y las reglas; el router embebido aplica.",[70,25780,25768,25781,25784],{},[231,25782,25783],{},"accessories"," (Postgres, Redis y similares al lado de la aplicación) se vuelve jobs auxiliares en el mismo cluster, gestionados como cualquier otro servicio.",[70,25786,25768,25787,25790],{},[231,25788,25789],{},"env"," se vuelve el sistema de secretos de HeroCtl, con las mismas claves.",[12,25792,25793,25796,25797,25799],{},[27,25794,25795],{},"Estimación honesta:"," una a tres horas para una aplicación de complejidad media, contando tiempo de lectura de documentación, conversión del archivo, primer deploy de validación. Aplicaciones con muchos ",[231,25798,25783],{}," o reglas inusuales de enrutamiento pueden llegar a medio día. Por encima de eso, escríbenos — tenemos un conversor experimental que cubre los casos comunes.",[19,25801,7352],{"id":7351},[12,25803,25804,25811],{},[27,25805,25806,25807,25810],{},"¿HeroCtl tiene el equivalente de ",[231,25808,25809],{},"kamal accessories","?","\nSí. En HeroCtl describes Postgres, Redis o cualquier otro servicio auxiliar como un job común, gestionado por el mismo cluster que ejecuta la aplicación principal. La diferencia práctica es que esos servicios auxiliares ganan el mismo tratamiento que la aplicación: alta disponibilidad cuando tiene sentido, reconciliación automática, certificados si son expuestos públicamente, métricas y logs en el panel central. No operas un conjunto separado de \"cosas al lado\".",[12,25813,25814,25817],{},[27,25815,25816],{},"¿Y si uso Kamal para una app pequeña y HeroCtl para otra mayor, puedo?","\nPuedes. Los dos mundos coexisten sin conflicto. Inclusive recomendamos ese modelo durante la migración: mantienes lo que funciona en Kamal exactamente como está, y usas HeroCtl para las aplicaciones donde el cluster real importa. El único cuidado es no ejecutar Kamal y HeroCtl en el mismo servidor — disputan espacio en Docker y en los puertos, y la confusión no compensa la ganancia operacional. Servidores diferentes, mundos diferentes.",[12,25819,25820,25823],{},[27,25821,25822],{},"¿HeroCtl corre en cualquier VPS Linux como Kamal?","\nSí. La premisa es la misma: servidor Linux con Docker. Proveedor de nube grande, proveedor menor, servidor dedicado, máquina virtual en la oficina — donde Kamal funciona, HeroCtl funciona. No hay requisito de red privada gestionada, no hay requisito de balanceador externo del proveedor, no hay requisito de sistema de archivos especial. La condición mínima es tres servidores que se vean en la red y tengan Docker instalado.",[12,25825,25826,25829],{},[27,25827,25828],{},"¿Cuánto consume de más que Kamal?","\nEl plano de control ocupa entre 200 y 400 MB por servidor. En tres servidores de configuración modesta, eso es menos de cinco por ciento de la memoria total disponible. Comparado con Kamal — que consume cero porque no tiene proceso residente — es más. Comparado con el coloso, cuya versión gestionada empieza en alrededor de 700 MB por nodo-maestro antes de que cualquier aplicación suba, es la mitad. La pregunta correcta no es \"cuánto a más\", es \"cuánto eso me da a cambio\". Para nuestro cluster público de demostración, que ejecuta cuatro servidores, dieciséis contenedores y cinco sitios con cinco vCPUs y diez gigabytes totales, la respuesta es: alta disponibilidad real, sin necesitar duplicar el hardware.",[12,25831,25832,25838,25839,25841],{},[27,25833,25834,25835,25837],{},"¿Y el ",[231,25836,25508],{},", que es router integrado por debajo?","\nHeroCtl tiene el propio router integrado, con cambio atómico entre versiones, terminación TLS automática vía Let's Encrypt y enrutamiento por nombre de dominio. El concepto es el mismo del ",[231,25840,25508],{},". La diferencia es que el router de HeroCtl conoce el estado del cluster — sabe cuándo un servidor entero se cayó, cuándo un contenedor está en rolling, cuándo una versión nueva aún no pasó en la verificación de salud. Router aislado hace enrutamiento; router integrado al plano de control hace enrutamiento informado.",[12,25843,25844,25847,25848,25850],{},[27,25845,25846],{},"¿Necesito aprender un lenguaje nuevo para usar HeroCtl?","\nNo. El archivo de configuración es texto simple, parecido al ",[231,25849,25386],{}," de Kamal en estructura y tamaño. Los comandos de línea de comando siguen el patrón verbo-sustantivo que cualquier persona que ejecutó Docker conoce. El panel web cubre noventa por ciento de las operaciones sin que necesites abrir terminal. No hay lenguaje de templating, no hay sistema de paquetes paralelo, no hay manifiesto ceremonial. La regla interna es la misma de Kamal: la configuración tiene que caber en una pantalla.",[12,25852,25853,25856],{},[27,25854,25855],{},"¿Cuándo HeroCtl no es la respuesta correcta?","\nCuando operas un servidor único sin presión de SLA, Kamal es mejor — y lo dijimos arriba. Cuando operas cientos de miles de máquinas en escala planetaria, el coloso es mejor — y lo dijimos en otro post. Cuando tu compliance officer necesita apuntar a un certificado existente con nombre de producto en la lista, hoy la respuesta es el coloso o un orquestador comercial maduro. En esas tres condiciones, HeroCtl no compite bien y no intentamos forzar. Para la franja entre tres y quinientos servidores, con presión real de disponibilidad y tiempo escaso para montar stack, es donde la herramienta fue diseñada para brillar.",[19,25858,3310],{"id":3309},[12,25860,25861],{},"La pregunta correcta no es Kamal o HeroCtl. Es: ¿tu segundo cliente serio ya apareció? Si aún no, quédate en Kamal y sé feliz — cualquier cosa diferente de eso es distracción. Si ya apareció, y la noche mal dormida con el servidor caído ya sucedió al menos una vez, la respuesta empieza a inclinarse.",[12,25863,25864],{},"El camino de prueba es un comando único:",[224,25866,25868],{"className":25867,"code":5318,"language":2530},[2528],[231,25869,5318],{"__ignoreMap":229},[12,25871,25872],{},"Corre en tres servidores, sube la aplicación, mata uno de ellos a la fuerza, mira el cluster realocar. Si la sensación de alivio es proporcional al dolor que tuviste en el último incidente, está conversado. Si no lo es, vuelve a Kamal sin culpa — significa que tu momento aún no llegó, y respetar eso es tan importante como adoptar la herramienta correcta cuando el momento llega.",[12,25874,25875,25876,101],{},"La historia más larga del por qué construimos esto, y la lectura honesta de los tres caminos que existían antes, está en ",[3337,25877,21746],{"href":6545},{"title":229,"searchDepth":244,"depth":244,"links":25879},[25880,25881,25882,25888,25889,25890,25891,25892,25893,25894],{"id":25373,"depth":244,"text":25374},{"id":25399,"depth":244,"text":25400},{"id":25432,"depth":244,"text":25433,"children":25883},[25884,25885,25886,25887],{"id":25439,"depth":271,"text":25440},{"id":25452,"depth":271,"text":25453},{"id":25482,"depth":271,"text":25483},{"id":25495,"depth":271,"text":25496},{"id":25512,"depth":244,"text":25513},{"id":25545,"depth":244,"text":25546},{"id":23241,"depth":244,"text":23242},{"id":25681,"depth":244,"text":25682},{"id":25716,"depth":244,"text":25717},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-01-29","Kamal es brillante para un VPS ejecutando Rails. Cuando el segundo cliente serio pide redundancia, la arquitectura necesita cambiar. Donde Kamal para y HeroCtl empieza.",{},"\u002Fes\u002Fblog\u002Fheroctl-vs-kamal",{"title":25356,"description":25896},{"loc":25898},"es\u002Fblog\u002Fheroctl-vs-kamal",[25903,25904,25905,25906,8775],"kamal","rails","multi-server","37signals","DhBUqEImkRiT3ffO17-R_k05c-EpqKYpBfh34XdyQKg",{"id":25909,"title":25910,"author":7,"body":25911,"category":8761,"cover":3380,"date":26421,"description":26422,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":26423,"navigation":411,"path":16709,"readingTime":26424,"seo":26425,"sitemap":26426,"stem":26427,"tags":26428,"__hash__":26431},"blog_es\u002Fes\u002Fblog\u002Fheroctl-vs-dokploy.md","HeroCtl vs Dokploy: comparativo honesto",{"type":9,"value":25912,"toc":26408},[25913,25919,25922,25925,25929,25932,25938,25944,25950,25956,25962,25965,25969,25976,25987,25990,25993,25996,25999,26003,26006,26009,26012,26016,26019,26028,26034,26040,26046,26052,26058,26067,26069,26072,26220,26223,26227,26230,26233,26236,26242,26245,26248,26252,26255,26258,26261,26264,26267,26270,26274,26277,26280,26283,26286,26289,26293,26296,26299,26302,26309,26315,26318,26321,26323,26329,26335,26341,26347,26353,26359,26364,26366,26369,26372,26381,26384,26400,26403,26406],[12,25914,25915,25916,25918],{},"En sub-Reddits de DevOps en 2026, entre los auto-hospedados que aparecieron tras la ola de ",[3337,25917,2771],{"href":16704},", el nombre más comentado es Dokploy. Panel limpio. Instalación rápida. Comunidad que creció a una velocidad que la mayoría de los proyectos de orquestación de la última década no vio.",[12,25920,25921],{},"Y una decisión técnica que define todo el resto: Dokploy ejecuta Docker Swarm como engine de cluster. No es detalle — es la fundación. Todo lo que entrega de bueno viene de esa elección, y todo lo que tiene de limitación también.",[12,25923,25924],{},"Este texto es la lectura honesta de esa elección, y la comparación punto a punto con el camino que HeroCtl siguió. Sin ataque a Dokploy, sin pintura color de rosa de HeroCtl. Los dos productos resuelven problemas parecidos con filosofías diferentes, y la decisión entre ellos es más que preferencia de panel.",[19,25926,25928],{"id":25927},"donde-dokploy-acerto","Donde Dokploy acertó",[12,25930,25931],{},"Antes del contraste, el crédito. Equipos que evalúan Dokploy hoy encuentran un producto que hace cinco cosas correctas y las hace bien.",[12,25933,25934,25937],{},[27,25935,25936],{},"La UX es coherente."," El panel tiene identidad visual propia, flujos lineales, y los botones hacen lo que prometen. Para quien viene de Heroku o del antiguo panel comercial que se volvió caro en los últimos años, Dokploy pasa la sensación familiar de \"abre, clica, deploya\". Es el tipo de pulido que solo aparece tras muchas iteraciones encima de feedback de usuario real.",[12,25939,25940,25943],{},[27,25941,25942],{},"La instalación es rápida."," Un comando, cinco minutos, panel al aire. Para proyectos individuales y equipos pequeños, esa fricción mínima es lo que separa \"voy a probar\" de \"voy a desistir y continuar con la nube cara\".",[12,25945,25946,25949],{},[27,25947,25948],{},"El multi-server viene de fábrica."," Añades un segundo y un tercer servidor por el panel y el Swarm por debajo cuida de distribuir contenedores. Para quien nunca había pensado en alta disponibilidad, volverse HA por configuración es un avance grande sobre paneles que corren solo en un servidor.",[12,25951,25952,25955],{},[27,25953,25954],{},"El router integrado funciona."," Hay un router embebido que termina TLS, emite certificados Let's Encrypt automáticamente y enruta tráfico a los contenedores. No necesitas montar y mantener un proxy reverso separado, no escribes configuración de virtual host a mano, no decoras flags de renovación de certificado.",[12,25957,25958,25961],{},[27,25959,25960],{},"Buen soporte a stacks comunes."," Apps Node, Django, Rails, proyectos con Dockerfile directo, proyectos vía docker compose — todo gira sin ajustes. La comunidad publica plugins one-click para los bancos de datos más comunes, para herramientas de colas, para observabilidad básica.",[12,25963,25964],{},"Esa lista es honesta. Quien diga que Dokploy es \"solo otro wrapper\" no está mirando bien. Es un producto serio, con tracción, y fue hecho por gente que escuchó al usuario.",[19,25966,25968],{"id":25967},"la-eleccion-tecnica-fundamental-docker-swarm","La elección técnica fundamental — Docker Swarm",[12,25970,25971,25972,25975],{},"El punto que cambia la conversación es la engine. Dokploy no inventó su propio plano de control de cluster — consume el Swarm que ya viene dentro de Docker. El panel habla con la API de Swarm, que coordina los agentes en cada servidor. Cuando añades un servidor por el panel, es un ",[231,25973,25974],{},"swarm join"," por debajo.",[12,25977,25978,25979,25982,25983,25986],{},"Esa decisión tiene virtudes reales. Swarm es estable hace casi una década. La API es consistente con ",[231,25980,25981],{},"docker compose"," que la mayoría de los equipos ya conoce — declarar servicios tiene la misma cara en ambos. La elección de coordinador es embebida, viene gratis con ",[231,25984,25985],{},"swarm init",". Y porque es parte de Docker, cualquier servidor que ya tiene Docker instalado puede entrar en el cluster con un comando.",[12,25988,25989],{},"El problema es lo que sucedió con Swarm desde 2019. Docker Inc decidió aquel año enfocar casi toda la ingeniería de orquestación en otros productos de la empresa, y Swarm entró en lo que comunicados internos de la época describían como \"modo mantenimiento\". Traducción práctica: correcciones de seguridad continúan, releases de bug fix continúan, pero features nuevas pararon. No hay roadmap público de evolución. Nadie del equipo Docker presentó en conferencia, en los últimos cinco años, mejoras de scheduling, de red, de criptografía entre servicios, de integración con nuevos runtimes.",[12,25991,25992],{},"Swarm no está abandonado — está en estasis. Y estasis tiene un coste compuesto.",[12,25994,25995],{},"Cuando una red sobrepuesta entre nodos tiene un caso de borde en proveedores cloud específicos, ese caso queda esperando que alguien de fuera proponga patch. Cuando un patrón nuevo de runtime de contenedor aparece — runtimes ligeros, contenedores confidenciales, mejoras de aislamiento — Swarm no absorbe. Cuando quieres criptografía entre servicios que va más allá del overlay encrypted opcional del Swarm, la respuesta es \"monta un producto separado por encima\".",[12,25997,25998],{},"Dokploy hereda ese perfil. Cada limitación de Swarm se vuelve una limitación de Dokploy sin camino propio de evolución. No es culpa de Dokploy — es la consecuencia matemática de construir encima de una engine que paró de evolucionar.",[19,26000,26002],{"id":26001},"la-eleccion-tecnica-de-heroctl","La elección técnica de HeroCtl",[12,26004,26005],{},"HeroCtl tomó la decisión opuesta: construir el plano de control desde cero, sin depender de Swarm ni del coloso de orquestación popular. No es purismo de \"no inventado aquí\". Es la constatación de que orquestación en la franja \"1 a 500 servidores\" es un problema diferente del que tanto Swarm como el coloso resuelven, y ninguno de los dos va a volver a enfocarse en ese nicho.",[12,26007,26008],{},"La consecuencia práctica es libertad de roadmap. Cuando el equipo decide que criptografía entre servicios necesita ser nativa — no plugin, no overlay opcional, no operador externo — basta implementar. Cuando decidimos que métricas persistentes deberían correr como job interno del propio cluster, sin montar tres productos externos, fue una decisión de arquitectura sin condicionante. Cuando necesitamos optimizar el camino de deploy para que mil contenedores entren en rotación en pocos minutos, no hay cola detrás de Docker Inc ni de la fundación que mantiene el coloso.",[12,26010,26011],{},"La contrapartida es honesta: HeroCtl es más nuevo. Tiene menos kilometraje que Swarm. Tiene comunidad menor. La pila de plugins one-click es más corta. Ese es el trade-off de construir el plano de control entero en lugar de consumir uno listo. Los primeros seis meses de producción cerrada — cuatro servidores, cinco vCPUs totales, diez gigabytes de RAM, dieciséis contenedores activos, cinco sitios con TLS automático — mostraron que el núcleo aguanta. El panel aún está en catch-up visual.",[19,26013,26015],{"id":26014},"comparacion-operacional","Comparación operacional",[12,26017,26018],{},"Lado a lado, en cuestiones que importan para quien va a operar.",[12,26020,26021,26024,26025,26027],{},[27,26022,26023],{},"Instalación."," Dokploy: cinco minutos para panel al aire — instala Docker si no tiene, hace ",[231,26026,25985],{},", sube el panel. HeroCtl: cinco minutos también — descarga un archivo ejecutable, registra el servicio, sube el agente. Empate operacional.",[12,26029,26030,26033],{},[27,26031,26032],{},"Multi-server real."," Dokploy depende del plano de control de Swarm — tres servidores coordinadores o más para que la pérdida de uno no tire el cluster. HeroCtl tiene plano de control replicado propio, también en tres servidores o más. Los dos entregan HA real. La diferencia es de quién estás dependiendo: del estado actual de Swarm o del estado actual de HeroCtl.",[12,26035,26036,26039],{},[27,26037,26038],{},"Panel."," Los dos tienen. En 2026, el de Dokploy está más pulido visualmente — años más de iteración y una comunidad mayor dando feedback. El de HeroCtl cubre los mismos casos de uso (deploy, métricas, logs, cluster topology, certificados, secretos, audit) pero en catch-up estético. Honestidad de producto: si la estética del panel es determinante en la decisión y tiene peso mayor que arquitectura, Dokploy gana hoy.",[12,26041,26042,26045],{},[27,26043,26044],{},"Plugins y marketplace."," Dokploy tiene más plugins one-click hoy — Postgres, Redis, MinIO, observabilidad. HeroCtl ejecuta cualquier contenedor como job, con la misma interfaz uniforme; lo que falta es la vitrina de \"clica y tienes\". Para quien prefiere describir un job en archivo de configuración y versionar en el repositorio, HeroCtl llega al mismo lugar. Para quien prefiere clicar y tener, Dokploy llega más rápido.",[12,26047,26048,26051],{},[27,26049,26050],{},"Métricas y logs."," Dokploy: stack vía plugins externos — Prometheus, Grafana, Loki o similares montados separadamente. HeroCtl: métricas y logs como jobs internos del propio cluster, con escritor único embebido. La diferencia es menos sobre quién entrega mejor dato, más sobre cuántos productos estás manteniendo. Equipo pequeño suele valorar la pila más corta; equipo con SRE suele preferir la flexibilidad de plugar la stack que ya conoce.",[12,26053,26054,26057],{},[27,26055,26056],{},"Criptografía entre servicios."," Dokploy no trae por defecto. Swarm tiene red overlay con criptografía opcional, pero Dokploy no promueve ese camino como primera clase. Para criptografía mutua de verdad entre todos los servicios, es un producto más por encima. HeroCtl la trae embebida — toda comunicación entre contenedores del cluster es cifrada por defecto, con PKI automática, sin operador externo. Es la diferencia entre \"tiene opción\" y \"viene encendido\".",[12,26059,26060,26063,26064,26066],{},[27,26061,26062],{},"Observabilidad del plano de control."," Dokploy: inspeccionas el estado de Swarm vía comandos ",[231,26065,1118],{}," en el servidor más panel para app. HeroCtl: API uniforme del plano de control expone estado de jobs, agentes, elección, certificados, en endpoints propios — auditados.",[19,26068,17389],{"id":17388},[12,26070,26071],{},"La versión honesta de la decisión. Como siempre, todo orquestador es un conjunto de tradeoffs.",[119,26073,26074,26084],{},[122,26075,26076],{},[125,26077,26078,26080,26082],{},[128,26079,2983],{},[128,26081,2777],{},[128,26083,2995],{},[141,26085,26086,26097,26107,26117,26127,26137,26147,26158,26169,26179,26188,26199,26209],{},[125,26087,26088,26091,26094],{},[146,26089,26090],{},"Engine de cluster",[146,26092,26093],{},"Docker Swarm (en mantenimiento desde 2019)",[146,26095,26096],{},"Plano de control propio, evolución activa",[125,26098,26099,26102,26105],{},[146,26100,26101],{},"Instalación",[146,26103,26104],{},"~5 min",[146,26106,26104],{},[125,26108,26109,26111,26114],{},[146,26110,16336],{},[146,26112,26113],{},"Sí (3+ coordinadores Swarm)",[146,26115,26116],{},"Sí (3+ servidores con plano de control replicado)",[125,26118,26119,26121,26124],{},[146,26120,25614],{},[146,26122,26123],{},"Sí, más pulido en 2026",[146,26125,26126],{},"Sí, en catch-up estético",[125,26128,26129,26132,26135],{},[146,26130,26131],{},"Router + TLS automático",[146,26133,26134],{},"Embebido (proxy reverso por debajo)",[146,26136,23300],{},[125,26138,26139,26141,26144],{},[146,26140,23315],{},[146,26142,26143],{},"Opcional vía overlay encrypted",[146,26145,26146],{},"Embebida y por defecto",[125,26148,26149,26152,26155],{},[146,26150,26151],{},"Métricas \u002F logs",[146,26153,26154],{},"Plugins externos",[146,26156,26157],{},"Jobs internos del cluster",[125,26159,26160,26163,26166],{},[146,26161,26162],{},"Marketplace de plugins",[146,26164,26165],{},"Más maduro",[146,26167,26168],{},"Más corto, cualquier contenedor como job",[125,26170,26171,26173,26176],{},[146,26172,22839],{},[146,26174,26175],{},"Open source",[146,26177,26178],{},"Community gratuito permanente + Business + Enterprise",[125,26180,26181,26183,26186],{},[146,26182,19703],{},[146,26184,26185],{},"Limitada",[146,26187,24656],{},[125,26189,26190,26193,26196],{},[146,26191,26192],{},"Escrow de código fuente",[146,26194,26195],{},"No aplicable",[146,26197,26198],{},"Sí (Enterprise)",[125,26200,26201,26203,26206],{},[146,26202,16426],{},[146,26204,26205],{},"1–50 servidores",[146,26207,26208],{},"1–500 servidores",[125,26210,26211,26214,26217],{},[146,26212,26213],{},"Roadmap de orquestación",[146,26215,26216],{},"Condicionado a Swarm",[146,26218,26219],{},"Independiente",[12,26221,26222],{},"La columna que más provoca la decisión es la primera. Todo lo demás deriva de ella.",[19,26224,26226],{"id":26225},"cuando-dokploy-es-la-eleccion-correcta","Cuándo Dokploy es la elección correcta",[12,26228,26229],{},"La honestidad exige la sección. Hay escenarios en los que recomendar Dokploy es la respuesta correcta.",[12,26231,26232],{},"Te gusta Docker Swarm y atiende lo que necesitas hoy. Apps web típicas, base de datos gestionada fuera del cluster, baja exigencia de criptografía interna, equipo pequeño que prefiere previsibilidad a evolución de plataforma. Swarm va a aguantar eso por años. Construir encima de él significa construir encima de algo testeado y estable, aunque parado.",[12,26234,26235],{},"El panel más pulido del segmento auto-hospedado importa mucho para tu equipo. Si la interfaz visual es parte de la venta interna para el resto de la empresa, si tu CTO va a mostrar al CEO y la impresión importa, Dokploy llega al frente en 2026. HeroCtl está cerrando esa distancia, pero aún no la cerró.",[12,26237,26238,26239,26241],{},"Ya tienes deploys vía ",[231,26240,25981],{}," y quieres camino de migración mínimo. Dokploy acepta compose con poca fricción. Subir un equipo entero acostumbrado con compose a un modelo nuevo de job spec es un coste organizacional que no todo proyecto justifica.",[12,26243,26244],{},"Quieres comunidad activa de plugins one-click. Si tu flujo es \"necesito Postgres con replicación, clico, listo\", Dokploy entrega eso hoy. HeroCtl entrega el mismo Postgres, pero describes el job y versionas en el repositorio.",[12,26246,26247],{},"No tienes requisitos formales de criptografía entre servicios nativa ni auditoría detallada. Para equipo de cinco personas con SaaS que aún no vendió al primer cliente Enterprise, Dokploy es respuesta suficiente. Salir de él después es trabajo — pero es trabajo que tal vez nunca necesites hacer.",[19,26249,26251],{"id":26250},"cuando-heroctl-es-la-eleccion-correcta","Cuándo HeroCtl es la elección correcta",[12,26253,26254],{},"Los perfiles simétricos.",[12,26256,26257],{},"Quieres un plano de control que evoluciona con decisiones propias. Para proyectos donde la plataforma de ejecución es parte del producto — no solo infra accesoria — depender de una engine en mantenimiento es un riesgo estratégico. Construir encima de algo que evoluciona es diferente de construir encima de algo que mantiene.",[12,26259,26260],{},"Criptografía entre servicios necesita ser nativa. Si tu arquitectura tiene decenas de servicios conversando, datos sensibles transitando entre ellos, y no quieres montar una malla de servicio separada ni confiar en \"red privada del proveedor cloud\" como única capa, hace diferencia tener cifrado por defecto.",[12,26262,26263],{},"Necesitas auditoría detallada. Quien firmó Business sabe quién hizo qué y cuándo — quién promovió versión de qué job, quién corrió qué comando administrativo, quién rotó qué secreto. Para equipos con requisitos de compliance crecientes, eso no es opcional.",[12,26265,26266],{},"Quieres escrow de código fuente como seguro de continuidad. Enterprise incluye contrato con tercera parte custodiante: si la empresa detrás de HeroCtl encierra operaciones, el código es entregado a los clientes pagantes con licencia de continuidad interna. Para organizaciones que no pueden darse el lujo de \"y si la empresa quiebra\", esa estructura es lo que destranca la aprobación de procurement.",[12,26268,26269],{},"Franja de aplicación 3 a 500 servidores con requisitos formales. Es la franja donde ni Swarm en mantenimiento ni el coloso diseñado para decenas de miles de máquinas sirven bien. Es exactamente donde HeroCtl apunta.",[19,26271,26273],{"id":26272},"la-cuestion-del-swarm-en-produccion","La cuestión del Swarm en producción",[12,26275,26276],{},"Conviene ser justo aquí — y ser específico.",[12,26278,26279],{},"Swarm continúa estable. Para la mayoría absoluta de los casos de uso, va a entregar lo que promete por algunos años más. Apps web típicas, microservicios de complejidad media, deploys rolling, healthchecks, descubrimiento de servicio básico — todo eso corre. Historias de cluster Swarm en producción hace cinco o seis años sin incidente grave existen en volumen.",[12,26281,26282],{},"El punto no es \"Swarm va a romper\". Es \"Swarm no va a mejorar\". Construir encima de él en 2026 es firmar tácitamente que el conjunto de capacidades que tiene hoy es el conjunto que vas a tener para siempre. Para proyectos donde eso es un trade-off aceptable, sin problema. Para proyectos donde criptografía entre servicios, observabilidad nativa, integración con runtimes nuevos, o extensibilidad del scheduler van a importar en los próximos tres años, vale la pena considerar una stack que sigue evolucionando.",[12,26284,26285],{},"Hay otro ángulo. Cuando Swarm tiene un caso de borde — red sobrepuesta con pérdida intermitente en proveedores cloud específicos, scheduling extraño cuando un nodo vuelve después de partición larga, comportamiento inesperado de health check en contenedores con inicialización lenta — esos casos hoy son debugueados por la comunidad de fuera. Docker Inc no está de plantón. Resolver se vuelve proyecto de tu equipo. En HeroCtl, esos casos son tratados por el equipo que escribió el código — abres reporte, subimos corrección. Es un modelo de soporte diferente porque la inversión de ingeniería sigue sucediendo.",[12,26287,26288],{},"No es argumento ideológico de \"código nuevo es mejor\". Swarm es estable precisamente porque es antiguo. El argumento es práctico: la evolución del producto que vas a usar en los próximos cinco años depende de quién está invirtiendo. En Dokploy, parte de la evolución depende de gente que paró de tocar Swarm en 2019. En HeroCtl, depende de gente que está tocando el plano de control hoy.",[19,26290,26292],{"id":26291},"migracion-entre-ellos","Migración entre ellos",[12,26294,26295],{},"Camino conceptual, no receta. Cada proyecto tiene detalles propios — escríbenos si quieres ayuda específica.",[12,26297,26298],{},"Imágenes Docker sirven en los dos. Dockerfile que usas en Dokploy es el mismo que usas en HeroCtl. No hay build especial, no hay runtime customizado.",[12,26300,26301],{},"Variables de entorno migran con mismas claves. Donde tienes un bloque de env vars en Dokploy, tienes un bloque equivalente en el job spec de HeroCtl. Los nombres no cambian.",[12,26303,26304,26305,26308],{},"Volúmenes nombrados se mantienen. Volume montado en ",[231,26306,26307],{},"\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata"," continúa montado allí. El concepto de volumen persistente entre reinicios es el mismo.",[12,26310,9008,26311,26314],{},[231,26312,26313],{},"compose"," que Dokploy acepta no convierte 1:1 al job spec de HeroCtl, pero el mapeo es directo. Servicio se vuelve task. Network se vuelve política de red. Deploy strategy se vuelve estrategia de rolling update. La primera migración lleva una tarde por aplicación; después de eso, copiar y pegar con sustituciones.",[12,26316,26317],{},"Ingress: el router de Dokploy y el router integrado de HeroCtl ambos terminan en configuración-como-código. Describes host, redirect, certificado en poquísimas líneas en cualquiera de los dos. La traducción es mecánica.",[12,26319,26320],{},"Para equipos con hasta diez aplicaciones, migración manual en una tarde. Por encima de eso, conversor experimental cubre los casos comunes — escríbenos.",[19,26322,7352],{"id":7351},[12,26324,26325,26328],{},[27,26326,26327],{},"¿HeroCtl es más maduro que Dokploy?","\nNo en todas las dimensiones. Dokploy tiene más tiempo de comunidad, más plugins, panel más pulido visualmente. HeroCtl tiene plano de control propio con evolución activa, alta disponibilidad real testada en batería de caos documentada, y roadmap independiente de cualquier otro proyecto. \"Maduro\" depende del eje. En estética de panel y marketplace, Dokploy. En arquitectura de plataforma y contrato comercial explícito, HeroCtl.",[12,26330,26331,26334],{},[27,26332,26333],{},"¿Y el panel, el de Dokploy es mejor?","\nEn 2026, sí — más pulido visualmente, más años de iteración, más feedback de comunidad incorporado. El de HeroCtl cubre los mismos casos de uso y está en catch-up estético. La pregunta importante es si la diferencia visual es el criterio decisivo para ti. Para algunos equipos lo es. Para otros, arquitectura pesa más.",[12,26336,26337,26340],{},[27,26338,26339],{},"¿Cuál consume menos recurso?","\nDokploy añade el overhead del panel más el overhead de Swarm dentro de Docker — Swarm en sí es ligero, pero el panel es una aplicación web razonablemente completa. HeroCtl tiene plano de control entre 200 y 400 MB por servidor, incluyendo panel web embebido. En cluster pequeño los dos caben cómodamente en servidores modestos. La diferencia no es determinante en la decisión.",[12,26342,26343,26346],{},[27,26344,26345],{},"¿Y el backup de base?","\nEn los dos, base de datos es una responsabilidad explícita de quien opera. Dokploy tiene plugins one-click para Postgres y similares, pero backup automático es configuración adicional — generalmente montas cron job o plugin de backup separado. HeroCtl trata base como cualquier otro job, con volumen persistente; backup es un job paralelo que defines. Business incluye backup gestionado con ventanas y retención. En ninguno de los dos \"encender y olvidar\" es respuesta honesta — base merece atención en ambos.",[12,26348,26349,26352],{},[27,26350,26351],{},"Dokploy es open source, HeroCtl no, ¿eso me preocupa?","\nPregunta justa. HeroCtl tiene Community Edition gratuita para siempre, sin límite de servidores, sin límite de jobs, sin feature gates artificiales. El binario no tiene phone-home obligatorio ni kill-switch remoto — una vez instalado, el cluster funciona offline indefinidamente. Enterprise incluye escrow de código fuente con tercera parte custodiante, así que si la empresa detrás del producto encierra operaciones, el código es entregado a los clientes pagantes con licencia de continuidad interna. No es lo mismo que open source, pero resuelve lo que open source resuelve en ese contexto: garantía contra desaparición del proveedor. El contrato comercial está publicado desde el día uno y congelado para quien firma hoy — no hay cláusula de cambio retroactivo.",[12,26354,26355,26358],{},[27,26356,26357],{},"¿Puedo usar los dos, uno para dev y otro para prod?","\nTécnicamente sí, pero raramente tiene sentido. Imágenes Docker son portables entre los dos, así que el camino funciona. En la práctica, dos orquestadores diferentes en entornos adyacentes duplica el conocimiento operacional del equipo. Recomendamos elegir uno y quedarse en él. Si la duda es a fondo cuál elegir, escríbenos — discutir caso por caso es más útil que consejo genérico.",[12,26360,26361,26363],{},[27,26362,22973],{},"\nPor encima de mil servidores, ninguno de los dos es la elección obvia — esa franja es territorio del coloso diseñado para decenas de miles de máquinas. En la franja de 1 a 500 servidores, HeroCtl fue diseñado específicamente. Dokploy escala bien dentro de lo que Swarm escala — típicamente hasta algunas decenas de nodos en producción sin gimnasia. Por encima de eso, Swarm pasa a exigir cuidados que no estaban en la propuesta original del producto.",[19,26365,3310],{"id":3309},[12,26367,26368],{},"La elección entre Dokploy y HeroCtl no es entre producto bueno y producto malo. Los dos son serios. La elección es entre filosofías diferentes de plataforma.",[12,26370,26371],{},"Dokploy eligió construir una capa de UX y producto encima de una engine madura pero estática. HeroCtl eligió construir el plano de control entero para controlar la evolución. Trade-offs reales en las dos direcciones.",[12,26373,26374,26375,26377,26378,26380],{},"Si estás en Dokploy hoy y no estás sintiendo las limitaciones, quédate. Es un producto bueno. Si estás evaluando los dos en greenfield, lee el post sobre ",[3337,26376,6546],{"href":6545}," para entender la motivación detrás de la decisión de construir el plano de control desde cero. Si estás viniendo de Heroku o de paneles comerciales que se volvieron caros, vale también el post ",[3337,26379,19774],{"href":19773}," — el contexto de mercado ayuda.",[12,26382,26383],{},"Para experimentar HeroCtl en tres minutos:",[224,26385,26386],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,26387,26388],{"__ignoreMap":229},[234,26389,26390,26392,26394,26396,26398],{"class":236,"line":237},[234,26391,1220],{"class":247},[234,26393,2958],{"class":251},[234,26395,5329],{"class":255},[234,26397,2964],{"class":383},[234,26399,2967],{"class":247},[12,26401,26402],{},"Un archivo ejecutable, un servidor para empezar, dos más cuando quieras HA real. Panel embebido, certificados automáticos, criptografía entre servicios por defecto. Sin phone-home, sin kill-switch, contrato comercial congelado.",[12,26404,26405],{},"La intención es simple: orquestación de contenedores, sin ceremonia.",[3351,26407,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":26409},[26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,26420],{"id":25927,"depth":244,"text":25928},{"id":25967,"depth":244,"text":25968},{"id":26001,"depth":244,"text":26002},{"id":26014,"depth":244,"text":26015},{"id":17388,"depth":244,"text":17389},{"id":26225,"depth":244,"text":26226},{"id":26250,"depth":244,"text":26251},{"id":26272,"depth":244,"text":26273},{"id":26291,"depth":244,"text":26292},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-01-22","Dokploy es la apuesta del segmento auto-hospedado tras el crecimiento de Coolify. Comparativo honesto: dónde se solapan, dónde divergen.",{},"12 min",{"title":25910,"description":26422},{"loc":16709},"es\u002Fblog\u002Fheroctl-vs-dokploy",[26429,8775,22492,26430],"dokploy","docker-swarm","8MIJFThnHeS79TAmvsG11yNY71Uce7xCyfaCpDFVsUY",{"id":26433,"title":26434,"author":7,"body":26435,"category":8761,"cover":3380,"date":27066,"description":27067,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":27068,"navigation":411,"path":27069,"readingTime":8766,"seo":27070,"sitemap":27071,"stem":27072,"tags":27073,"__hash__":27076},"blog_es\u002Fes\u002Fblog\u002Fcaprover-vs-coolify-vs-dokploy.md","CapRover vs Coolify vs Dokploy: el segmento simple comparado en 2026",{"type":9,"value":26436,"toc":27053},[26437,26446,26449,26456,26463,26470,26473,26477,26480,26483,26489,26499,26505,26509,26512,26515,26520,26529,26535,26539,26542,26545,26550,26555,26561,26565,26568,26746,26753,26757,26763,26766,26769,26780,26797,26800,26803,26835,26838,26842,26845,26848,26851,26863,26866,26870,26873,26905,26908,26912,26915,26921,26934,26943,26949,26952,26956,26959,26976,26979,26982,26984,26990,26996,27002,27008,27014,27020,27026,27028,27031,27034,27037,27042],[12,26438,26439,26440,5839,26442,26445],{},"Tres productos disputan hoy el mismo nicho: el desarrollador que quiere un Heroku corriendo en una VPS propia, sin aprender orquestador de cluster y sin pagar US$25 por dyno. CapRover, Coolify y Dokploy. Los tres hacen la misma promesa — ",[231,26441,16110],{},[231,26443,26444],{},"docker pull",", panel web, certificado automático, deploy en minutos. Los tres entregan esa promesa. Y aún así, elegir mal entre ellos te va a costar tres meses de tu próximo trimestre.",[12,26447,26448],{},"La diferencia no está en lo que cada uno hace. Está en lo que cada uno apuesta.",[12,26450,26451,26452,26455],{},"CapRover apostó a la ",[27,26453,26454],{},"estabilidad",". Existe desde 2017, atravesó tres olas de hype sin perder identidad, y prefiere envejecer a reinventarse.",[12,26457,26458,26459,26462],{},"Coolify apostó a la ",[27,26460,26461],{},"riqueza de features",". Marketplace de templates, soporte nativo a docker-compose, multi-server, decenas de integraciones listas. Es el panel más popular del segmento en enero de 2026.",[12,26464,26465,26466,26469],{},"Dokploy apostó al ",[27,26467,26468],{},"peso ligero con UX moderna",". Usa Docker Swarm por debajo para ganar multi-server fuera de la caja, copia lo que funcionó en Coolify y descarta lo que pesó.",[12,26471,26472],{},"La elección entre los tres define el siguiente dolor que vas a tener — y no es el dolor de instalación. Es el dolor que aparece en el octavo mes, cuando el panel ya está corriendo tus dos o tres SaaS de producción y necesitas decidir si confías en él en un jueves por la noche. Este post es el mapa para elegir sabiendo qué dolor viene.",[19,26474,26476],{"id":26475},"caprover-el-veterano","CapRover, el veterano",[12,26478,26479],{},"CapRover salió en 2017, antes de que Coolify existiera, antes del hype de auto-hosting volver a estar de moda, antes de que docker-compose fuera sinónimo de \"dev local\". Fue escrito en Node, usa Docker Swarm internamente (sí, antes de que Dokploy hiciera de eso bandera), y nunca intentó ser bonito.",[12,26481,26482],{},"La filosofía del proyecto es visible en cada decisión: haz una cosa bien, mantén el código simple, prefiere release semestral a release semanal. El resultado es una de las herramientas más confiables de ese segmento. Personas que instalaron CapRover en 2019 aún corren aquella misma instalación en 2026 con upgrades incrementales y cero reinstalación completa.",[12,26484,26485,26488],{},[27,26486,26487],{},"Lo que hace bien."," Idle de aproximadamente 150 MB de RAM — el más liviano de los tres por un margen cómodo. Instalación en una VPS de US$5\u002Fmes corre tranquilo, con 600 MB libres para workload real. Panel funcional sin florituras, abstracción de \"App\" simple (una imagen Docker, variables de entorno, dominio, certificado), soporte a deploy vía CLI, vía push de tarball, vía Dockerfile. Comunidad pequeña pero leal — el foro tiene respuestas de 2018 que aún tienen sentido en 2026.",[12,26490,26491,26494,26495,26498],{},[27,26492,26493],{},"Donde pierde."," El modelo \"App\" es primariamente single-container. Consigues correr servicios auxiliares (Postgres, Redis) como Apps separados, pero la integración entre ellos es vía DNS interno y variables manuales. docker-compose tiene soporte limitado — funciona para casos simples, se rompe en casos con volúmenes nombrados complejos o healthchecks elaborados. El ecosistema de plugins\u002Ftemplates (\"one-click apps\") existe y funciona, pero la curaduría se estancó; muchos templates apuntan a versiones de imagen de 2022. UI tiene el estilo visual de cuando fue escrita — funcional, pero data el producto. Y el punto más crítico: ",[27,26496,26497],{},"no existe multi-server real",". Corres en una VPS. ¿Quieres redundancia? CapRover no te ayuda.",[12,26500,26501,26504],{},[27,26502,26503],{},"Cuándo CapRover es la elección correcta."," Solo dev con una VPS. Aplicación monolítica sin decenas de microservicios. Presupuesto ajustado (su ligereza te ahorra un upgrade de plan). Equipo de una a tres personas que ya tomó todas las decisiones importantes y quiere un panel que simplemente no muera. Valoras estabilidad por encima de feature nueva. CapRover envejece bien; en enero de 2026 sigue siendo la elección pragmática para ese perfil específico.",[19,26506,26508],{"id":26507},"coolify-el-feature-rich-popular","Coolify, el feature-rich popular",[12,26510,26511],{},"Coolify entró al mercado tarde — primera release relevante en 2021 — y ganó tracción asombrosa en los últimos tres años. En enero de 2026 acumula decenas de miles de estrellas en el repositorio público, comunidad activa, releases mensuales, presencia en conferencias, creador conocido personalmente por el público. Es el panel que indie hacker en Twitter recomienda primero.",[12,26513,26514],{},"La filosofía es clara: haz el panel más completo del mercado. Soporta todo. Marketplace, multi-server, monitoring integrado, soporte a destinos múltiples (proveedor cloud A, proveedor cloud B, tu VPS), notificaciones en varios canales, integración con varios git providers, deploys preview, branch-per-environment, revisión de pull request. Si un competidor tiene feature, Coolify quiere tener también — y generalmente tiene.",[12,26516,26517,26519],{},[27,26518,26487],{}," UI moderna y agradable. Soporte nativo y robusto a docker-compose — pegas tu compose existente, ajustas dominios, despliegas. Templates de base de datos en un clic para Postgres, MySQL, MariaDB, MongoDB, Redis, y una decena más. Multi-server: registras un destino remoto y Coolify provisiona apps allí. Backup automático integrado para las bases provisionadas. Soporte a múltiples proveedores git. Comunidad activa que responde rápido — Discord activo, releases que incorporan pedidos.",[12,26521,26522,26524,26525,26528],{},[27,26523,26493],{}," Pesado. Idle entre 500 y 700 MB de RAM, dependiendo de la versión y del número de servicios auxiliares activos. En una VPS de 1 GB estás apretado antes de subir un único contenedor de aplicación. La complejidad creció en los últimos dos años más rápido de lo que la documentación acompañó — features nuevas debutan con tutorial en vídeo en Twitter y tardan en volverse página estática consultable. Pero el punto más grave es lo que ",[27,26526,26527],{},"multi-server no significa en Coolify",": no es alta disponibilidad. Es \"un panel central despliega en N hosts remotos\". Si el servidor que aloja el panel cae, pierdes la capacidad de hacer deploy, ver logs, revisar status — los apps remotos siguen corriendo, pero estás ciego. El panel es punto único de fallo por diseño.",[12,26530,26531,26534],{},[27,26532,26533],{},"Cuándo Coolify es la elección correcta."," Indie hacker con 2 a 5 aplicaciones. Quiere panel maduro, con features listas que ahorran tiempo de configuración. Valora marketplace de templates y setup rápido de base de datos. Tiene latitud presupuestaria para hardware — una VPS de 2 a 4 GB de RAM dedicada al panel no es problema. No tiene requisito formal de SLA. Es el \"Heroku auto-hospedado\" más completo que consigues hoy, y para ese perfil entrega exactamente.",[19,26536,26538],{"id":26537},"dokploy-el-desafiante-ligero","Dokploy, el desafiante ligero",[12,26540,26541],{},"Dokploy es el más nuevo de los tres. Lanzamiento público en 2024, ganó tracción rápido en 2025, en enero de 2026 acumula algo en torno a diez mil estrellas en el repositorio público. Fue explícitamente posicionado como \"lo que Coolify debería ser, sin el peso\".",[12,26543,26544],{},"La filosofía: copiar lo que Coolify acertó en UX y descartar lo que pesó. Usa Docker Swarm como capa de orquestación — decisión polémica y fundadora del proyecto. Swarm te da multi-server fuera de la caja: añades un nodo worker y entra al pool sin configuración de red manual. A cambio, heredas el destino de Swarm como producto.",[12,26546,26547,26549],{},[27,26548,26487],{}," Idle aproximadamente 350 MB de RAM — significativamente más liviano que Coolify, más pesado que CapRover. UI clean y moderna, claramente inspirada en Coolify pero con elecciones más económicas (menos pestañas, menos config inicial). Multi-server real vía Swarm: registras un worker, aparece en el pool, jobs se distribuyen. Soporte nativo a Docker Compose (Dokploy lo llama \"stacks\"). Crecimiento de la comunidad: Discord activo, releases frecuentes, proyecto incorporó pedidos importantes en meses, no años.",[12,26551,26552,26554],{},[27,26553,26493],{}," Más nuevo significa menos battle-tested. Bugs aparecen en casos de borda que Coolify y CapRover ya documentaron. Acoplado a Swarm — y Swarm es una tecnología en mantenimiento lento por la mantenedora original. Recibe correcciones de seguridad y estabilidad, pero no hay indicación clara de que gane nuevas features. Para proyecto de 2024 elegir Swarm es una apuesta defendible (estable, simple, embebido en Docker), pero estás construyendo encima de una capa que no evoluciona más. Ecosistema de plugins\u002Ftemplates aún superficial comparado a Coolify — ganas lo básico, no la biblioteca curada de templates específicos. Documentación en español prácticamente inexistente.",[12,26556,26557,26560],{},[27,26558,26559],{},"Cuándo Dokploy es la elección correcta."," Equipo pequeño (3 a 6 personas) que valora UX moderna pero no quiere pagar el precio de Coolify en RAM. Multi-server real fuera de la caja es requisito (quieres correr en 2 a 4 VPS desde el inicio). Proyecto nuevo sin dependencia histórica en templates o plugins específicos. No tienes aversión a Docker Swarm como tecnología subyacente. Para ese perfil, en enero de 2026, Dokploy es la elección que envejece mejor entre los tres.",[19,26562,26564],{"id":26563},"los-tres-lado-a-lado","Los tres lado a lado",[12,26566,26567],{},"La tabla abajo es la versión comprimida de la decisión. Cada línea es una dimensión que suele volverse argumento de foro; lado a lado, se vuelve criterio.",[119,26569,26570,26583],{},[122,26571,26572],{},[125,26573,26574,26576,26579,26581],{},[128,26575,2983],{},[128,26577,26578],{},"CapRover",[128,26580,2771],{},[128,26582,2777],{},[141,26584,26585,26599,26613,26627,26641,26654,26666,26680,26694,26707,26719,26733],{},[125,26586,26587,26590,26593,26596],{},[146,26588,26589],{},"Idle RAM (media observada)",[146,26591,26592],{},"~150 MB",[146,26594,26595],{},"500 a 700 MB",[146,26597,26598],{},"~350 MB",[125,26600,26601,26604,26607,26610],{},[146,26602,26603],{},"Idle CPU en VPS ociosa",[146,26605,26606],{},"\u003C 1%",[146,26608,26609],{},"1 a 3%",[146,26611,26612],{},"1 a 2%",[125,26614,26615,26618,26621,26624],{},[146,26616,26617],{},"Tiempo de instalación típico",[146,26619,26620],{},"5 a 8 minutos",[146,26622,26623],{},"8 a 15 minutos",[146,26625,26626],{},"5 a 10 minutos",[125,26628,26629,26632,26635,26638],{},[146,26630,26631],{},"UI (impresión subjetiva)",[146,26633,26634],{},"datada, funcional",[146,26636,26637],{},"moderna, densa",[146,26639,26640],{},"moderna, austera",[125,26642,26643,26646,26648,26651],{},[146,26644,26645],{},"docker-compose nativo",[146,26647,17489],{},[146,26649,26650],{},"sí, robusto",[146,26652,26653],{},"sí, \"stacks\"",[125,26655,26656,26659,26661,26664],{},[146,26657,26658],{},"Multi-server real",[146,26660,100],{},[146,26662,26663],{},"sí, sin HA del panel",[146,26665,26663],{},[125,26667,26668,26671,26674,26677],{},[146,26669,26670],{},"Marketplace de templates",[146,26672,26673],{},"existente, estancado",[146,26675,26676],{},"grande, activo",[146,26678,26679],{},"básico, en crecimiento",[125,26681,26682,26685,26688,26691],{},[146,26683,26684],{},"Comunidad (estrellas en enero de 2026)",[146,26686,26687],{},"~13 mil",[146,26689,26690],{},"~40 mil",[146,26692,26693],{},"~10 mil",[125,26695,26696,26699,26702,26705],{},[146,26697,26698],{},"Releases en los últimos 6 meses",[146,26700,26701],{},"~3",[146,26703,26704],{},"mensuales",[146,26706,26704],{},[125,26708,26709,26711,26714,26716],{},[146,26710,4895],{},[146,26712,26713],{},"rara",[146,26715,17489],{},[146,26717,26718],{},"prácticamente ninguna",[125,26720,26721,26724,26727,26730],{},[146,26722,26723],{},"Madurez en producción (años)",[146,26725,26726],{},"8+",[146,26728,26729],{},"4+",[146,26731,26732],{},"1+",[125,26734,26735,26737,26740,26743],{},[146,26736,16426],{},[146,26738,26739],{},"1 VPS, 1 a 3 apps",[146,26741,26742],{},"1 a 2 VPS, 2 a 5 apps",[146,26744,26745],{},"2 a 4 VPS, equipo pequeño",[12,26747,26748,26749,26752],{},"La columna que más informa no está visible en esa tabla: ",[27,26750,26751],{},"qué dolor viene en tercer lugar",". CapRover te da estabilidad inmediata y el dolor viene cuando creces y necesitas multi-server. Coolify te da features ricas y el dolor viene en la cuenta de la VPS y en la complejidad creciente. Dokploy te da multi-server moderno y el dolor viene en el acoplamiento a Swarm de largo plazo. Elegir es responder honestamente: ¿cuál de esos tres dolores es el que más cabe en tu próximo año?",[19,26754,26756],{"id":26755},"el-dolor-que-los-tres-comparten","El dolor que los tres comparten",[12,26758,26759,26760,101],{},"Hay un dolor común a los tres que merece nombre propio, porque es donde la transición honesta ocurre: ",[27,26761,26762],{},"ninguno de los tres tiene alta disponibilidad real",[12,26764,26765],{},"Voy a ser preciso sobre lo que eso significa.",[12,26767,26768],{},"CapRover es single-server por diseño. No lo intenta. Instalas, corres en una VPS, punto. Caer el servidor es caer el producto.",[12,26770,26771,26772,26775,26776,26779],{},"Coolify y Dokploy ofrecen multi-server, pero la expresión usada por ambos confunde. Multi-server, en el vocabulario de ellos, significa que un ",[27,26773,26774],{},"panel central"," despliega contenedores en ",[27,26777,26778],{},"N hosts remotos",". El panel vive en una máquina; los hosts son objetivos de deploy. Cuando el servidor del panel cae:",[2735,26781,26782,26785,26788,26791,26794],{},[70,26783,26784],{},"Los apps remotos siguen corriendo (Docker en ellos sigue funcionando).",[70,26786,26787],{},"Pierdes acceso a logs centralizados, métricas, deploys, edición de variables de entorno.",[70,26789,26790],{},"¿Update del panel? Esperar.",[70,26792,26793],{},"¿Redeploy de un app trabado? Esperar.",[70,26795,26796],{},"¿Ver por qué el servicio de checkout empezó a devolver 500? Esperar.",[12,26798,26799],{},"Para un hobby project, \"esperar\" es tolerable. Para startup con primer cliente B2B exigiendo uplink contractual de 99,5%, \"esperar\" es violación de SLA. Los tres productos comparten esa pared.",[12,26801,26802],{},"La pared está señalizada cuando:",[2735,26804,26805,26811,26817,26823,26829],{},[70,26806,26807,26810],{},[27,26808,26809],{},"Cliente exige SLA explícito."," Algo como ≥ 99,5% en el contrato. Best-effort no pasa por el jurídico del cliente.",[70,26812,26813,26816],{},[27,26814,26815],{},"El panel ya cayó una vez por semana ininterrumpidamente."," Puede ser update mal-sucedido, kernel panic, OOM kill en pico de tráfico — la causa importa menos que la frecuencia.",[70,26818,26819,26822],{},[27,26820,26821],{},"Tienes 2 o más aplicaciones importantes en producción."," Backup centralizado se vuelve requisito; coordinación entre apps se vuelve requisito; observabilidad unificada se vuelve requisito.",[70,26824,26825,26828],{},[27,26826,26827],{},"Equipo creció a 3 o más personas y el panel se volvió cuello de botella."," Un deploy bloquea al otro. Acceso simultáneo confunde estado.",[70,26830,26831,26834],{},[27,26832,26833],{},"Backup del panel es manual y no fue probado en meses."," ¿Consigues restaurar la VPS entera en 30 minutos? ¿Ya probaste ese procedimiento en prod?",[12,26836,26837],{},"Cuando dos o más de esos puntos se confirman al mismo tiempo, pasaste de la fase en que CapRover, Coolify y Dokploy resuelven el problema. La siguiente decisión es estructural.",[19,26839,26841],{"id":26840},"heroctl-como-paso-siguiente-natural","HeroCtl como paso siguiente natural",[12,26843,26844],{},"HeroCtl es un archivo ejecutable único que instalas en N servidores Linux con Docker. Los tres primeros servidores forman el plano de control replicado — no hay \"servidor central\" que pueda caer. La coordinación entre ellos sobrevive a la pérdida de cualquiera, con elección automática en torno a siete segundos sin acción humana.",[12,26846,26847],{},"La experiencia de uso para subir aplicación es la misma que ya conoces de los tres paneles: describes el servicio, lo envías vía CLI o panel web, el cluster decide dónde correr, abre el puerto, registra en el router integrado, emite certificado Let's Encrypt automático y empieza a servir tráfico. Actualizar es cambiar la versión de la imagen y enviar de nuevo — rolling update sin ventana de mantenimiento.",[12,26849,26850],{},"La diferencia está en lo que pasa cuando algo sale mal. ¿Servidor cae? Workload migra. Panel \"central\" no existe — cualquiera de los servidores sirve la UI y la API. Nunca estás ciego.",[12,26852,26853,26854,26856,26857,26859,26860,26862],{},"El modelo comercial es explícito desde el día uno. ",[27,26855,4352],{}," es gratuito permanente, sin límite de servidores, sin feature gates artificiales — corre toda la stack arriba incluyendo alta disponibilidad, router, certificados, métricas y logs. Indie hackers y equipos pequeños nunca necesitan salir de aquí. ",[27,26858,4356],{}," añade SSO\u002FSAML, control de acceso granular, auditoría detallada, backup gestionado y soporte con SLA — para cuando tu cliente pasa a exigir los controles formales. ",[27,26861,4360],{}," añade escrow de código fuente, contrato de continuidad y soporte 24×7. Los precios de Business y Enterprise están publicados — sin \"habla con ventas\" obligatorio.",[12,26864,26865],{},"HeroCtl no intenta sustituir a CapRover, Coolify o Dokploy en las franjas en que ellos brillan. Intenta ser el paso lógico después de ellos, cuando la pared de la alta disponibilidad aparece. Los tres siguen excelentes para los perfiles que describimos arriba — no hay razón para cambiar antes de tiempo.",[19,26867,26869],{"id":26868},"decision-por-perfil","Decisión por perfil",[12,26871,26872],{},"Para resolver la indecisión en una frase por perfil:",[2735,26874,26875,26881,26887,26893,26899],{},[70,26876,26877,26880],{},[27,26878,26879],{},"Solo dev, 1 VPS, proyecto hobby o producto temprano."," CapRover. Más liviano, más maduro, menos abandonable.",[70,26882,26883,26886],{},[27,26884,26885],{},"Indie hacker con 2 a 5 apps en 1 o 2 VPS, sin requisito formal de SLA."," Coolify. Marketplace y features listas ahorran tiempo.",[70,26888,26889,26892],{},[27,26890,26891],{},"Equipo pequeño valorando UX moderna, multi-server, proyecto nuevo sin legado de templates, 3 o más VPS."," Dokploy. Apuesta a la ligereza moderna.",[70,26894,26895,26898],{},[27,26896,26897],{},"Startup con primer cliente B2B exigiendo SLA contractual, 3 o más servidores, requisito de alta disponibilidad real."," HeroCtl. El panel deja de ser punto único de fallo.",[70,26900,26901,26904],{},[27,26902,26903],{},"Solo dev sin tiempo para cuidar servidor."," Hospedado: Render, Railway, Vercel, Fly.io. Auto-hosting es compromiso — si no tienes tiempo, pagas.",[12,26906,26907],{},"No hay vergüenza en cambiar de categoría. Empezar en CapRover, migrar a Coolify cuando la complejidad pide más features, eventualmente salir a HeroCtl cuando el cliente pide SLA — eso es camino saludable, no fallo de planeamiento inicial.",[19,26909,26911],{"id":26910},"migracion-entre-los-tres","Migración entre los tres",[12,26913,26914],{},"La buena noticia: lo que sobrevive entre los tres es lo que importa.",[12,26916,26917,26920],{},[27,26918,26919],{},"Imágenes Docker (Dockerfile) sirven en los tres."," Si construiste para CapRover, construyes igual para Coolify y Dokploy. No hay lock-in de runtime.",[12,26922,26923,26926,26927,26929,26930,26933],{},[27,26924,26925],{},"Volúmenes nombrados sobreviven."," Consigues copiar el contenido de un volumen a un host nuevo vía ",[231,26928,2406],{}," con bind mount, o vía ",[231,26931,26932],{},"docker cp",". Postgres dump y restore vale el de siempre.",[12,26935,26936,26939,26940,26942],{},[27,26937,26938],{},"Variables de entorno migran literalmente."," Los tres aceptan las mismas claves. Copiar un ",[231,26941,9374],{}," es trivial.",[12,26944,26945,26948],{},[27,26946,26947],{},"Lo que necesita adaptación manual:"," templates one-click de Coolify (la config interna es específica, reinstalas el servicio desde cero en el destino), stacks Swarm de Dokploy (similar, reescribes), Apps single-container de CapRover (los fragmentas en compose si es para Coolify\u002FDokploy). Configuraciones de dominio, certificado e ingress migran conceptualmente pero la UI de cada panel es específica — rehacer toma una tarde, no una semana.",[12,26950,26951],{},"Para migrar de los tres a HeroCtl, el camino es el mismo: imágenes iguales, variables iguales, configuración de ingress reescrita una vez en el formato de HeroCtl (que es un archivo de configuración de cincuenta líneas, no trescientas).",[19,26953,26955],{"id":26954},"la-pregunta-inevitable-cual-es-el-mas-popular","La pregunta inevitable: \"¿cuál es el más popular?\"",[12,26957,26958],{},"En enero de 2026, en estrellas en el repositorio público (que es proxy débil de uso real, pero es el único proxy mensurable):",[2735,26960,26961,26966,26971],{},[70,26962,26963,26965],{},[27,26964,2771],{},": aproximadamente 40 mil estrellas.",[70,26967,26968,26970],{},[27,26969,26578],{},": aproximadamente 13 mil estrellas.",[70,26972,26973,26975],{},[27,26974,2777],{},": aproximadamente 10 mil estrellas, en crecimiento acelerado.",[12,26977,26978],{},"En uso real en producción, es difícil medir. Coolify tiene la discusión pública más activa — Twitter, Discord, conferencias. CapRover tiene la base instalada más antigua y silenciosa: gente que instaló en 2018 y no habla de eso porque no tiene de qué quejarse. Dokploy tiene el crecimiento más rápido en porcentaje.",[12,26980,26981],{},"Popular no es proxy directo de \"correcto para ti\". CapRover atiende medio millón de devs en silencio sin salir en titular. La elección por popularidad te lleva a Coolify por inercia — y Coolify puede hasta ser correcto, pero que sea por análisis, no por cantidad de tweets.",[19,26983,7352],{"id":7351},[12,26985,26986,26989],{},[27,26987,26988],{},"¿Puedo migrar de CapRover a Coolify sin rehacer todo?","\nRehaces la configuración en el panel nuevo (una tarde de trabajo para dos o tres apps), pero las imágenes Docker y los volúmenes sobreviven. No es refactorización de código — es re-registro en el panel.",[12,26991,26992,26995],{},[27,26993,26994],{},"Dokploy depende de Docker Swarm. ¿Eso es problema?","\nDepende del horizonte. Para los próximos dos años, no. Swarm es estable y funcional. Para horizonte de cinco años, es apostar a una capa que no recibe nuevas features hace tiempo. Si tu proyecto es para durar, vale considerar.",[12,26997,26998,27001],{},[27,26999,27000],{},"¿Cuál usa menos disco?","\nCapRover instala alrededor de 1,5 GB. Dokploy alrededor de 2 a 3 GB. Coolify alrededor de 3 a 5 GB dependiendo de cuántos servicios auxiliares habilites. En una VPS de 25 GB, cualquiera cabe; en una de 10 GB, CapRover es más cómodo.",[12,27003,27004,27007],{},[27,27005,27006],{},"¿Hay soporte en español en alguno?","\nCapRover tiene alguna traducción parcial y tutoriales en español dispersos. Coolify tiene traducción parcial de la UI pero documentación mayoritariamente en inglés. Dokploy es predominantemente en inglés. Para equipo que prefiere material en español, el desempate queda entre CapRover y Coolify; HeroCtl es nativamente en español.",[12,27009,27010,27013],{},[27,27011,27012],{},"¿HeroCtl sustituye a uno de esos o es diferente?","\nDiferente en propuesta. CapRover, Coolify y Dokploy resuelven \"Heroku en 1 VPS\" (o múltiples VPS sin alta disponibilidad del panel). HeroCtl resuelve \"Heroku en cluster con plano de control replicado\". La franja en que tiene sentido es después de superar a los tres — no antes.",[12,27015,27016,27019],{},[27,27017,27018],{},"¿Vale correr panel + cluster orquestador junto?","\nNo. Va a dar conflicto de puertos, conflicto de proxy reverso y dolor de cabeza operacional. Elige uno. Si estás en CapRover\u002FCoolify\u002FDokploy hoy y quieres migrar a HeroCtl, despídete del anterior antes — no corras en paralelo en la misma máquina.",[12,27021,27022,27025],{},[27,27023,27024],{},"¿Y para agencia que aloja 30 sites de cliente?","\nCoolify es la elección popular en ese perfil hoy, por el aislamiento por proyecto y por las features de billing-adjacent (multi-tenancy parcial, usuarios separados). Dokploy empieza a competir en ese nicho. HeroCtl es la elección cuando la agencia crece al punto en que caer el panel deja a 30 clientes sin deploy al mismo tiempo — ahí el punto único de fallo se vuelve inaceptable.",[19,27027,3310],{"id":3309},[12,27029,27030],{},"Los tres productos del segmento simple son buenos en lo que prometen. CapRover envejece bien si no creces demasiado. Coolify entrega el paquete más completo si tienes RAM sobrando. Dokploy hace la apuesta más moderna si aceptas Docker Swarm como base. No hay elección equivocada para los perfiles que describimos — hay elección cara, que es no elegir por las razones correctas.",[12,27032,27033],{},"El día en que los tres dejan de bastar es específico e identificable: cliente exigiendo SLA, panel volviéndose cuello de botella, equipo creciendo, backup volviéndose obligación. Cuando ese día llega, la siguiente herramienta en la secuencia es lo que estamos construyendo.",[12,27035,27036],{},"Si estás eligiendo ahora entre los tres y el cluster aún está distante, eliges por el perfil arriba y sigues. Si el cluster está volviéndose exigencia, instalas en tres VPS:",[224,27038,27040],{"className":27039,"code":5318,"language":2530},[2528],[231,27041,5318],{"__ignoreMap":229},[12,27043,27044,27045,27047,27048,27050,27051,101],{},"Para lectura adicional: la comparativa directa ",[3337,27046,16705],{"href":16704},", la comparativa ",[3337,27049,16710],{"href":16709},", y el panorama ",[3337,27052,19774],{"href":19773},{"title":229,"searchDepth":244,"depth":244,"links":27054},[27055,27056,27057,27058,27059,27060,27061,27062,27063,27064,27065],{"id":26475,"depth":244,"text":26476},{"id":26507,"depth":244,"text":26508},{"id":26537,"depth":244,"text":26538},{"id":26563,"depth":244,"text":26564},{"id":26755,"depth":244,"text":26756},{"id":26840,"depth":244,"text":26841},{"id":26868,"depth":244,"text":26869},{"id":26910,"depth":244,"text":26911},{"id":26954,"depth":244,"text":26955},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-01-19","Los tres paneles dominantes para correr 'Heroku en 1 VPS'. Cada uno apuesta a una filosofía diferente — madurez, riqueza de features, o peso ligero. Comparativa honesta para elegir sin arrepentimiento.",{},"\u002Fes\u002Fblog\u002Fcaprover-vs-coolify-vs-dokploy",{"title":26434,"description":27067},{"loc":27069},"es\u002Fblog\u002Fcaprover-vs-coolify-vs-dokploy",[27074,27075,26429,22492,24194,14948],"caprover","coolify","heuV-5pl2_6HIqNO9GP9kOQbsNxXt1A6dFBmKMPD-Vw",{"id":27078,"title":27079,"author":7,"body":27080,"category":8761,"cover":3380,"date":27527,"description":27528,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":27529,"navigation":411,"path":16704,"readingTime":4402,"seo":27530,"sitemap":27531,"stem":27532,"tags":27533,"__hash__":27535},"blog_es\u002Fes\u002Fblog\u002Fheroctl-vs-coolify.md","HeroCtl vs Coolify: cuando el panel de un servidor no basta",{"type":9,"value":27081,"toc":27516},[27082,27085,27088,27092,27095,27098,27106,27116,27119,27123,27126,27129,27132,27146,27149,27152,27156,27159,27162,27165,27168,27185,27188,27191,27195,27198,27201,27204,27207,27210,27212,27215,27342,27345,27348,27352,27355,27361,27367,27373,27379,27385,27388,27392,27395,27401,27407,27413,27419,27422,27425,27427,27433,27439,27445,27451,27457,27463,27469,27475,27477,27480,27483,27486,27489,27505,27511,27514],[12,27083,27084],{},"La pregunta nunca fue \"¿Coolify es bueno?\". Es bueno, sí. La pregunta es \"¿hasta cuándo Coolify es suficiente?\".",[12,27086,27087],{},"Este post no es sobre desbancar nada. Es sobre dibujar una línea — donde el panel en un servidor único deja de ser la respuesta correcta y empieza a ser una trampa silenciosa que aparece en el peor momento posible: en la primera reunión con el primer cliente que pregunta el número del SLA.",[19,27089,27091],{"id":27090},"por-que-coolify-gano-el-segmento","Por qué Coolify ganó el segmento",[12,27093,27094],{},"Vale la pena empezar reconociendo lo que Coolify acertó, sin ironía.",[12,27096,27097],{},"Instalación de cinco minutos en una VPS de US$10 al mes. Panel limpio, con un vocabulario familiar para cualquier persona que ya tocó Heroku o Vercel. Plugin ecosystem activo, comunidad comprometida, lanzamientos frecuentes. El contrato gratuito para self-hosting nunca cambió.",[12,27099,27100,27101,27103,27104,101],{},"Para un indie hacker en abril de 2026, con un servidor de 4 GB de RAM ejecutando un SaaS de US$5 mil de MRR, Coolify es la mejor opción que existe en el mercado. Mejor que Dokku, mejor que Caprover, mejor que ",[3337,27102,2777],{"href":16709}," en madurez — e infinitamente mejor que orquestar la misma carga en Kubernetes gestionado, que cobraría US$73 al mes solo por el plano de control, antes de NAT, balanceador y cualquier cosa que entregue valor — asunto que destrozamos en ",[3337,27105,21924],{"href":15790},[12,27107,27108,27109,27112,27113,27115],{},"La categoría \"",[3337,27110,27111],{"href":19773},"Heroku auto-hospedado simple","\" fue inventada por esa generación de herramientas. Coolify, ",[3337,27114,2777],{"href":16709},", Caprover dividen ese podio. Coolify lidera en adopción, en comunidad y en ritmo de release. No es por casualidad.",[12,27117,27118],{},"El punto de este artículo es específico: existe una pared que aparece cuando tu producto crece, y esa pared no tiene solución elegante dentro de Coolify. Es un límite arquitectural, no un bug que se vaya a arreglar.",[19,27120,27122],{"id":27121},"la-pared-invisible-el-servidor-unico","La pared invisible: el servidor único",[12,27124,27125],{},"Coolify fue diseñado en torno a un servidor central. El panel vive ahí. La base de configuración vive ahí. Las decisiones de deploy parten de ahí.",[12,27127,27128],{},"Eso es una elección de diseño coherente — para quien está en una sola VPS, esa centralización es exactamente lo que vuelve el producto tan simple. No hay red de cluster que debuguear, no hay certificado entre nodos, no hay replicación de estado que entender. Enciendes una máquina, instalas, deployas. Cinco minutos.",[12,27130,27131],{},"La cuestión es lo que sucede en los escenarios siguientes:",[2735,27133,27134,27137,27140,27143],{},[70,27135,27136],{},"El disco de la VPS empieza a presentar errores de I\u002FO. El proveedor agenda mantenimiento para \"remediar\". La máquina queda indisponible por tres horas en una madrugada de miércoles. Todo lo que corría en ella está fuera.",[70,27138,27139],{},"Un update del kernel es empujado por el proveedor y la máquina reinicia sola. El panel de Coolify vuelve — pero tres contenedores entran en loop de restart porque dependen de un volume mount que aún está siendo remontado. Lo descubres cuarenta minutos después, por el Twitter de un cliente.",[70,27141,27142],{},"El datacenter entero del proveedor tiene un incidente de red regional. Sucede en enero de 2024 con un gran proveedor europeo, en octubre de 2024 con un proveedor americano, en febrero de 2026 con un proveedor latinoamericano. Tu máquina ni siquiera está con defecto — solo quedó inalcanzable.",[70,27144,27145],{},"Un deploy malo consume toda la memoria de la máquina, el OOM killer empieza a tirar procesos, y el propio panel de Coolify entra en loop. No tienes dónde clicar para revertir porque la interfaz que controla el cluster está dentro de la máquina que necesita ser controlada.",[12,27147,27148],{},"En todos esos escenarios, la respuesta operacional es la misma: rezar para que la máquina vuelva, o abrir un ticket, o subir una nueva máquina y restaurar backup. No hay failover automático. No hay otra réplica del panel para asumir. No hay elección de coordinador entre servidores sobrevivientes — porque solo existe un servidor.",[12,27150,27151],{},"Cuando tu primer cliente serio pregunta \"¿cuál es el SLA?\", la respuesta honesta es \"best-effort, nuestra máquina principal tiene tres nueves de uptime histórico del proveedor\". Es una respuesta que funciona para algunos clientes. No funciona para clientes que tienen el propio SLA por honrar. Y son justamente esos clientes los que pagan contratos anuales.",[19,27153,27155],{"id":27154},"multi-servidor-en-coolify-no-es-alta-disponibilidad-real","Multi-servidor en Coolify no es alta disponibilidad real",[12,27157,27158],{},"La confusión más común en esta conversación es el feature \"remote servers\" de Coolify.",[12,27160,27161],{},"Coolify permite, sí, conectar máquinas adicionales como destinos de deploy. Registras un IP, configuras una clave SSH, y el panel pasa a saber que puede subir contenedores en aquella máquina remota. Para quien necesita separar staging de producción, o colocar workers en una máquina más barata, es útil de verdad.",[12,27163,27164],{},"Pero eso no es alta disponibilidad. Es distribución de carga.",[12,27166,27167],{},"La diferencia está en dónde vive el cerebro del sistema. En Coolify, el cerebro es la máquina principal — donde el panel corre, donde la base SQLite o Postgres de Coolify vive, donde las colas internas están. Las máquinas remotas son brazos. Si el cerebro se cae, los brazos siguen sosteniendo lo que tenían en las manos en el momento de la caída — los contenedores ya en ejecución no mueren. Pero pierdes:",[2735,27169,27170,27173,27176,27179,27182],{},[70,27171,27172],{},"El panel web, integralmente.",[70,27174,27175],{},"La capacidad de hacer deploys, revertir, cambiar variable de entorno, leer log centralizado.",[70,27177,27178],{},"La capacidad de redirigir tráfico entre réplicas si una se cae.",[70,27180,27181],{},"Renovación automática de certificados (si la máquina principal era la que respondía al desafío ACME).",[70,27183,27184],{},"Health checks que reiniciarían contenedores con problema.",[12,27186,27187],{},"Quedas en un estado zombi: el sitio del cliente puede seguir respondiendo por algunas horas, pero perdiste el control del orquestador. Reencender la máquina principal se vuelve la única operación útil — y si la razón de la caída fue disco corrupto, estás restaurando backup a las cuatro de la mañana.",[12,27189,27190],{},"Eso no es fallo de Coolify. Es una consecuencia directa del diseño arquitectural — diseño que tiene total sentido para quien nunca va a necesitar nada además de eso. El problema es cuando tu empresa crece y las expectativas del cliente cambian. La herramienta no crece junto.",[19,27192,27194],{"id":27193},"el-paso-siguiente-natural","El paso siguiente natural",[12,27196,27197],{},"HeroCtl empieza exactamente donde Coolify para. Misma promesa de instalación simple — un comando, cinco minutos, panel web listo. Pero el cerebro del sistema es replicado entre tres o más servidores desde el primer momento.",[12,27199,27200],{},"En términos prácticos: instalas el mismo binario en tres máquinas Linux con Docker. Los tres servidores combinan estado entre sí por consenso entre servidores. Decisiones importantes (qué contenedor va a qué nodo, qué versión está activa, qué certificado está renovado) son grabadas en el log replicado y confirmadas solo después de que la mayoría concordó. Si uno de los tres se cae — kill -9, caída de energía, partición de red — los dos que sobraron eligen un nuevo coordinador en unos siete segundos y siguen sirviendo tráfico.",[12,27202,27203],{},"No es magia. Es una técnica conocida hace veinte años, usada en producción por bancos, por sistemas de mensajería, por bancos de datos distribuidos. La novedad de HeroCtl es empaquetar eso en un paquete que instalas en cinco minutos, con panel web embebido y sin exigir un operador especializado.",[12,27205,27206],{},"El router integrado distribuye el tráfico entrante entre las réplicas saludables automáticamente. Si un servidor está fuera, deja de recibir peticiones — sin que necesites tocar el DNS, sin que necesites despertarte de madrugada. Los certificados Let's Encrypt viven en el log replicado, así que cualquier servidor sobreviviente puede renovarlos y servirlos; no hay \"máquina principal\" responsable del TLS.",[12,27208,27209],{},"La batería de tests de caos cubre los escenarios reales: kill -9 del coordinador (elección en siete segundos, sin pérdida de petición de lectura), partición de red de 30 segundos (cluster reconverge solo), pérdida momentánea de quórum (sistema entra en modo solo-lectura preservando el tráfico existente, retoma escrituras cuando el quórum vuelve), wipe de disco en un nodo (rejoina el cluster y baja el estado del log replicado), drain forzado (workloads migran a los nodos sobrevivientes en segundos). Los cinco escenarios sobrevividos en el cluster público que sirve este blog.",[19,27211,23242],{"id":23241},[12,27213,27214],{},"La tabla siguiente es la versión honesta. No hay columna sin reservas — toda herramienta de orquestación es un conjunto de tradeoffs, y HeroCtl también.",[119,27216,27217,27227],{},[122,27218,27219],{},[125,27220,27221,27223,27225],{},[128,27222,2983],{},[128,27224,2771],{},[128,27226,2995],{},[141,27228,27229,27239,27249,27259,27270,27280,27289,27298,27307,27315,27324,27332],{},[125,27230,27231,27234,27237],{},[146,27232,27233],{},"Tiempo de instalación",[146,27235,27236],{},"5 minutos",[146,27238,27236],{},[125,27240,27241,27243,27246],{},[146,27242,25614],{},[146,27244,27245],{},"Sí, central",[146,27247,27248],{},"Sí, embebido en todos los servidores",[125,27250,27251,27253,27256],{},[146,27252,3924],{},[146,27254,27255],{},"Sí (en la máquina principal)",[146,27257,27258],{},"Sí, replicados entre servidores",[125,27260,27261,27264,27267],{},[146,27262,27263],{},"Multi-servidor",[146,27265,27266],{},"Sí, como destinos de deploy",[146,27268,27269],{},"Sí, como cluster de plano de control",[125,27271,27272,27274,27277],{},[146,27273,16336],{},[146,27275,27276],{},"No — panel es punto único de fallo",[146,27278,27279],{},"Sí — sobrevive a la pérdida de servidores",[125,27281,27282,27284,27286],{},[146,27283,23281],{},[146,27285,26195],{},[146,27287,27288],{},"Sí, ~7s tras caída",[125,27290,27291,27293,27296],{},[146,27292,23315],{},[146,27294,27295],{},"No embebida",[146,27297,23321],{},[125,27299,27300,27302,27305],{},[146,27301,25641],{},[146,27303,27304],{},"Plugin\u002Fintegración externa",[146,27306,25646],{},[125,27308,27309,27311,27313],{},[146,27310,22806],{},[146,27312,27304],{},[146,27314,22329],{},[125,27316,27317,27319,27322],{},[146,27318,22839],{},[146,27320,27321],{},"Open-source con nube paga opcional",[146,27323,25675],{},[125,27325,27326,27328,27330],{},[146,27327,16410],{},[146,27329,22214],{},[146,27331,22214],{},[125,27333,27334,27336,27339],{},[146,27335,16426],{},[146,27337,27338],{},"1 servidor (hasta 3 con remote servers)",[146,27340,27341],{},"3 a 500 servidores",[12,27343,27344],{},"La línea que más importa para esta conversación es la quinta — alta disponibilidad real. Las demás son consecuencias de ella. Sin consenso entre servidores, no se puede tener panel resiliente. Sin panel resiliente, no se puede prometer SLA. Sin SLA, algunos clientes no cierran contrato.",[12,27346,27347],{},"La última línea también merece atención. Coolify es increíble con un servidor. HeroCtl es increíble con tres a quinientos. No son productos de la misma franja — son productos que cubren franjas adyacentes del mismo problema.",[19,27349,27351],{"id":27350},"cuando-quedarse-en-coolify","Cuándo quedarse en Coolify",[12,27353,27354],{},"Esta sección existe porque la honestidad es el mecanismo de defensa de una herramienta nueva. Si decimos \"todo el mundo debería usar HeroCtl\", estamos errando. Hay cinco perfiles en los que recomendamos firmemente continuar en Coolify.",[12,27356,27357,27360],{},[27,27358,27359],{},"Tienes un solo servidor y no pretendes tener más.","\nSi tu arquitectura cabe entera en una VPS de 4 u 8 GB de RAM, y tu modelo de negocio no exige SLA contractual, Coolify es la respuesta correcta. HeroCtl ejecutándose en un servidor único funciona, pero estás pagando el overhead de una capa de coordinación que nunca va a necesitar coordinar con nadie. Es como comprar un coche de cinco plazas para hacer solo viajes solo — no está mal, solo es innecesario.",[12,27362,27363,27366],{},[27,27364,27365],{},"Estás ejecutando aplicaciones internas o de desarrollo.","\nEntornos de staging, dashboards internos, herramientas que solo usa tu equipo, side-projects experimentales — todos esos casos no justifican multiplicar servidores. Una caída de dos horas en un staging no cuesta nada más allá de la molestia. Coolify entrega el mejor coste-beneficio para ese tipo de workload, y lo recomendamos abiertamente.",[12,27368,27369,27372],{},[27,27370,27371],{},"Eres hobby developer.","\nProyectos personales, blogs, portfolios, experimentos con APIs nuevas — quédate en Coolify. El coste mental de operar un cluster de tres servidores es mayor que la ganancia percibida. Quieres publicar cosa, no administrar infraestructura. Coolify fue diseñado para ese perfil. No vamos a intentar empujar una herramienta con más ceremonia operacional de la que el caso pide.",[12,27374,27375,27378],{},[27,27376,27377],{},"Tienes dependencia fuerte de plugins del ecosistema Coolify.","\nSi tu flujo depende de tres plugins específicos de Coolify para integrar con servicios terceros que aún no tenemos integración nativa, migrar ahora es prematuro. Espera a que HeroCtl madure esas integraciones o evalúa si la integración específica vale el trabajo de reescribir. Preferimos que esperes a que la integración exista que migrar y descubrir un agujero a mitad de camino.",[12,27380,27381,27384],{},[27,27382,27383],{},"No estás sintiendo dolor.","\nEse es el criterio más importante y el más subestimado. Si Coolify nunca falló para ti, si tu máquina principal tiene tres años de uptime, si ningún cliente tuyo ya cobró SLA — no migres por moda. Migración de herramienta de orquestación tiene coste real (una a dos semanas de un ingeniero senior, más ajustes). Paga ese coste solo cuando el dolor lo justifique. Migrar antes de sentir dolor es una forma elegante de quemar tiempo de ingeniería que podría estar volviéndose producto.",[12,27386,27387],{},"La regla mental simple: si la frase \"si esa máquina se cae a las tres de la mañana, tengo problema serio con cliente\" describe tu situación, es hora de evaluar. Si la frase \"si esa máquina se cae a las tres de la mañana, me despierto mañana, reenciendo, y todo sigue\" describe, quédate donde estás.",[19,27389,27391],{"id":27390},"como-migrar-cuando-tiene-sentido","Cómo migrar cuando tiene sentido",[12,27393,27394],{},"La migración no necesita ser un big bang. El camino que recomendamos es gradual, en cuatro etapas, y mantiene Coolify funcionando todo el tiempo.",[12,27396,27397,27400],{},[27,27398,27399],{},"Etapa 1 — Subir el cluster HeroCtl en paralelo."," Tres servidores nuevos, en la misma región, sin tocar el Coolify existente. Corre el instalador en cada uno, los junta en el cluster, abre el panel. Validación básica: el panel responde en los tres IPs, certificado de prueba es emitido, un contenedor \"hello world\" sube y responde. Tiempo medio: una tarde.",[12,27402,27403,27406],{},[27,27404,27405],{},"Etapa 2 — Migrar una aplicación de bajo riesgo."," Elige una aplicación interna o de bajísimo tráfico. Algo que, si queda fuera por diez minutos, no causa pánico. Reescribe el archivo de configuración en el formato de HeroCtl (en general, cincuenta líneas sustituyen lo que era un conjunto de campos en el panel de Coolify). Súbela en el cluster nuevo. Apunta un subdominio de prueba. Valida por una semana.",[12,27408,27409,27412],{},[27,27410,27411],{},"Etapa 3 — Migrar workloads con tráfico real, una a la vez."," Para cada aplicación migrada, haz blue-green: sube la versión en HeroCtl, apunta el DNS a HeroCtl, mantén Coolify ejecutando la versión antigua por 24 a 72 horas como fallback. Si algo sale mal, rollback es cambiar el DNS de vuelta. Cuando todo se estabilice, apaga la aplicación en Coolify.",[12,27414,27415,27418],{},[27,27416,27417],{},"Etapa 4 — Apagar Coolify."," Cuando todas las aplicaciones migraron y se estabilizaron por una semana o dos, apaga la máquina del Coolify. Mantén el backup de la base del Coolify por un trimestre más, por garantía. Ahí sí, encierra la VPS.",[12,27420,27421],{},"El punto alto de ese camino es que en ningún momento te quedas sin opción de rollback. Coolify sigue ejecutándose hasta el último día. Si la migración sale mal en alguna etapa, vuelves un paso, ajustas, lo intentas de nuevo. No hay \"punto de no retorno\" forzado por arquitectura.",[12,27423,27424],{},"Tiempo total típico, para un portfolio de diez a veinte aplicaciones: dos a tres semanas, con un ingeniero dedicando la mitad del tiempo. Para portfolios mayores, escala linealmente.",[19,27426,7352],{"id":7351},[12,27428,27429,27432],{},[27,27430,27431],{},"Coolify deploya en N servidores también. ¿Cuál es la diferencia real?","\nCoolify deploya contenedores en N servidores. HeroCtl ejecuta el orquestador en N servidores. La diferencia es dónde vive el cerebro. En Coolify, el cerebro vive en la máquina principal — máquinas remotas son brazos. En HeroCtl, el cerebro es distribuido: tres o más servidores combinan estado por consenso, y cualquiera puede asumir el rol de coordinador si el actual se cae. Es la misma diferencia entre \"tener copias de un documento en varios ordenadores\" y \"tener un documento colaborativo en tiempo real\". Los dos tienen múltiples máquinas; solo el segundo sobrevive a la pérdida de una de ellas sin perder control.",[12,27434,27435,27438],{},[27,27436,27437],{},"¿Puedo usar Coolify y HeroCtl juntos?","\nSí, y durante una migración es la recomendación. Los dos ejecutan Docker como runtime, así que no disputan recursos en el nivel del contenedor. Lo que cambia es qué orquestador mira a qué conjunto de máquinas. Técnicamente, se puede mantener aplicaciones antiguas en Coolify para siempre y usar HeroCtl solo para workloads nuevos con requisito de HA — algunos equipos eligen ese enfoque y nunca llegan a apagar Coolify. No hay acoplamiento forzado.",[12,27440,27441,27444],{},[27,27442,27443],{},"¿Cuánto cuesta migrar?","\nEl coste directo es tiempo de ingeniería: dos a tres semanas de medio tiempo para un portfolio típico. El coste indirecto es la curva de aprendizaje del archivo de configuración nuevo — generalmente medio día para un ingeniero senior agarrarle la onda. No hay coste de licencia para migrar (HeroCtl Community es gratuito permanente, sin límite de servidores o de jobs), ni coste de salida del Coolify (simplemente paras de usar). El coste de oportunidad es el ingeniero no estar haciendo otra cosa en aquellas dos semanas.",[12,27446,27447,27450],{},[27,27448,27449],{},"¿Qué pierdo de Coolify?","\nLa interfaz visual de Coolify es más amigable para quien nunca vio nada de orquestación — es un trade real. Algunos plugins del ecosistema Coolify aún no tienen equivalente en HeroCtl, especialmente integraciones con servicios de nicho. La comunidad de Coolify es mayor en volumen — foros tienen más respuestas para preguntas específicas. Y ciertas conveniencias de UI (templates pre-configurados para aplicaciones famosas) aún no están en la misma paridad. Esos puntos son reales y los reconocemos.",[12,27452,27453,27456],{},[27,27454,27455],{},"¿Y los plugins de Coolify que uso?","\nCada uno se vuelve un análisis individual. Para integraciones con bases gestionadas (Postgres, Redis), HeroCtl ejecuta esos servicios como jobs comunes — sin necesidad de plugin específico. Para integraciones con servicios externos (envío de email, observabilidad SaaS), en general es una variable de entorno apuntando a la API del proveedor — replicable en cualquier orquestador. Para plugins muy específicos, vale escribirnos — en algunos casos, equivalente nativo ya está en el roadmap.",[12,27458,27459,27462],{},[27,27460,27461],{},"Solo tengo un servidor ahora. ¿Vale la pena ya empezar con HeroCtl?","\nHonestamente: no. Si tienes un solo servidor y ninguna intención de añadir más en los próximos seis meses, Coolify es mejor para tu caso. HeroCtl ejecutándose en un único servidor funciona, pero estás pagando overhead de coordinación que no tiene con quién coordinar. La hora correcta de empezar con HeroCtl es cuando sabes que vas a tener tres o más servidores — sea porque el tráfico creció, sea porque el cliente pidió SLA, sea porque quieres dormir mejor. Antes de eso, quédate en Coolify.",[12,27464,27465,27468],{},[27,27466,27467],{},"¿Cuándo salen los precios de Business y Enterprise?","\nYa están publicados en la página de planes, sin \"habla con ventas\". Business añade SSO\u002FSAML, RBAC granular, auditoría detallada, backup gestionado y soporte con SLA — para equipos con requisitos formales de plataforma. Enterprise añade escrow de código fuente, contrato de continuidad y soporte 24×7. El contrato es congelado para clientes existentes — no hay cláusula de cambio retroactivo. Community sigue gratuita permanente, sin límite de servidores, sin límite de jobs, sin feature gates artificiales. Individuos y equipos pequeños nunca necesitan salir de Community.",[12,27470,27471,27474],{},[27,27472,27473],{},"¿Y si quiero volver a Coolify después de migrar?","\nPosible. Los contenedores ejecutan Docker en ambos casos — las imágenes son las mismas. Lo que cambia es el archivo de configuración y el panel. Volver significa recrear las configuraciones en Coolify y reapuntar el DNS. Nunca trancamos a nadie: el binario de HeroCtl no tiene phone-home obligatorio, no hay kill-switch remoto, y el cluster instalado sigue funcionando offline para siempre. Si tu decisión es apagar y volver, es solo apagar y volver. La libertad de salida es lo que vuelve la confianza honesta.",[19,27476,3310],{"id":3309},[12,27478,27479],{},"La elección entre Coolify y HeroCtl no es técnica, es situacional.",[12,27481,27482],{},"Coolify es la respuesta correcta para una fase específica del crecimiento de un producto: solo dev, MRR inicial, un servidor, sin presión de SLA. HeroCtl es la respuesta correcta para la fase siguiente: equipo pequeño, MRR creciente, tres o más servidores, primeros contratos con SLA, primeros clientes que cobran disponibilidad. Las dos herramientas atienden perfiles adyacentes del mismo problema.",[12,27484,27485],{},"Si estás en la primera fase, instalas Coolify y eres feliz. Si estás entrando en la segunda fase y sientes la pared llegando, HeroCtl te encuentra del otro lado.",[12,27487,27488],{},"Para empezar, en cualquiera de los tres servidores Linux con Docker:",[224,27490,27491],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,27492,27493],{"__ignoreMap":229},[234,27494,27495,27497,27499,27501,27503],{"class":236,"line":237},[234,27496,1220],{"class":247},[234,27498,2958],{"class":251},[234,27500,2961],{"class":255},[234,27502,2964],{"class":383},[234,27504,2967],{"class":247},[12,27506,27507,27508,101],{},"La instalación corre en cinco minutos, el panel sube en cada uno de los servidores, y el cluster está listo para recibir jobs. Para más sobre por qué HeroCtl existe y qué problema intenta resolver, ",[3337,27509,27510],{"href":6545},"lee el post de fundación",[12,27512,27513],{},"La intención es simple: orquestación de contenedores, sin ceremonia — ahora con cluster.",[3351,27515,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":27517},[27518,27519,27520,27521,27522,27523,27524,27525,27526],{"id":27090,"depth":244,"text":27091},{"id":27121,"depth":244,"text":27122},{"id":27154,"depth":244,"text":27155},{"id":27193,"depth":244,"text":27194},{"id":23241,"depth":244,"text":23242},{"id":27350,"depth":244,"text":27351},{"id":27390,"depth":244,"text":27391},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2026-01-13","Coolify resuelve solo dev brillantemente. Cuando el cliente pide SLA y el servidor único se vuelve punto único de fallo, la historia cambia. Comparativo honesto.",{},{"title":27079,"description":27528},{"loc":16704},"es\u002Fblog\u002Fheroctl-vs-coolify",[27075,27534,8775,22492],"alta-disponibilidad","XRlKGGGn4F19VkBpXmt7D5MAdreMx1DRju7tiPhdpnE",{"id":27537,"title":27538,"author":7,"body":27539,"category":3379,"cover":3380,"date":28319,"description":28320,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":28321,"navigation":411,"path":11730,"readingTime":8766,"seo":28322,"sitemap":28323,"stem":28324,"tags":28325,"__hash__":28329},"blog_es\u002Fes\u002Fblog\u002Fbackup-de-base-de-datos-en-cluster.md","Backup de base de datos en cluster: las estrategias que sobreviven a las 3 de la mañana",{"type":9,"value":27540,"toc":28304},[27541,27548,27554,27557,27560,27564,27570,27573,27576,27580,27583,27589,27598,27601,27607,27611,27618,27624,27633,27639,27658,27661,27667,27671,27674,27684,27689,27694,27699,27718,27721,27724,27729,27733,27736,27746,27752,27758,27764,27769,27778,27783,27801,27804,27809,27813,27816,27819,27824,27829,27834,27839,27846,27849,27854,27858,27861,27866,27871,27876,27881,27884,27889,27891,27894,28096,28099,28103,28106,28112,28118,28124,28130,28136,28140,28143,28152,28158,28164,28170,28176,28180,28183,28186,28189,28192,28195,28198,28200,28211,28217,28223,28237,28246,28252,28262,28264,28267,28270,28273,28290,28299,28302],[12,27542,27543,27544,27547],{},"Tres de la mañana. La alerta te despierta porque el endpoint de health check está devolviendo 500 desde hace doce minutos. Abres el terminal somnoliento, te conectas a la base de producción, y la primera query devuelve ",[231,27545,27546],{},"ERROR: invalid page in block 4421 of relation base\u002F16384\u002F24576",". Corrupción física. Postgres aún responde algunas peticiones pero está entregando datos podridos a la mitad de los clientes que caben en la parte sana de las páginas.",[12,27549,27550,27551,27553],{},"Recuerdas el cron de ",[231,27552,5736],{}," que corre a las 3 de la mañana. Miras el reloj: 3h12. El cron empezó hace doce minutos. O sea, el backup que está siendo grabado ahora mismo en S3 es la fotografía de la corrupción. El backup anterior tiene 24 horas. Tienes 24 horas de pedidos, pagos, mensajes y subidas que perder, o una base corrupta que restaurar.",[12,27555,27556],{},"Ese es el escenario en que toda decisión sobre backup se cobra. No es en reunión de arquitectura. No es en retro de sprint. Es a las tres de la mañana, contigo solo en un terminal, decidiendo entre dos malos.",[12,27558,27559],{},"Este post abre los cinco modelos de backup que existen para base de datos en cluster, con los números honestos de cuánto cada uno pierde y cuánto cada uno tarda en volver. Cada estrategia tiene una franja de SaaS donde es la elección correcta — y una franja donde es negligencia. La diferencia es la etapa en que tu empresa está, no el estilo de quien la configuró.",[19,27561,27563],{"id":27562},"la-frase-que-define-todo-backup-que-nunca-fue-restaurado-es-placebo","La frase que define todo: backup que nunca fue restaurado es placebo",[12,27565,27566,27567,27569],{},"La mayoría de los equipos tiene opinión confiada sobre backup y práctica frágil. \"Tiene cron de ",[231,27568,5736],{}," a S3\" es el equivalente operacional de \"tiene extintor pero nunca probó que funciona\". La confianza viene de tener el archivo ahí en el bucket. La fragilidad viene de nunca haber realmente tirado ese archivo, restaurado en un ambiente aislado, validado conteo de filas, comprobado checksums.",[12,27571,27572],{},"Backup es el tipo de sistema en que la versión \"funciona hasta dejar de funcionar\" es indistinguible de la versión \"funciona de verdad\" — hasta el momento exacto en que lo necesitas. Los dos primeros años de un SaaS se viven en el estado de Schrödinger: el backup está vivo y muerto al mismo tiempo, y nadie abrió la caja.",[12,27574,27575],{},"Este texto es el ejercicio de abrir la caja antes del incidente. Las cinco estrategias abajo están organizadas de forma creciente en complejidad y en garantía. Para cada una, la pregunta es: ¿cuántos datos pierdo? ¿cuánto tiempo quedo fuera? ¿cuánto cuesta? y — el criterio que nadie toma en serio hasta necesitarlo — ¿cuánta competencia interna exige?",[19,27577,27579],{"id":27578},"rpo-y-rto-sin-buzzword","RPO y RTO sin buzzword",[12,27581,27582],{},"Antes de comparar estrategias, dos números necesitan estar sobre la mesa. Tienen siglas pesadas pero el concepto es simple.",[12,27584,27585,27588],{},[27,27586,27587],{},"RPO — Recovery Point Objective."," Cuántos datos aceptas perder. Es la distancia entre el \"ahora\" del incidente y el último punto consistente que consigues restaurar. Backup diario a las 3 de la mañana significa RPO de hasta 24 horas — si la corrupción ocurre a las 2 de la mañana del día siguiente, pierdes 23 horas de transacciones. Backup continuo significa RPO de segundos.",[12,27590,27591,27594,27595,27597],{},[27,27592,27593],{},"RTO — Recovery Time Objective."," Cuánto tiempo aceptas estar offline. Es la distancia entre el \"empezó el incidente\" y el \"está sirviendo tráfico de nuevo\". Restore de ",[231,27596,5736],{}," en una base de 50 GB toma entre 30 y 60 minutos en una máquina decente. Failover a réplica streaming toma 30 segundos.",[12,27599,27600],{},"Ambos cuestan dinero de formas diferentes. RPO bajo cuesta storage y ancho de banda continuo (cada commit necesita volverse bytes durados en algún lugar antes de ser confirmado al cliente). RTO bajo cuesta hardware redundante — una réplica caliente es literalmente otra base corriendo, consumiendo CPU, RAM y disco en paralelo, sin servir tráfico en momento normal.",[12,27602,27603,27604,27606],{},"Definir RPO y RTO antes de implementar evita el error más común: gastar mucho para resolver el lado equivocado. Equipo que paga US$300 al mes de read replica y aún pierde 24 horas de datos cuando el disco se corrompe gastó mal — compró RTO bajo e ignoró RPO. Equipo que hace ",[231,27605,5736],{}," quincenal en bucket cross-region cifrado también gastó mal — compró durabilidad extrema y aceptó RTO de horas que el cliente B2B no tolera.",[19,27608,27610],{"id":27609},"estrategia-1-cron-pg_dump-a-s3","Estrategia 1 — Cron + pg_dump a S3",[12,27612,27613,27614,27617],{},"La versión MVP. Un cron job en el servidor de la base, ejecuta ",[231,27615,27616],{},"pg_dump | gzip | aws s3 cp"," a las tres de la mañana. Bucket cross-region con lifecycle policy: archivos con más de 30 días migran a storage frío, con más de 90 días son borrados.",[12,27619,27620,27623],{},[27,27621,27622],{},"RPO real:"," 24 horas en el camino normal. Puede llegar a 48 si el cron falla una noche y nadie lo nota.",[12,27625,27626,27629,27630,27632],{},[27,27627,27628],{},"RTO real:"," 30 a 60 minutos para base de hasta 50 GB. El ",[231,27631,21218],{}," de un dump comprimido corre cerca de la velocidad de I\u002FO del disco — una máquina con SSD decente hace 1 a 2 GB por minuto, contando el tiempo de crear índices.",[12,27634,27635,27638],{},[27,27636,27637],{},"Funciona para:"," proyecto personal, MVP, herramienta interna, app donde 24 horas de datos es recuperable humanamente. Plataforma de registro donde el cliente rehace lo que perdió. Herramienta de caché que rehidrata del upstream. SaaS B2C en los primeros 100 usuarios, donde \"perdimos un día, perdona\" es respuesta aceptable.",[12,27640,27641,27644,27645,6833,27647,27650,27651,27653,27654,27657],{},[27,27642,27643],{},"Donde duele:"," backup caliente en base transaccional puede capturar estado inconsistente entre tablas relacionadas si no usas las flags correctas. ",[231,27646,5736],{},[231,27648,27649],{},"--serializable-deferrable"," resuelve consistencia transaccional pero puede bloquear writes pesados. La versión paralela con ",[231,27652,21674],{}," es más rápida pero exige ",[231,27655,27656],{},"--format=directory",", lo que complica el pipe directo a S3 — terminas necesitando disco temporal local.",[12,27659,27660],{},"Y el restore es lento de una manera que sorprende. Base de 200 GB que parecía \"solo un poco grande\" se vuelve tres horas de restore con índices siendo reconstruidos. Tres horas en que tu plataforma está fuera.",[12,27662,27663,27666],{},[27,27664,27665],{},"Coste:"," US$1 a US$6 al mes de storage S3-compatible para retención razonable. Tiempo humano: cero después del setup, diez minutos al mes para revisar log del cron.",[19,27668,27670],{"id":27669},"estrategia-2-pg_basebackup-wal-archiving","Estrategia 2 — pg_basebackup + WAL archiving",[12,27672,27673],{},"La primera vez que el RPO baja de \"un día\" a \"algunos minutos\". La idea es separar dos cosas: la fotografía completa de la base (basebackup) y el historial de cambios desde la última fotografía (WAL — Write-Ahead Log, el archivo donde Postgres escribe cada commit antes de aplicarlo en los datos).",[12,27675,27676,27677,27679,27680,27683],{},"Setup: ",[231,27678,17246],{}," semanal graba un snapshot completo del directorio de datos. En paralelo, el ",[231,27681,27682],{},"archive_command"," de Postgres copia cada archivo WAL cerrado (16 MB cada uno) a S3 conforme son producidos. En condiciones normales, el WAL es cerrado en segundos bajo carga media.",[12,27685,27686,27688],{},[27,27687,27622],{}," 1 a 5 minutos. Es el intervalo entre el último WAL haber sido enviado y el disco haber muerto.",[12,27690,27691,27693],{},[27,27692,27628],{}," 15 a 45 minutos. Restaurar el basebackup, replay de los WALs hasta el punto deseado.",[12,27695,27696,27698],{},[27,27697,27637],{}," SaaS con 10 a 100 GB de base, primer centenar de clientes pagando. Etapa en que perder 24 horas es catastrófico pero el equipo aún no tiene DBA dedicado.",[12,27700,27701,27703,27704,27706,27707,27709,27710,27713,27714,27717],{},[27,27702,27643],{}," el ",[231,27705,27682],{}," necesita ser tratado como código de producción, no script de fin de semana. Si falla y nadie lo nota, el WAL acumula en el disco de la base hasta reventar, y cuando revienta la base para de aceptar writes. Ya he visto cluster caer a las cuatro de la mañana porque el ",[231,27708,27682],{}," llamaba ",[231,27711,27712],{},"aws s3 cp"," sin ",[231,27715,27716],{},"--no-progress"," y la salida del progreso bloqueaba el stdout en ambiente sin TTY.",[12,27719,27720],{},"El volumen de WAL sorprende. Base con tráfico medio genera 5 a 50 GB de WAL por día, dependiendo de lo que escribe. Multiplicado por retención de 30 días, se vuelve terabytes. Storage barato sigue siendo barato, pero el lifecycle policy del bucket tiene que estar afilado.",[12,27722,27723],{},"Y el restore exige replay secuencial. No puedes saltar WALs. Si un archivo intermedio se perdió (bug en archive, bucket borrado por error, cualquier cosa), el restore para en ese punto y lo que vino después es ilegible. Verificación periódica es obligatoria.",[12,27725,27726,27728],{},[27,27727,27665],{}," US$10 a US$40 al mes de storage dependiendo de retención. Tiempo humano: 2 a 4 horas para setup inicial bien hecho, más la primera media hora de cada incidente entendiendo qué WAL necesita.",[19,27730,27732],{"id":27731},"estrategia-3-pgbackrest-wal-e-restic-xtrabackup","Estrategia 3 — pgBackRest, WAL-E, restic, xtrabackup",[12,27734,27735],{},"Cuando la estrategia 2 es demasiado buena para hacerse a mano. Herramientas dedicadas que combinan basebackup, WAL archiving, retención, compresión, cifrado y — crucialmente — verificación automática.",[12,27737,27738,27741,27742,27745],{},[231,27739,27740],{},"pgBackRest"," es el nombre más maduro para Postgres. Hace todo lo que la estrategia 2 hace, pero con paralelización (varios procesos enviando WAL simultáneamente), validación de checksum en cada archivo, point-in-time recovery (PITR) sin dolor, y — la ganancia operacional grande — un comando único ",[231,27743,27744],{},"pgbackrest restore"," que sabe encontrar el backup más reciente, bajar lo que necesita, y replay hasta el instante que pides.",[12,27747,27748,27751],{},[231,27749,27750],{},"WAL-E"," es más antiguo pero más simple si solo quieres mandar a S3 y volver.",[12,27753,27754,27757],{},[231,27755,27756],{},"restic"," es genérico (no es específico de Postgres), pero tiene deduplicación que es especialmente útil cuando haces dump completo varias veces al día — el segundo dump solo envía los bloques que cambiaron.",[12,27759,27760,27763],{},[231,27761,27762],{},"xtrabackup"," es el equivalente para MySQL, con la misma filosofía: backup caliente sin lock, incremental, PITR.",[12,27765,27766,27768],{},[27,27767,27622],{}," minutos, igual estrategia 2. La diferencia es que aquí los \"5 minutos\" son más confiables porque la herramienta verifica continuamente que el pipeline esté funcionando.",[12,27770,27771,27773,27774,27777],{},[27,27772,27628],{}," 10 a 30 minutos con PITR directo. El comando ",[231,27775,27776],{},"pgbackrest restore --type=time --target='2025-12-11 03:42:00'"," resuelve lo que en la estrategia 2 exige media hora de scripts.",[12,27779,27780,27782],{},[27,27781,27637],{}," SaaS serio, base de 100 GB a 1 TB, equipo que asume responsabilidad formal por tests mensuales de restore.",[12,27784,27785,27787,27788,27790,27791,571,27794,571,27797,27800],{},[27,27786,27643],{}," aprender la herramienta. ",[231,27789,27740],{}," tiene documentación decente pero el vocabulario es específico — ",[231,27792,27793],{},"stanza",[231,27795,27796],{},"repo",[231,27798,27799],{},"archive-async",". La configuración inicial bien hecha toma 2 a 4 horas, y otro día para correr el primer full + incrementales y tener certeza de que todo cuadra.",[12,27802,27803],{},"La trampa aquí es que la herramienta esconde la complejidad del mecanismo, no la elimina. Cuando algo sale mal, necesitas entender que por debajo sigue siendo basebackup + WAL. La diferencia es que los bugs comunes de la estrategia 2 (archive fallando silenciosamente, WAL faltando) son detectados y alertados por la herramienta antes del incidente.",[12,27805,27806,27808],{},[27,27807,27665],{}," storage proporcional al volumen + tiempo de DBA part-time. Hablo en \"DBA part-time\" aunque nadie con ese título exista en el equipo — es el tiempo que alguien de guardia necesita invertir mensualmente para correr el restore-test.",[19,27810,27812],{"id":27811},"estrategia-4-streaming-replication-con-failover-automatico","Estrategia 4 — Streaming replication con failover automático",[12,27814,27815],{},"La primera estrategia en que el RTO baja por debajo de un minuto. En lugar de copiar la base después de que ella terminó de escribir, mantienes una réplica recibiendo el stream del WAL en tiempo real. Cuando el primario muere, un orquestador promueve la réplica a primario, actualiza el enrutamiento, y el servicio vuelve sin intervención humana.",[12,27817,27818],{},"Patroni es el nombre más común para orquestar eso en Postgres. Resuelve elección de líder entre nodos, gestiona replication slots, hace fencing del nodo muerto para evitar dos escrituras simultáneas, y expone un endpoint que tu balanceador de carga consulta para saber qué nodo es el primario corriente.",[12,27820,27821,27823],{},[27,27822,27622],{}," segundos. Replicación síncrona puede llegar a cero (commit en el primario solo confirma después de que la copia llegue a la réplica) pero cuesta latencia en cada write — elección que se hace transacción a transacción en la mayoría de los sistemas.",[12,27825,27826,27828],{},[27,27827,27628],{}," 30 segundos a 5 minutos. Los 30 segundos es el failover automático sin human-in-the-loop. Los 5 minutos es el escenario en que el orquestador detecta el problema, decide que no es falso positivo, promueve la réplica, y la caché de DNS de los clientes expira.",[12,27830,27831,27833],{},[27,27832,27637],{}," SaaS con primer cliente B2B serio, SLA contractual igual o mayor que 99,5%. Plataforma donde 5 minutos de ventana equivale a una pena contractual.",[12,27835,27836,27838],{},[27,27837,27643],{}," split-brain durante particionamiento de red. Si el primario queda aislado pero sigue aceptando escrituras, y la réplica es promovida por el orquestador en el otro lado de la partición, terminas con dos verdades divergentes que necesitan ser reconciliadas manualmente cuando la red vuelve. Los orquestadores serios usan un tercer nodo de testigo para evitar eso, pero la configuración es exigente.",[12,27840,27841,27842,27845],{},"Peor aún: la réplica copia corrupción. Si el primario escribió una página podrida, la réplica recibió el WAL idéntico y está igualmente podrida. Streaming replication te protege contra fallo de hardware del primario; no protege contra bug de aplicación que escribió basura, contra ",[231,27843,27844],{},"DROP TABLE"," errado, contra ransomware.",[12,27847,27848],{},"Por eso esta estrategia nunca sustituye a las tres anteriores — suma. RTO bajísimo para fallo de hardware, más backup tradicional para fallo lógico.",[12,27850,27851,27853],{},[27,27852,27665],{}," dos o tres bases corriendo todo el tiempo (un primario activo, uno o dos standbys). Storage y CPU duplicados o triplicados en relación a la base única. Tiempo humano: setup inicial de una semana, más batería de tests de failover trimestral.",[19,27855,27857],{"id":27856},"estrategia-5-backup-gestionado-por-tercero","Estrategia 5 — Backup gestionado por tercero",[12,27859,27860],{},"La estrategia en que compras el problema fuera. RDS en AWS, Cloud SQL en Google, Neon, Crunchy Bridge, o un proveedor local que entrega backup automático con PITR. Defines la ventana de retención, ellos cuidan del resto.",[12,27862,27863,27865],{},[27,27864,27622],{}," 5 minutos es el número típico publicado.",[12,27867,27868,27870],{},[27,27869,27628],{}," 30 segundos a 5 minutos para el failover dentro de la misma región. Restore cross-region es otro animal — puede ser una hora, dependiendo del proveedor.",[12,27872,27873,27875],{},[27,27874,27637],{}," equipo sin expertise interna O cumplimiento que exige vendor con SOC 2 \u002F ISO 27001 emitido. Empresa que preferiría pagar caro para no pensar en el asunto.",[12,27877,27878,27880],{},[27,27879,27643],{}," coste. Base que costaría US$60\u002Fmes en hardware se vuelve US$300 a US$600\u002Fmes en RDS equivalente, dependiendo de la configuración de réplica. Lock-in de proveedor — salir de RDS es una migración complicada porque la forma de hacer backup es específica del producto. Y el restore cross-region (que es la parte que el cliente B2B exige en el contrato) frecuentemente es más difícil de lo que parece en los slides comerciales.",[12,27882,27883],{},"La ventaja real es zero ops en condiciones normales. La desventaja real es que cuando estás en incidente, el camino para escalar con el soporte del proveedor puede tomar más tiempo del que tendrías para resolver con auto-hospedado bien configurado.",[12,27885,27886,27888],{},[27,27887,27665],{}," US$50 a US$500 al mes para bases pequeñas y medianas. Por encima de eso es cobro proporcional al tamaño.",[19,27890,17389],{"id":17388},[12,27892,27893],{},"La versión honesta lado a lado. Cada columna es una de las estrategias arriba.",[119,27895,27896,27917],{},[122,27897,27898],{},[125,27899,27900,27902,27905,27908,27911,27914],{},[128,27901,2983],{},[128,27903,27904],{},"1: Cron + pg_dump",[128,27906,27907],{},"2: basebackup + WAL",[128,27909,27910],{},"3: pgBackRest",[128,27912,27913],{},"4: Streaming + failover",[128,27915,27916],{},"5: Gestionado",[141,27918,27919,27936,27955,27973,27990,28006,28023,28041,28059,28077],{},[125,27920,27921,27924,27926,27928,27931,27934],{},[146,27922,27923],{},"RPO típico",[146,27925,12000],{},[146,27927,3020],{},[146,27929,27930],{},"1-5 min",[146,27932,27933],{},"segundos",[146,27935,3020],{},[125,27937,27938,27941,27944,27947,27950,27953],{},[146,27939,27940],{},"RTO típico",[146,27942,27943],{},"30-60 min",[146,27945,27946],{},"15-45 min",[146,27948,27949],{},"10-30 min",[146,27951,27952],{},"30s-5 min",[146,27954,27952],{},[125,27956,27957,27960,27962,27965,27968,27971],{},[146,27958,27959],{},"Tamaño ideal de base",[146,27961,17625],{},[146,27963,27964],{},"10-100 GB",[146,27966,27967],{},"100 GB - 1 TB",[146,27969,27970],{},"cualquiera",[146,27972,27970],{},[125,27974,27975,27978,27981,27983,27985,27988],{},[146,27976,27977],{},"Coste de storage",[146,27979,27980],{},"bajísimo",[146,27982,17526],{},[146,27984,17526],{},[146,27986,27987],{},"alto (réplica)",[146,27989,17521],{},[125,27991,27992,27995,27998,28000,28002,28004],{},[146,27993,27994],{},"Coste de tiempo humano",[146,27996,27997],{},"~cero",[146,27999,17526],{},[146,28001,17526],{},[146,28003,17521],{},[146,28005,27997],{},[125,28007,28008,28010,28013,28016,28018,28021],{},[146,28009,4880],{},[146,28011,28012],{},"trivial",[146,28014,28015],{},"moderada",[146,28017,28015],{},[146,28019,28020],{},"alta",[146,28022,28012],{},[125,28024,28025,28028,28031,28033,28036,28039],{},[146,28026,28027],{},"Complejidad de restore",[146,28029,28030],{},"baja",[146,28032,28015],{},[146,28034,28035],{},"baja (PITR)",[146,28037,28038],{},"n\u002Fa (failover)",[146,28040,28030],{},[125,28042,28043,28045,28048,28050,28053,28056],{},[146,28044,7104],{},[146,28046,28047],{},"manual",[146,28049,28047],{},[146,28051,28052],{},"nativo",[146,28054,28055],{},"requiere config",[146,28057,28058],{},"depende del proveedor",[125,28060,28061,28064,28066,28069,28072,28075],{},[146,28062,28063],{},"Point-in-time recovery",[146,28065,100],{},[146,28067,28068],{},"sí, manual",[146,28070,28071],{},"sí, comando único",[146,28073,28074],{},"n\u002Fa",[146,28076,17447],{},[125,28078,28079,28082,28085,28087,28090,28093],{},[146,28080,28081],{},"Franja de SaaS",[146,28083,28084],{},"MVP",[146,28086,17631],{},[146,28088,28089],{},"early\u002Fmid",[146,28091,28092],{},"startup con SLA",[146,28094,28095],{},"enterprise \u002F sin expertise",[12,28097,28098],{},"Repara que ninguna línea tiene un ganador absoluto. La estrategia 5 gana en \"tiempo humano\" y pierde en \"coste de storage\". La estrategia 4 gana en RPO y pierde en \"complejidad de setup\". La elección es siempre sobre qué columna priorizas, dado el etapa de la empresa.",[19,28100,28102],{"id":28101},"los-cinco-errores-que-matan-el-backup-del-colega","Los cinco errores que matan el backup del colega",[12,28104,28105],{},"A partir de aquí es folclore operacional. Cada uno de esos errores fue cometido por un equipo que tenía confianza en el backup que tenía. Cada uno se volvió post-mortem.",[12,28107,28108,28111],{},[27,28109,28110],{},"Nunca restauró."," Backup que nunca fue restaurado en ambiente aislado es hipótesis. Cron mensual que toma el backup más reciente del bucket, lo sube en una base efímera (una máquina temporal que apagas en seguida), valida conteo de filas de las tablas críticas, comprueba checksum de algunas muestras, y manda email al equipo confirmando éxito. El backup del mes en que ese cron falló es el único backup del que tienes certeza de que va a funcionar. Todo antes es fe.",[12,28113,28114,28117],{},[27,28115,28116],{},"Backup en el mismo disco o misma región."," Disco muere, backup va junto. Región entera de proveedor cloud cae (ya ocurrió varias veces en los últimos cinco años), backup va junto. Cross-region es el mínimo. Cross-provider — backup principal en un proveedor, copia secundaria en otro — es lo que separa \"preparado\" de \"hincha\".",[12,28119,28120,28123],{},[27,28121,28122],{},"Sin retención lógica larga."," Siete días de retención parece cómodo hasta que descubres que la corrupción empezó hace ocho días y nadie lo notó. Bug sutil de aplicación que escribe dato inválido en una fila por minuto no dispara alerta, pero en dos semanas envenenó medio millón de registros. Retención corta es negligencia disfrazada de ahorro. Política mínima razonable: 7 días de backup horario, 30 días de diario, 12 meses de mensual.",[12,28125,28126,28129],{},[27,28127,28128],{},"Sin alerta de fallo."," El cron silencioso es el asesino más común. Falló hace treinta días por un cambio de credencial en S3, nadie miró el log, todo el mundo durmió tranquilo. Alerta integrada al sistema de notificación del equipo (no email perdido en la bandeja, sino Slack o equivalente que alguien va a leer) es obligatorio. Y la alerta tiene que ser doble — alerta cuando falla, y alerta cuando no hay éxito hace más de N horas (para detectar el caso en que el cron ni corrió).",[12,28131,28132,28135],{},[27,28133,28134],{},"Backup sin cifrado."," Filtración de bucket S3 público se vuelve filtración de la base entera. Los incidentes de prensa de los últimos años están todos compuestos por \"bucket quedó público por dos días y tenía el backup completo\". Cifrado en reposo (server-side encryption en el bucket es el mínimo, cifrado cliente-side con clave gestionada por ti es lo adecuado), cifrado en tránsito, y — separado de eso — control de acceso al bucket que sigue el principio del menor privilegio.",[19,28137,28139],{"id":28138},"la-trayectoria-de-madurez","La trayectoria de madurez",[12,28141,28142],{},"La pregunta práctica: qué estrategia para qué etapa. Tomando como referencia métricas de ingresos mensuales recurrentes.",[12,28144,28145,28148,28149,28151],{},[27,28146,28147],{},"MVP hasta US$1k de MRR."," Estrategia 1. Cron de ",[231,28150,5736],{}," a S3-compatible, retención de 30 días, alerta básica de fallo. Cuesta prácticamente nada y protege contra el riesgo principal en esa fase, que es \"el servidor desapareció\". RPO de 24 horas es aceptable porque el cliente en esa fase tiene expectativa de producto que está empezando.",[12,28153,28154,28157],{},[27,28155,28156],{},"Indie de US$1k a US$6k."," Estrategia 2. Añade WAL archiving, derriba RPO de 24 horas a 5 minutos. El salto de complejidad es compensado por el salto de garantía. Cliente que paga US$100 al mes de suscripción B2B empieza a hacer pregunta de SLA — necesitas respuesta mejor que \"diario\".",[12,28159,28160,28163],{},[27,28161,28162],{},"Startup early de US$6k a US$40k."," Estrategia 3. pgBackRest configurado con restore-test mensual automático. Aquí ya no es opcional — tienes cliente serio, contrato serio, y la fragilidad de la estrategia 2 hecha a mano es riesgo operacional concreto. El setup de medio día se paga en tres meses por el primer incidente que no se vuelve post-mortem público.",[12,28165,28166,28169],{},[27,28167,28168],{},"Startup con SLA contractual."," Estrategia 4 sumada a la 3. Streaming replication con failover automático cuida del hardware; pgBackRest cuida del dato lógico. Las dos juntas resuelven los dos modos de fallo que los contratos B2B serios cobran: indisponibilidad momentánea y pérdida de dato.",[12,28171,28172,28175],{},[27,28173,28174],{},"Enterprise o cumplimiento pesado."," Estrategia 5 O estrategia 4 con auditoría detallada. Aquí la decisión es menos técnica y más regulatoria. Si la auditoría exige proveedor con certificación X, compras gestionado. Si la auditoría acepta auto-hospedado con runbook documentado, operas las estrategias 3 y 4 e inviertes en la trayectoria de auditoría.",[19,28177,28179],{"id":28178},"como-heroctl-simplifica-eso","Cómo HeroCtl simplifica eso",[12,28181,28182],{},"La motivación del producto es justamente ese esquema arriba — son capas que aparecen repetidamente en todo SaaS, y cada equipo gasta una temporada entera reconstruyendo la misma cañería. HeroCtl resuelve el transporte, la orquestación y la observación de esas capas. Mantiene lo que es específico de la base con el equipo, automatiza lo que es genérico.",[12,28184,28185],{},"Concretamente, en el plan Community (gratuito), corres Postgres como job común en el cluster, con persistencia cifrada en reposo. El cron de backup se vuelve otro job, con retry automático, alerta integrada de fallo (sin necesidad de montar Alertmanager por fuera), y métricas que aparecen en el panel — duración del dump, tamaño del archivo, tiempo desde el último éxito.",[12,28187,28188],{},"En el Business, entra backup gestionado de Postgres y MySQL. La diferencia con \"hacerlo tú mismo\" es que la verificación de integridad, el restore-test mensual, el cifrado cliente-side con clave gestionada por ti, y la política de retención en tres tiers (horario\u002Fdiario\u002Fmensual) ya vienen configuradas. Defines la ventana y el resto es problema nuestro.",[12,28190,28191],{},"En el Enterprise, entra orquestación de streaming replication entre nodos del cluster — un job describe la topología (primario aquí, standby allá, quién promueve quién), y el cluster cuida del failover cuando el primario muere. Batería de tests de chaos corre contra tu cluster mensualmente, con informe.",[12,28193,28194],{},"En todos los planes, el restore-test puede ser configurado como cron job interno: el cluster sube una base efímera, restaura el backup más reciente, valida lo que definas como \"saludable\" (una query de checksum, una conteo de filas, lo que tenga sentido), reporta éxito o fallo, y apaga la base efímera. El coste son los minutos de CPU del test, no día de trabajo de ingeniero.",[12,28196,28197],{},"La filosofía es la misma del resto del producto: lo que es genérico para todo SaaS ya está listo; lo que es específico de tu dominio se queda contigo. Backup es genérico. El contenido de la base es tuyo.",[19,28199,3226],{"id":3225},[12,28201,28202,28207,28208,28210],{},[27,28203,19046,28204,28206],{},[231,28205,5736],{}," basta para empezar?","\nSí, para MVP hasta primeros clientes pagando. La regla práctica: si perder 24 horas de datos cuesta menos que tres horas de tiempo de ingeniero, ",[231,28209,5736],{}," es la elección correcta. Cuando se invierta (perder dato cuesta más que migrar a la estrategia 2), migra.",[12,28212,28213,28216],{},[27,28214,28215],{},"¿Cuánto cuesta storage S3-compatible en 2026?","\nFranja actual entre US$0,03 y US$0,08 por GB-mes dependiendo del proveedor y del tier. Backup de base de 50 GB con retención de 30 días más algunos dumps semanales antiguos = ~3 TB-mes equivalente comprimido = US$10 a US$25\u002Fmes. Cross-region prácticamente dobla. Tier frío para retención mensual larga derriba a la mitad.",[12,28218,28219,28222],{},[27,28220,28221],{},"¿Cómo pruebo restore sin afectar producción?","\nCron job en el cluster que: 1) baja el backup más reciente del bucket; 2) sube un Postgres temporal en otro nodo (o contenedor efímero) sin exponer puerto público; 3) restaura el dump; 4) corre queries de validación (conteo por tabla, checksum de muestras, query crítica del dominio); 5) compara con baselines esperados; 6) reporta resultado en el canal de alertas; 7) destruye el ambiente. Corre mensual, como mínimo. Nunca toca la base de producción en momento ninguno.",[12,28224,28225,28228,28229,28232,28233,28236],{},[27,28226,28227],{},"Backup cifrado en S3 — ¿cuál es la forma correcta?","\nTres capas. Server-side encryption del bucket (",[231,28230,28231],{},"AES256"," o KMS) es la base y es gratis. Cifrado cliente-side con clave gestionada por ti (cifras el archivo antes de subir, con clave que vive fuera del proveedor cloud) protege contra escenario de comprometimiento de credencial. Política de bucket con ",[231,28234,28235],{},"aws:SecureTransport=true"," y bloqueo de acceso público explícito. Las tres juntas, sin excepción. Una sola no basta.",[12,28238,28239,28242,28243,28245],{},[27,28240,28241],{},"¿Read replica cuenta como backup?","\nNo. Read replica protege contra fallo de hardware del primario. No protege contra ",[231,28244,27844],{}," errado, contra bug que escribe dato inválido, contra corrupción lógica que se replica. Toda corrupción lógica que entra en el primario entra en la réplica en segundos. Read replica es alta disponibilidad, no backup. Las dos cosas coexisten; ninguna sustituye a la otra.",[12,28247,28248,28251],{},[27,28249,28250],{},"¿Cross-region replication es necesario?","\nPara cliente B2B serio, sí. Para MVP, no. La frontera práctica: si un único proveedor cloud cayendo por 4 horas es suficiente para que rompas contrato, cross-region es mínimo. Si 4 horas fuera aún se pueden explicar por email, cross-region puede esperar.",[12,28253,28254,28257,28258,28261],{},[27,28255,28256],{},"¿Cuánto tiempo tarda restaurar 100 GB de Postgres?","\nDepende mucho del disco. SSD NVMe local: 20 a 40 minutos contando creación de índices. SSD remoto (volumen de proveedor cloud): 40 a 90 minutos. HDD: no quieres saber. Compresión del dump típicamente derriba a la mitad del tamaño original; base de 100 GB se vuelve dump de 30 a 50 GB. Crea índices en paralelo (",[231,28259,28260],{},"pg_restore -j",") para acelerar 30 a 50%.",[19,28263,3310],{"id":3309},[12,28265,28266],{},"Backup es menos sobre estrategia técnica y más sobre disciplina de test. Las cinco estrategias arriba son todas decentes en alguna etapa. La diferencia entre el equipo que sobrevive al incidente y el equipo que pierde cliente no está en cuál de ellas escogió — está en haber restaurado un backup recientemente lo suficiente para confiar.",[12,28268,28269],{},"Si tu respuesta a \"¿cuándo fue el último restore-test?\" empieza con \"déjame ver\", tienes trabajo para esta semana. No es la próxima sprint. Es esta semana. El escenario de las tres de la mañana no está agendado.",[12,28271,28272],{},"HeroCtl corre en cualquier servidor Linux con Docker. Instalas en un laboratorio, subes un Postgres como job, configuras backup automático, agendas restore-test mensual, y en una tarde tienes el esquema de la estrategia 3 entero funcionando. Sin montar cinco productos diferentes, sin aprender vocabulario de orquestador especializado.",[224,28274,28276],{"className":28275,"code":5318,"language":1531,"meta":229,"style":229},"language-sh shiki shiki-themes github-dark-default",[231,28277,28278],{"__ignoreMap":229},[234,28279,28280,28282,28284,28286,28288],{"class":236,"line":237},[234,28281,1220],{"class":247},[234,28283,2958],{"class":251},[234,28285,5329],{"class":255},[234,28287,2964],{"class":383},[234,28289,2967],{"class":247},[12,28291,28292,28293,28295,28296,101],{},"Para contexto sobre cuándo tiene sentido correr Postgres en el propio cluster vs. comprar gestionado, lee ",[3337,28294,7467],{"href":7466},". Para entender por qué la ventana de deploy es el otro lado de la moneda del backup (porque el deploy malo es la forma más común de generar el incidente que va a exigir restore), lee ",[3337,28297,28298],{"href":3339},"Rolling deploy seguro: por qué el tuyo puede no serlo",[12,28300,28301],{},"Backup que nunca fue restaurado es placebo. La diferencia entre placebo y remedio aparece exactamente una vez, exactamente cuando no puedes elegir.",[3351,28303,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":28305},[28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318],{"id":27562,"depth":244,"text":27563},{"id":27578,"depth":244,"text":27579},{"id":27609,"depth":244,"text":27610},{"id":27669,"depth":244,"text":27670},{"id":27731,"depth":244,"text":27732},{"id":27811,"depth":244,"text":27812},{"id":27856,"depth":244,"text":27857},{"id":17388,"depth":244,"text":17389},{"id":28101,"depth":244,"text":28102},{"id":28138,"depth":244,"text":28139},{"id":28178,"depth":244,"text":28179},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"2025-12-11","Backup que nunca fue restaurado es placebo. Cinco estrategias con tiempo de recuperación real (RTO) y pérdida de datos aceptable (RPO) honesto, para cada etapa de SaaS.",{},{"title":27538,"description":28320},{"loc":11730},"es\u002Fblog\u002Fbackup-de-base-de-datos-en-cluster",[28326,13022,28327,3379,28328],"backup","disaster-recovery","rpo-rto","Ev2EyYOvg_IObmOzE8sis1fiVzkdtDuMN00d4g4Ye4o",{"id":28331,"title":28298,"author":7,"body":28332,"category":3379,"cover":3380,"date":29018,"description":29019,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":29020,"navigation":411,"path":3339,"readingTime":4402,"seo":29021,"sitemap":29022,"stem":29023,"tags":29024,"__hash__":29027},"blog_es\u002Fes\u002Fblog\u002Frolling-deploy-seguro-por-que-el-tuyo-puede-no-serlo.md",{"type":9,"value":28333,"toc":29003},[28334,28337,28340,28343,28347,28357,28360,28373,28378,28381,28385,28388,28395,28398,28401,28405,28412,28415,28418,28422,28428,28435,28441,28444,28452,28455,28464,28467,28474,28478,28481,28484,28494,28497,28501,28504,28688,28694,28698,28701,28736,28756,28777,28795,28801,28807,28817,28821,28824,28829,28834,28840,28846,28850,28853,28859,28865,28882,28888,28890,28896,28912,28922,28932,28938,28944,28956,28958,28961,28964,28967,28969,28985,28997,29000],[12,28335,28336],{},"Todo equipo de ingeniería que opera contenedor en producción, antes o después, escribe una frase parecida en el canal de status: \"deploy concluido, sin downtime\". La frase es optimista. En al menos la mitad de los casos que ya hemos auditado — en scripts caseros, en paneles self-hosted populares, en tutoriales oficiales que se volvieron referencia —, lo que pasó de hecho fue una ventana de 5 a 30 segundos en que el balanceador de carga retornó 502, algunos uploads cortaron por la mitad, y nadie se dio cuenta porque el monitoreo muestrea cada minuto.",[12,28338,28339],{},"Rolling deploy parece el problema más simple de orquestación: tienes N contenedores corriendo una versión antigua, quieres tener N contenedores corriendo una versión nueva, y quieres que la app siga respondiendo durante el cambio. La receta conceptual cabe en tres líneas. Sustituir un contenedor viejo por uno nuevo, uno por uno, manteniendo el tráfico siempre dirigido hacia quien está vivo. Lo que vuelve eso difícil no es la estrategia — es el conjunto de seis detalles que necesitan estar correctos al mismo tiempo. Cada uno solo parece detalle de implementación. Los seis juntos son la diferencia entre \"deploy sin downtime de verdad\" y \"deploy que parece sin downtime el viernes por la mañana, pero tiene treinta segundos de error en medio del día a las 17h\".",[12,28341,28342],{},"Este post mapea los seis. Al final tiene una receta en formato de spec, una comparación honesta de quién implementa qué, y una sección de tests que puedes correr en tu sistema actual para descubrir si está mal — antes de que tu cliente lo descubra primero.",[19,28344,28346],{"id":28345},"detalle-1-health-check-antes-de-promover-el-nuevo-contenedor","Detalle 1 — Health check antes de promover el nuevo contenedor",[12,28348,28349,28350,28353,28354,28356],{},"El error más común en rolling deploy casero es confiar en el estado ",[231,28351,28352],{},"running"," que el runtime de contenedor reporta. Subes un contenedor nuevo, Docker (o equivalente) lo marca como ",[231,28355,28352],{}," en milisegundos, y tu script considera eso prueba de que puede matar al viejo. Mata al viejo. El nuevo, internamente, aún está iniciando — esperando conexión con base, cargando cache en memoria, bajando configuración de feature flag, abriendo pool de threads. Durante ese intervalo, el balanceador rutea tráfico a un proceso que aún no está listo para recibir y devuelve 502 o 503.",[12,28358,28359],{},"La ventana es corta — generalmente entre 5 y 30 segundos por contenedor —, y por eso engaña al monitoreo. Si tu métrica de error es muestreada cada minuto y cambias cinco contenedores en secuencia, cada uno con 10 segundos de \"está running pero no está listo\", el pico no siempre cae exactamente sobre una ventana de colecta. Quedas con la impresión estadística de que todo salió bien.",[12,28361,28362,28363,571,28365,28368,28369,28372],{},"Lo que rolling debe hacer, en lugar de eso, es separar dos conceptos: \"el proceso está corriendo\" y \"el proceso está listo para servir tráfico\". Corriendo es estado de runtime; listo es respuesta afirmativa de un endpoint que la propia app expone — ",[231,28364,355],{},[231,28366,28367],{},"\u002Freadyz",", o equivalente. El orquestador hace HTTP GET en ese endpoint del contenedor nuevo, espera recibir 200, espera esa respuesta sustentada por un período (",[231,28370,28371],{},"min_healthy_time",", típicamente 10 segundos), y solo entonces remueve el contenedor viejo del balanceador.",[12,28374,9008,28375,28377],{},[231,28376,28371],{}," es el detalle que mucha gente salta. Existe porque un único 200 no significa nada — puede ser que la app respondió antes de cerrar una conexión crítica, y va a empezar a fallar al segundo siguiente. Esperar 10 segundos consecutivos de respuestas saludables filtra esos falsos positivos sin alargar el deploy de forma absurda.",[12,28379,28380],{},"El Watchtower clásico — script popular para actualizar contenedores a partir de nuevas tags de imagen — no hace nada de eso. Hace pull, para el viejo, sube el nuevo. Coolify y Dokploy implementan parcialmente, dependiendo de la configuración de la aplicación y del tipo de health check que activaste. Un orquestador de cluster serio trata eso como requisito mínimo.",[19,28382,28384],{"id":28383},"detalle-2-connection-draining-y-graceful-shutdown","Detalle 2 — Connection draining y graceful shutdown",[12,28386,28387],{},"Incluso cuando ordenas al router que pare de mandar conexiones nuevas al contenedor viejo, aún existen conexiones en curso — uploads de archivo, downloads grandes, requests largos que aguardan respuesta de base, websocket abierto, streaming de evento. Si simplemente envías SIGKILL (o dejas al runtime mandar, después de un timeout demasiado corto), todas esas conexiones cortan por la mitad. El usuario ve error de red en el momento exacto del deploy.",[12,28389,28390,28391,28394],{},"El flujo correcto tiene cuatro pasos ordenados. Primero, señalizas al router que el contenedor viejo no debe más recibir conexiones nuevas — eso generalmente es una remoción del balanceador o un ",[231,28392,28393],{},"drain"," del nodo. Segundo, envías SIGTERM al proceso. SIGTERM es una señal capturable; la app puede tratar e iniciar shutdown gracioso. Tercero, esperas. El timeout depende del perfil de la aplicación — 30 a 60 segundos cubre la vasta mayoría de los web apps; APIs con upload de archivo grande pueden necesitar 120 o más. Cuarto, y solo después de ese timeout, mandas SIGKILL a lo que aún no terminó.",[12,28396,28397],{},"Existe una trampa conocida en ese paso: la app necesita, ella misma, lidiar con SIGTERM. Node, Rails, Django, Go HTTP server — todos tienen middleware o helpers para eso, pero ninguno de ellos viene activado por defecto en template básico. Si tu aplicación no captura SIGTERM, la señal se vuelve no-op y el orquestador va a esperar el timeout completo antes de matar con SIGKILL. El resultado es deploy lento y, aún así, conexiones cortadas — porque la app solo se dio cuenta de que iba a morir en el instante del KILL.",[12,28399,28400],{},"Verifica tu app. Específicamente: cuando recibe SIGTERM, ¿deja de aceptar conexiones nuevas, espera las conexiones en curso terminar, y solo entonces cierra? Si la respuesta es \"no sé\", tu rolling deploy está roto en ese detalle.",[19,28402,28404],{"id":28403},"detalle-3-imagen-anterior-pre-puxada-para-rollback-rapido","Detalle 3 — Imagen anterior pre-puxada para rollback rápido",[12,28406,28407,28408,28411],{},"Bug crítico en producción, tres minutos después del deploy. Necesitas volver a la versión anterior ahora. El comando ",[231,28409,28410],{},"pull"," de la imagen antigua toma 30 a 60 segundos por nodo — porque, claro, \"limpiaste\" la vieja para ahorrar disco, o el cache de imagen del nodo ya fue rotacionado. Multiplica por número de réplicas, suma el tiempo de orquestación del propio cambio, y tu incidente de cinco minutos se volvió quince. Quince minutos es la diferencia entre \"inestabilidad momentánea\" en el postmortem e \"incidente reportado al cliente\".",[12,28413,28414],{},"La corrección es trivial y casi nadie la implementa: mantener la imagen N-1 pre-puxada en los nodos que la corrían. Rollback se vuelve cambiar la tag pointed-to y reiniciar — operación de aproximadamente 10 segundos por contenedor, dominada por el health check del contenedor antiguo volviendo a la vida.",[12,28416,28417],{},"La versión más sofisticada es mantener snapshot del estado completo del job — no solo imagen, sino variables de entorno, configuraciones de red, secretos asociados, recursos asignados. Rollback parcial (solo imagen) cubre la mayoría de los casos, pero no cubre regresión introducida en una feature flag o en una string de conexión. Snapshot total es lo que separa rollback rápido de rollback completo.",[19,28419,28421],{"id":28420},"detalle-4-deteccion-automatica-de-fallo-y-auto-revert","Detalle 4 — Detección automática de fallo y auto-revert",[12,28423,28424,28425,28427],{},"Escenario común en script casero: el deploy sube, el contenedor nuevo entra en crash-loop (vuelve a ",[231,28426,28352],{},", muere en 5 segundos, vuelve de nuevo, muere de nuevo). El sistema queda esperando que alguien vea el problema y aborte manualmente. Si eso pasa a las cuatro de la mañana y la alerta va a un Slack que nadie está mirando, el downtime se prolonga hasta que alguien despierte.",[12,28429,28430,28431,28434],{},"Lo que rolling debe hacer es definir un ",[231,28432,28433],{},"healthy_deadline"," — un techo absoluto de tiempo dentro del cual el contenedor nuevo necesita entrar y permanecer en estado saludable. Nuestro default es 300 segundos; cinco minutos cubre apps que tardan en inicializar (apps Java pesadas, apps con warm-up de cache) sin dar margen indefinido. Si pasó el deadline y el contenedor no está saludable, el orquestador revierte automáticamente a la versión anterior. Alerta al equipo después, sin urgencia — porque el sistema ya se protegió solo.",[12,28436,28437,28438,28440],{},"La implementación práctica cuenta dos señales combinadas: cuenta de restarts en el contenedor nuevo (si pasó de 3 en 60 segundos, es crash-loop) y tiempo total transcurrido sin health check positivo sostenido. Cualquiera de los dos disparándose antes de que el ",[231,28439,28371],{}," sea alcanzado aborta el deploy de aquella réplica y dispara el revert.",[12,28442,28443],{},"Un detalle sutil: auto-revert solo tiene sentido si el detalle 3 (imagen anterior pre-puxada) está implementado. Revertir a una imagen que necesita ser bajada de nuevo durante el auto-revert anula la ganancia.",[19,28445,28447,28448,28451],{"id":28446},"detalle-5-max_parallel-1-en-cluster-multi-instance","Detalle 5 — ",[231,28449,28450],{},"max_parallel: 1"," en cluster multi-instance",[12,28453,28454],{},"Tienes cinco réplicas del mismo servicio. Tentado de cambiar todas las cinco al mismo tiempo: deploy paralelo, espera todas quedar saludables, listo. Ese camino tiene tres problemas. Primero, durante la ventana en que todas están siendo cambiadas, todo el tráfico pasa por la versión nueva — si tiene bug, 100% de los usuarios sienten, sin fallback. Segundo, el pico de uso de recursos durante el cambio es 2× (porque viejas y nuevas coexisten por instantes), lo que puede reventar memoria del nodo y generar OOM en cascada. Tercero, pierdes la oportunidad barata de detectar regresión antes de propagar.",[12,28456,28457,28458,28460,28461,28463],{},"Rolling debe cambiar una réplica por vez (",[231,28459,28450],{},") — o, en clusters muy grandes, una fracción pequeña (10-25%). Cambia la primera, espera quedar saludable, espera el ",[231,28462,28371],{},", cambia la segunda, y así sucesivamente. La capacidad total del servicio queda mantenida durante toda la ventana de deploy: si cinco réplicas aguantaban el tráfico antes, cuatro nuevas + una vieja (o vice-versa) también aguantan.",[12,28465,28466],{},"El tradeoff es tiempo. Diez réplicas con 30 segundos cada una de cambio + min_healthy_time = cinco minutos de ventana total de deploy. No es rápido. A cambio, ganas rollback barato: si la primera réplica nueva falla, el orquestador para de cambiar las otras. Quedas con nueve viejas + una nueva fracasada, descartas la fracasada, volviste al estado anterior sin ningún impacto en capacidad. El coste de deploy lento es pagado por la seguridad de no tener cluster entero con bug corriendo antes de que alguien perciba.",[12,28468,28469,28470,28473],{},"Existe un knob extra que ayuda: ",[231,28471,28472],{},"stagger",", el intervalo entre cambios consecutivos. Default razonable es 30 segundos. Ese atraso permite que métricas y logs del contenedor recién cambiado sean colectados y evaluados antes de partir hacia el próximo — ventana mínima para detectar bug que solo aparece bajo tráfico real.",[19,28475,28477],{"id":28476},"detalle-6-pre-stop-hooks-para-long-running-jobs","Detalle 6 — Pre-stop hooks para long-running jobs",[12,28479,28480],{},"Ese detalle afecta específicamente a apps que tienen worker asíncrono — Sidekiq, Celery, Resque, RQ, BullMQ, cualquier cola de job en background. El contenedor del worker tomó un job que tarda 30 minutos en procesar (envío de e-mail en lote, generación de reporte, procesamiento de pago). En medio del procesamiento, viene el SIGTERM del deploy. Si el worker no tiene tratamiento adecuado, el job se pierde — queda en estado intermedio, o vuelve a la cola y es procesado en duplicado, o simplemente desaparece.",[12,28482,28483],{},"El flujo correcto es más elaborado que el del detalle 2. Antes mismo del SIGTERM, el orquestador necesita ejecutar un pre-stop hook que señalice al worker para entrar en modo de drenaje: parar de aceptar jobs nuevos, pero terminar los que ya tomó. El orquestador entonces espera (con timeout configurable — 60 a 300 segundos es rango normal) por la cola local drenar. Solo después manda SIGTERM al proceso.",[12,28485,28486,28487,5839,28490,28493],{},"La implementación varía. Apps más sofisticadas exponen un endpoint ",[231,28488,28489],{},"\u002Fpause",[231,28491,28492],{},"\u002Fdrain"," que coloca al worker en modo gracioso. Apps más simples usan un archivo de centinela — pre-stop crea un archivo, worker chequea el archivo a cada loop y para de tomar job nuevo si existe. En ambos casos, la clave es que el orquestador necesita esperar la confirmación de que la cola local drenó antes de mandar SIGTERM.",[12,28495,28496],{},"Sin eso, tu tasa de fallo de jobs asíncronos durante deploy es directamente proporcional al tiempo medio de procesamiento de job × número de workers cambiados. En apps que procesan pago o envío de e-mail, esa tasa de fallo se vuelve problema serio rápido.",[19,28498,28500],{"id":28499},"la-receta-completa","La receta completa",[12,28502,28503],{},"Los seis detalles se componen en una especificación reconocible. En formato spec:",[224,28505,28507],{"className":9015,"code":28506,"language":9017,"meta":229,"style":229},"update:\n  max_parallel: 1\n  min_healthy_time: 10    # 10s sostenidos saludable\n  healthy_deadline: 300   # 5 min máx para quedar saludable\n  auto_revert: true       # si pasa deadline, revierte\n  stagger: 30             # 30s entre réplicas cambiadas\ntasks:\n  - name: web\n    healthcheck:\n      path: \u002Fhealthz\n      interval: 5s\n      timeout: 2s\n      retries: 3\n    lifecycle:\n      pre_stop:\n        timeout: 60         # 60s para worker drenar\n        command: [\"\u002Fbin\u002Fsh\", \"-c\", \"kill -TERM 1; sleep 30\"]\n",[231,28508,28509,28516,28525,28537,28549,28562,28574,28581,28592,28599,28609,28619,28629,28639,28646,28653,28666],{"__ignoreMap":229},[234,28510,28511,28514],{"class":236,"line":237},[234,28512,28513],{"class":9024},"update",[234,28515,9028],{"class":387},[234,28517,28518,28521,28523],{"class":236,"line":244},[234,28519,28520],{"class":9024},"  max_parallel",[234,28522,6562],{"class":387},[234,28524,10048],{"class":251},[234,28526,28527,28530,28532,28534],{"class":236,"line":271},[234,28528,28529],{"class":9024},"  min_healthy_time",[234,28531,6562],{"class":387},[234,28533,1589],{"class":251},[234,28535,28536],{"class":240},"    # 10s sostenidos saludable\n",[234,28538,28539,28542,28544,28546],{"class":236,"line":415},[234,28540,28541],{"class":9024},"  healthy_deadline",[234,28543,6562],{"class":387},[234,28545,1576],{"class":251},[234,28547,28548],{"class":240},"   # 5 min máx para quedar saludable\n",[234,28550,28551,28554,28556,28559],{"class":236,"line":434},[234,28552,28553],{"class":9024},"  auto_revert",[234,28555,6562],{"class":387},[234,28557,28558],{"class":251},"true",[234,28560,28561],{"class":240},"       # si pasa deadline, revierte\n",[234,28563,28564,28567,28569,28571],{"class":236,"line":459},[234,28565,28566],{"class":9024},"  stagger",[234,28568,6562],{"class":387},[234,28570,5544],{"class":251},[234,28572,28573],{"class":240},"             # 30s entre réplicas cambiadas\n",[234,28575,28576,28579],{"class":236,"line":464},[234,28577,28578],{"class":9024},"tasks",[234,28580,9028],{"class":387},[234,28582,28583,28585,28587,28589],{"class":236,"line":479},[234,28584,9550],{"class":387},[234,28586,10463],{"class":9024},[234,28588,6562],{"class":387},[234,28590,28591],{"class":255},"web\n",[234,28593,28594,28597],{"class":236,"line":484},[234,28595,28596],{"class":9024},"    healthcheck",[234,28598,9028],{"class":387},[234,28600,28601,28604,28606],{"class":236,"line":490},[234,28602,28603],{"class":9024},"      path",[234,28605,6562],{"class":387},[234,28607,28608],{"class":255},"\u002Fhealthz\n",[234,28610,28611,28614,28616],{"class":236,"line":508},[234,28612,28613],{"class":9024},"      interval",[234,28615,6562],{"class":387},[234,28617,28618],{"class":255},"5s\n",[234,28620,28621,28624,28626],{"class":236,"line":529},[234,28622,28623],{"class":9024},"      timeout",[234,28625,6562],{"class":387},[234,28627,28628],{"class":255},"2s\n",[234,28630,28631,28634,28636],{"class":236,"line":535},[234,28632,28633],{"class":9024},"      retries",[234,28635,6562],{"class":387},[234,28637,28638],{"class":251},"3\n",[234,28640,28641,28644],{"class":236,"line":546},[234,28642,28643],{"class":9024},"    lifecycle",[234,28645,9028],{"class":387},[234,28647,28648,28651],{"class":236,"line":552},[234,28649,28650],{"class":9024},"      pre_stop",[234,28652,9028],{"class":387},[234,28654,28655,28658,28660,28663],{"class":236,"line":557},[234,28656,28657],{"class":9024},"        timeout",[234,28659,6562],{"class":387},[234,28661,28662],{"class":251},"60",[234,28664,28665],{"class":240},"         # 60s para worker drenar\n",[234,28667,28668,28671,28673,28676,28678,28681,28683,28686],{"class":236,"line":594},[234,28669,28670],{"class":9024},"        command",[234,28672,9528],{"class":387},[234,28674,28675],{"class":255},"\"\u002Fbin\u002Fsh\"",[234,28677,571],{"class":387},[234,28679,28680],{"class":255},"\"-c\"",[234,28682,571],{"class":387},[234,28684,28685],{"class":255},"\"kill -TERM 1; sleep 30\"",[234,28687,9534],{"class":387},[12,28689,28690,28691,28693],{},"Esa configuración — en texto, en archivo de configuración de orquestador, o implícita en código de deploy — es el mínimo viable de rolling deploy seguro. Cubrir los seis detalles es lo que diferencia una orquestación seria de una serie de comandos ",[231,28692,1118],{}," enfilados.",[19,28695,28697],{"id":28696},"quien-implementa-que-la-version-honesta","Quién implementa qué (la versión honesta)",[12,28699,28700],{},"La grilla abajo cubre el ecosistema más común en el nicho self-hosted\u002Fcluster pequeño. No es exhaustiva — hay herramientas excelentes que quedaron fuera —, pero es honesta sobre las que aparecen en las decisiones de arquitectura típicas.",[12,28702,28703,28706,28707,28710,28711,21703,28714,28717,28718,28721,28722,21703,28725,28728,28729,21703,28732,28735],{},[27,28704,28705],{},"Kubernetes."," Implementa todos los seis cuando el manifiesto está completo: ",[231,28708,28709],{},"readinessProbe"," cubre el detalle 1, ",[231,28712,28713],{},"terminationGracePeriodSeconds",[231,28715,28716],{},"preStop"," cubre el 2 y el 6, ",[231,28719,28720],{},"imagePullPolicy"," + cache local cubre el 3, ",[231,28723,28724],{},"progressDeadlineSeconds",[231,28726,28727],{},"revisionHistoryLimit"," cubre el 4, ",[231,28730,28731],{},"maxUnavailable",[231,28733,28734],{},"maxSurge"," cubre el 5. El problema no es lo que hace; es el tamaño del manifiesto necesario para hacer eso, y el número de campos cuyo default no es lo que necesitas.",[12,28737,28738,28741,28742,28745,28746,571,28749,571,28752,28755],{},[27,28739,28740],{},"Docker Swarm."," Implementa rolling vía ",[231,28743,28744],{},"docker service update",". Las primitivas existen (",[231,28747,28748],{},"--update-parallelism",[231,28750,28751],{},"--update-delay",[231,28753,28754],{},"--update-failure-action","), pero los defaults son agresivos demás — paralelismo default alto, sin health check obligatorio, y el comportamiento de auto-revert es opt-in con un flag específico. Necesita ser tuneado para cada servicio; raramente es tuneado.",[12,28757,28758,28761,28762,28764,28765,571,28767,571,28769,571,28771,571,28774,28776],{},[27,28759,28760],{},"Nomad."," Implementa nativamente, con defaults sensatos. ",[231,28763,28513],{}," block tiene ",[231,28766,3303],{},[231,28768,28371],{},[231,28770,28433],{},[231,28772,28773],{},"auto_revert",[231,28775,28472],{}," — básicamente los mismos campos de la spec arriba, porque esa nomenclatura no es coincidencia: es la herencia de buenas prácticas que los principales orquestadores convergieron.",[12,28778,28779,28782,28783,571,28785,571,28788,571,28791,28794],{},[27,28780,28781],{},"HeroCtl."," Implementa todos los seis detalles nativamente, con la configuración prácticamente idéntica a la spec arriba. La elección de coordinador del plano de control toma cerca de 7 segundos cuando el nodo líder cae, así que incluso un deploy ejecutado en pleno momento de cambio de coordinador es resiliente — el nuevo coordinador retoma el ciclo de health check del punto donde estaba. Los defaults son ",[231,28784,28450],{},[231,28786,28787],{},"min_healthy_time: 10",[231,28789,28790],{},"healthy_deadline: 300",[231,28792,28793],{},"auto_revert: true",". Si envías un job sin configurar nada, eso es lo que captura.",[12,28796,28797,28800],{},[27,28798,28799],{},"Watchtower."," No. Watchtower es una herramienta útil para un caso específico — actualización automática de contenedores en ambiente donde aceptas downtime corto y pérdida de conexión como coste de no tener pipeline de deploy. En producción seria, falla en cinco de los seis detalles. No es crítica al proyecto; es crítica al uso de él en contexto erróneo.",[12,28802,28803,28806],{},[27,28804,28805],{},"Coolify y Dokploy."," Implementan parcialmente. Health check existe pero necesita ser configurado por aplicación. Connection draining depende del app capturar SIGTERM (responsabilidad compartida). Auto-revert es manual en ambos. Pre-stop hook genérico no es primitivo de primera clase. Para single-server, es suficiente; para cluster, es frágil.",[12,28808,28809,28812,28813,28816],{},[27,28810,28811],{},"Scripts caseros."," Aquella combinación de ",[231,28814,28815],{},"docker pull && docker stop && docker run"," en un shell script gestionado por cron o disparado por webhook de GitHub. Cero de los seis. Cobertura honesta de lo que es eso: un deploy con downtime corto, no un rolling deploy.",[19,28818,28820],{"id":28819},"los-cuatro-patrones-mas-alla-de-rolling","Los cuatro patrones más allá de rolling",[12,28822,28823],{},"Rolling no es la única estrategia. Conforme el requisito y el presupuesto, tres otras tienen sentido en contextos específicos.",[12,28825,28826,28828],{},[27,28827,2741],{}," Dos ambientes paralelos completos, cada uno con el stack entero. Deploy es subir el ambiente alternativo (verde) con la versión nueva, validar en paralelo, y hacer switch vía DNS o balanceador — un único momento atómico en que el tráfico entero cambia. Más seguro que rolling porque puedes validar la versión nueva con tráfico sintético antes de cualquier usuario real. Cuesta, en capacidad, 2× durante la ventana de deploy. Recomendado para apps donde el coste de bug en producción es alto y el coste de capacidad extra es bajo.",[12,28830,28831,28833],{},[27,28832,2747],{}," Manda 5% (o 1%, o cualquier fracción pequeña) del tráfico hacia la versión nueva, monitorea métricas clave por un período de observación (15 minutos a algunas horas), y escala gradualmente — 5%, 25%, 50%, 100%. Detecta regresión antes de afectar al usuario principal. Prerrequisito es tener métricas confiables con sensibilidad alta; sin eso, canary solo atrasa el deploy sin ganar seguridad. Combina bien con rolling: rolling es el mecanismo, canary es la estrategia de promoción.",[12,28835,28836,28839],{},[27,28837,28838],{},"Rainbow."," Varias versiones coexistiendo simultáneamente en producción, con tráfico ruteado por clave de cliente o tipo de tenant. Caso de uso raro, generalmente en B2B con requisitos de versión por contrato. No es la primera opción casi nunca.",[12,28841,28842,28845],{},[27,28843,28844],{},"Recreate."," Para todo, sube nuevo. Downtime explícito y aceptado. Aceptable para apps internos con ventana de mantenimiento o para ambientes de desarrollo. Sorprendentemente apropiado en casos específicos: deploy que envuelve migración de base que rompe schema, o deploy de app cuya arquitectura no soporta dos versiones coexistiendo. Cuando recreate es la elección correcta, es la elección correcta — no hay premio por hacer rolling de todo.",[19,28847,28849],{"id":28848},"como-detectar-que-tu-rolling-esta-mal","Cómo detectar que tu rolling está mal",[12,28851,28852],{},"Cuatro tests directos. Los dos primeros son métricas que puedes mirar en el monitoreo que ya tienes; los dos siguientes son experimentos que necesitan ser hechos con intención.",[12,28854,28855,28858],{},[27,28856,28857],{},"Tasa de 5xx durante la ventana de deploy."," Si tu tasa de 5xx en producción es estadísticamente diferente de cero durante la ventana del deploy, está mal. \"Estadísticamente diferente\" significa: toma 30 deploys consecutivos, mide la tasa de 5xx en el minuto que precede al deploy y en el minuto del deploy. Si la media del segundo es mayor, hay error real, y la ventana está cortando conexión.",[12,28860,28861,28864],{},[27,28862,28863],{},"Latencia p99 durante el deploy."," Si p99 sube 3× o más durante la ventana de deploy, está mal. Spike de latencia indica que requests están siendo reiniciados internamente, o que el balanceador está reaceptando conexiones para contenedores lentos para responder.",[12,28866,28867,28870,28871,28874,28875,28878,28879,28881],{},[27,28868,28869],{},"Test de crash forzado."," Antes de un deploy programado, fuerza la app en el contenedor nuevo a fallar — ",[231,28872,28873],{},"chmod 000"," en el binario, o variable de entorno que hace ",[231,28876,28877],{},"process.exit(1)"," en el startup. ¿El sistema revierte automáticamente dentro del ",[231,28880,28433],{},"? Si queda trabado esperando intervención humana, el detalle 4 está roto.",[12,28883,28884,28887],{},[27,28885,28886],{},"Deploy de viernes 17h con tráfico real."," El test social. Haz un deploy no-trivial en horario de pico, en un día en que nadie del equipo está mirando activamente. Si la métrica de tu app durante esa ventana es indistinguible de una ventana aleatoria, tu rolling deploy es seguro. Si fue necesaria intervención, o si el canal de status registró algo, no es.",[19,28889,3226],{"id":3225},[12,28891,28892,28895],{},[27,28893,28894],{},"¿Watchtower es seguro para producción?","\nPara producción pequeña con tolerancia explícita a downtime corto y herramienta de fallback (rollback manual rápido), sí. Para producción que tiene cliente pagante con expectativa de SLA, no. Watchtower fue hecho para un problema diferente.",[12,28897,28898,28905,28906,28908,28909,28911],{},[27,28899,28900,28901,5839,28903,25810],{},"¿Health check en ",[231,28902,355],{},[231,28904,28367],{},"\nLa convención que más ayuda en la práctica: ",[231,28907,355],{}," indica \"el proceso está vivo\" (liveness — usado por orquestador para decidir si reinicia el contenedor) y ",[231,28910,28367],{}," indica \"estoy listo para servir tráfico\" (readiness — usado por el orquestador para decidir si incluye el contenedor en el balanceador). Para rolling deploy, lo que importa es el readiness; el orquestador solo promueve un contenedor al pool de tráfico cuando el readiness retorna 200. Si tienes solo un endpoint y responde 200 inmediatamente después de que el proceso suba, tu readiness no está midiendo lo que debía.",[12,28913,28914,28919,28920,101],{},[27,28915,19046,28916,28918],{},[231,28917,28371],{}," debe ser cuánto?","\nRango típico es 10 a 30 segundos. Más corto que eso (3 segundos, 5 segundos) deja pasar falsos positivos — apps que responden 200 luego al inicio pero empiezan a fallar cuando el tráfico real llega. Más largo que 60 segundos se vuelve impedimento operacional sin ganancia proporcional. Si tu aplicación tiene warm-up complejo (cache en memoria, conexión con terceros lentos), el lugar para cubrir eso es en el health check en sí — hacer que solo responda 200 después del warm-up —, no inflar el ",[231,28921,28371],{},[12,28923,28924,28927,28928,28931],{},[27,28925,28926],{},"¿Cómo hago pre-stop en app Rails?","\nRails responde nativamente a SIGTERM con graceful shutdown desde la 5.x — el servidor para de aceptar conexión nueva y termina las en curso. Para Sidekiq, la señal correcta es SIGTSTP (pause workers), seguida por SIGTERM después de que ",[231,28929,28930],{},"Sidekiq.redis { |c| c.llen(\"queue:default\") }"," se ponga a cero. En práctica, el pre-stop hook ejecuta un script pequeño que manda SIGTSTP, hace polling de cola por hasta N segundos, y retorna — el orquestador entonces hace el SIGTERM convencional.",[12,28933,28934,28937],{},[27,28935,28936],{},"¿Sticky sessions y rolling deploy se llevan bien?","\nMal. Sticky session significa que tu arquitectura está delegando estado al balanceador, y durante rolling ese estado es descartado cuando la réplica que sostenía la sesión es cambiada. Resultado: usuario es deslogado, pierde formulario por la mitad, o tiene comportamiento inconsistente. Si necesitas sticky, eso es síntoma — refactoriza a estado externo (Redis, base) y el rolling deploy se vuelve trivial.",[12,28939,28940,28943],{},[27,28941,28942],{},"¿Migración de base en el rolling deploy?","\nLa regla práctica que evita 90% de los dolores: toda migración necesita ser compatible con la versión anterior de la app durante la ventana de deploy. Añadir columna nullable: tranquilo. Remover columna: hazlo en dos releases (release N para de usar la columna; release N+1 la remueve). Renombrar columna: ídem, con columna nueva como copia. Eso permite que viejas y nuevas réplicas coexistan, que es exactamente lo que rolling presupone.",[12,28945,28946,28949,28950,5839,28952,28955],{},[27,28947,28948],{},"¿Puedo testear rolling deploy localmente?","\nPuedes. Sube tres réplicas locales con docker-compose, simula un balanceador (nginx o caddy) al frente, dispara ",[231,28951,2491],{},[231,28953,28954],{},"wrk"," con tráfico sostenido, y ejecuta un script de cambio como tu pipeline ejecutaría en producción. Mide 5xx durante la ventana. Es un test imperfecto (el tráfico es sintético, el nodo es único, no hay red real entre nodos), pero captura los bugs gruesos en los detalles 1, 2 y 3 antes de que filtren a producción.",[19,28957,3310],{"id":3309},[12,28959,28960],{},"Rolling deploy seguro no es un botón; es un conjunto de seis comportamientos coordinados, y la mayoría de las herramientas que prometen \"zero downtime\" cubre tres o cuatro de ellos. La diferencia práctica se vuelve visible el viernes a las 17h, o en el incidente de miércoles por la mañana, o en el postmortem en que alguien pregunta por qué tres usuarios reportaron error durante el último deploy.",[12,28962,28963],{},"La receta está arriba. Si tu herramienta actual cubre los seis, óptimo. Si no, o asumes el coste de cubrir manualmente los faltantes, o cambias por algo que cubre nativamente.",[12,28965,28966],{},"HeroCtl cubre nativamente. Plan Community es gratuito permanente, sin límite de servidores o jobs, con la configuración de rolling deploy descrita aquí como default. Plan Business añade SSO, RBAC, auditoría y soporte con SLA para equipos con requisitos formales de plataforma. Plan Enterprise añade escrow de código fuente y contrato de continuidad.",[12,28968,22434],{},[224,28970,28971],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,28972,28973],{"__ignoreMap":229},[234,28974,28975,28977,28979,28981,28983],{"class":236,"line":237},[234,28976,1220],{"class":247},[234,28978,2958],{"class":251},[234,28980,2961],{"class":255},[234,28982,2964],{"class":383},[234,28984,2967],{"class":247},[12,28986,28987,28988,28990,28991,2403,28994,101],{},"Si quieres ver los otros lados del asunto, lee ",[3337,28989,21746],{"href":6545}," para el contexto de producto, y en los próximos posts vamos a cubrir ",[3337,28992,28993],{"href":3344},"deploy de Docker en producción, del compose al cluster",[3337,28995,28996],{"href":11730},"estrategias de backup de base en cluster para las tres de la mañana",[12,28998,28999],{},"La intención sigue siendo la misma: orquestación de contenedores, sin ceremonia — y sin teatro.",[3351,29001,29002],{},"html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}",{"title":229,"searchDepth":244,"depth":244,"links":29004},[29005,29006,29007,29008,29009,29011,29012,29013,29014,29015,29016,29017],{"id":28345,"depth":244,"text":28346},{"id":28383,"depth":244,"text":28384},{"id":28403,"depth":244,"text":28404},{"id":28420,"depth":244,"text":28421},{"id":28446,"depth":244,"text":29010},"Detalle 5 — max_parallel: 1 en cluster multi-instance",{"id":28476,"depth":244,"text":28477},{"id":28499,"depth":244,"text":28500},{"id":28696,"depth":244,"text":28697},{"id":28819,"depth":244,"text":28820},{"id":28848,"depth":244,"text":28849},{"id":3225,"depth":244,"text":3226},{"id":3309,"depth":244,"text":3310},"2025-12-04","Cambiar contenedor sin downtime parece simple — pull nueva imagen, mata viejo, sube nuevo. Funciona hasta el primer viernes a las 17h. Los 6 detalles que separan rolling deploy real de teatro.",{},{"title":28298,"description":29019},{"loc":3339},"es\u002Fblog\u002Frolling-deploy-seguro-por-que-el-tuyo-puede-no-serlo",[29025,1526,3394,29026,16739],"rolling-deploy","zero-downtime","OzCgVoRlJjPLkGQnQqsN8uWITlEl_GkPcyRABxbkgCM",{"id":29029,"title":29030,"author":7,"body":29031,"category":6382,"cover":3380,"date":29753,"description":29754,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":29755,"navigation":411,"path":14883,"readingTime":3387,"seo":29756,"sitemap":29757,"stem":29758,"tags":29759,"__hash__":29761},"blog_es\u002Fes\u002Fblog\u002Falternativa-kubernetes-paas-auto-hospedado.md","Alternativa a Kubernetes en 2026: PaaS auto-hospedado para equipos pequeños",{"type":9,"value":29032,"toc":29733},[29033,29036,29039,29042,29045,29049,29052,29078,29081,29106,29109,29113,29116,29119,29138,29141,29148,29154,29157,29161,29164,29178,29184,29187,29190,29194,29197,29200,29203,29206,29209,29211,29214,29217,29220,29223,29227,29230,29233,29236,29239,29243,29246,29249,29252,29255,29259,29262,29265,29268,29271,29274,29278,29281,29284,29298,29301,29304,29307,29311,29314,29320,29326,29332,29338,29341,29345,29348,29390,29393,29395,29398,29577,29580,29584,29587,29593,29599,29605,29609,29612,29618,29624,29629,29635,29640,29646,29648,29654,29660,29666,29672,29678,29684,29690,29692,29695,29698,29701,29717,29720,29729,29731],[12,29034,29035],{},"La literatura técnica sobre orquestación de contenedores es mayoritariamente americana. Y mayoritariamente asume un conjunto de premisas que no aplica para equipos pequeños en 2026.",[12,29037,29038],{},"El salario mediano de un SRE americano gira en torno a US$150 mil por año. Para el CFO en San Francisco, es \"una persona cara\". Para un equipo en Madrid, Ciudad de México o Buenos Aires, al cambio actual, es el equivalente a varias personas enteras. La cuenta da diferente. La conclusión también.",[12,29040,29041],{},"Un coste de US$140 al mes de plataforma gestionada se vuelve ruido para el CFO de Mountain View. Para el fundador en otro contexto, es un porcentaje significativo del salario del dev mid que acaba de contratar. La misma decisión arquitectónica — \"vamos a pagar el gestionado y seguir\" — tiene peso financiero completamente diferente en los dos lados del hemisferio.",[12,29043,29044],{},"Este post recalibra la decisión para realidades de equipo pequeño. No es un manifiesto contra Kubernetes. Es una hoja de cálculo.",[19,29046,29048],{"id":29047},"la-realidad-de-presupuesto-sin-rodeos","La realidad de presupuesto, sin rodeos",[12,29050,29051],{},"Antes de comparar plataformas, vale alinear números actuales. Las franjas abajo son medianas del mercado en abril de 2026, considerando equipo de SaaS B2B remoto.",[2735,29053,29054,29060,29066,29072],{},[70,29055,29056,29059],{},[27,29057,29058],{},"Dev mid full-stack",": US$2k a US$3k mensuales.",[70,29061,29062,29065],{},[27,29063,29064],{},"Dev sénior full-stack",": US$3,5k a US$5,5k mensuales.",[70,29067,29068,29071],{},[27,29069,29070],{},"SRE con Kubernetes en producción seria",": US$5k a US$8k mensuales. Raro encontrar por debajo — quien tiene Kubernetes en el currículo aprendió rápido a cobrar por lo que aprendió.",[70,29073,29074,29077],{},[27,29075,29076],{},"Guardia 24×7",": dos SREs como mínimo, o quemas a la única persona en tres meses. La matemática de guardia sostenible no cambia con el país: nadie aguanta ser el único pager por más que eso.",[12,29079,29080],{},"El hospedaje cloud común en 2026 sigue cuatro patrones principales:",[2735,29082,29083,29088,29094,29100],{},[70,29084,29085,29087],{},[27,29086,14362],{},": precios en dólar, simples y previsibles. Popular para equipos pequeños.",[70,29089,29090,29093],{},[27,29091,29092],{},"AWS São Paulo (sa-east-1)",": latencia buena para clientes en Sudamérica, pero precios 30 a 40% por encima de us-east-1.",[70,29095,29096,29099],{},[27,29097,29098],{},"Hetzner (Alemania)",": 30 a 50% más barato que AWS. Bueno para workloads que no son latencia-críticos en Sudamérica.",[70,29101,29102,29105],{},[27,29103,29104],{},"Proveedor local",": facturación en moneda local, atención en español, factura nacional para contabilidad local. Precios por GB y por vCPU generalmente peores que cloud internacional, pero cero exposición cambiaria.",[12,29107,29108],{},"Por encima de todo eso, planea el cambio. El dólar en 2026 oscila con volatilidad anual de aproximadamente 10%. Eso significa que un coste de US$200 al mes en enero puede convertirse en equivalentes de US$220 en octubre sin que tú hayas aumentado nada. Quien presupuesta en moneda local y paga en dólar carga riesgo cambiario silencioso, y ese riesgo es proporcional al tamaño de la factura.",[19,29110,29112],{"id":29111},"la-cuenta-del-kubernetes-gestionado-para-equipo-pequeno","La cuenta del Kubernetes gestionado para equipo pequeño",[12,29114,29115],{},"Pongamos el escenario más común sobre la mesa. Startup B2B, 4 devs, primer producto en producción, 50 clientes pagando, ingresos mensuales recurrentes en moneda local.",[12,29117,29118],{},"La elección \"estándar de la industria\" es EKS en la región São Paulo. La cuenta mínima:",[2735,29120,29121,29124,29127,29130,29133],{},[70,29122,29123],{},"Cluster EKS: US$73\u002Fmes.",[70,29125,29126],{},"Gateway de salida (NAT): ~US$40\u002Fmes.",[70,29128,29129],{},"Balanceador de carga (ALB): ~US$25\u002Fmes.",[70,29131,29132],{},"Tráfico de salida: variable, conservador US$30\u002Fmes.",[70,29134,29135,29137],{},[27,29136,16930],{},": ~US$170\u002Fmes.",[12,29139,29140],{},"Eso es solo plataforma. Las máquinas donde la aplicación corre son extras. En 4 nodos m5.large en la región São Paulo, más ~US$400\u002Fmes. Total realista para producción pequeña: ~US$570\u002Fmes solo en infra.",[12,29142,29143,29144,29147],{},"Y aún falta el coste verdadero: el equipo. Dos SREs junior-mid contratados, US$5k\u002Fmes cada uno: ",[27,29145,29146],{},"US$120k\u002Faño"," solo en plantilla de plataforma. Con seniors, más alto.",[12,29149,29150,29151,101],{},"Total año 1 conservador, plataforma + plantilla: ",[27,29152,29153],{},"US$130k a US$200k antes de que el primer cliente Enterprise pague",[12,29155,29156],{},"Como referencia: 4 devs full-stack a US$3k entregan producto por US$144k\u002Faño. La elección \"Kubernetes gestionado + 2 SREs\" cuesta casi lo mismo que tener el equipo entero de producto duplicado. Solo que entregando plataforma — no entregando feature al cliente.",[19,29158,29160],{"id":29159},"la-cuenta-del-auto-hospedado","La cuenta del auto-hospedado",[12,29162,29163],{},"Mismo escenario, decisión diferente. 3 a 4 VPS Linux con Docker, plano de control replicado, router integrado, certificados automáticos.",[2735,29165,29166,29169,29172,29175],{},[70,29167,29168],{},"4 VPS DigitalOcean (4 vCPU, 8 GB RAM cada uno): US$48\u002Fmes × 4 = US$192\u002Fmes.",[70,29170,29171],{},"Alternativa Hetzner: US$32\u002Fmes × 4 = US$128\u002Fmes.",[70,29173,29174],{},"Backup S3 región São Paulo: ~US$15\u002Fmes.",[70,29176,29177],{},"Tiempo de dev full-stack que cuida la plataforma: 20% de una persona = ~US$600\u002Fmes asignados.",[12,29179,29180,29181,101],{},"Total año 1: ",[27,29182,29183],{},"US$10k a US$15k",[12,29185,29186],{},"Diferencia con el escenario Kubernetes gestionado: 9 a 13 veces menos. Ese delta — algo entre US$115k y US$185k al año — se convierte en dos devs full-stack adicionales, o un diseñador sénior, o tres meses de runway. Es el margen entre cerrar el año con beneficio y cerrar con pérdida.",[12,29188,29189],{},"La objeción honesta a esa cuenta es: \"pero va a dar trabajo operar\". La respuesta también necesita ser honesta. Sí, va a dar algo de trabajo. La pregunta correcta es si el trabajo extra cabe en 20% del tiempo de una persona del equipo. Si la respuesta es sí — y en la franja de 4 servidores y 16 contenedores generalmente lo es — el ROI es directo.",[19,29191,29193],{"id":29192},"hospedaje-en-la-practica-panorama-en-abril-de-2026","Hospedaje en la práctica: panorama en abril de 2026",[12,29195,29196],{},"Cada proveedor que importa tiene trade-offs específicos. Resumen corto para cada uno.",[368,29198,29092],{"id":29199},"aws-sao-paulo-sa-east-1",[12,29201,29202],{},"La región más antigua en territorio brasileño, activa desde 2011. Latencia óptima para cliente en São Paulo (1 a 5 ms intra-región, 30 a 50 ms para Sur y Centro-Oeste). Precios 30 a 40% por encima de us-east-1. No todos los servicios de AWS están disponibles: algunos productos nuevos tardan de 6 a 18 meses en llegar a sa-east-1.",[12,29204,29205],{},"Bueno para: producto B2B con clientes exigiendo data residency en contrato, equipo grande lo suficiente para absorber la complejidad de AWS, empresa con ingresos predominantes en moneda local.",[12,29207,29208],{},"Cuidado con: costes de transferencia de datos entre regiones (caro). Quien replica base entre sa-east-1 y us-east-1 paga caro por el egress.",[368,29210,14362],{"id":14945},[12,29212,29213],{},"Sin región en Sudamérica. Datacenter más cercano es Nueva York (NYC1, NYC3) o Toronto. Latencia media para São Paulo en la franja de 110 a 130 ms — perceptible en aplicación interactiva, irrelevante para API JSON con 200 ms de procesamiento propio.",[12,29215,29216],{},"Precios simples, en USD, previsibles. VPS de 4 vCPU + 8 GB RAM por US$48\u002Fmes. Sin sorpresas de billing — sabes en el día 1 cuánto vas a gastar en el día 30.",[12,29218,29219],{},"Bueno para: equipo pequeño con latencia tolerable (B2B SaaS, dashboards, APIs), startup que prioriza simplicidad de billing, proyecto personal que se vuelve producto.",[12,29221,29222],{},"Cuidado con: aplicaciones user-facing donde 120 ms extra de latencia cuesta conversión (e-commerce, juegos, video chat). Tipo de cambio: todo en dólar.",[368,29224,29226],{"id":29225},"hetzner-alemania-finlandia","Hetzner (Alemania, Finlandia)",[12,29228,29229],{},"Proveedor europeo con la mejor relación coste-beneficio del mercado en 2026. VPS de 4 vCPU + 8 GB por ~US$15\u002Fmes — la mitad del precio de DigitalOcean. Servidores dedicados por US$50\u002Fmes con 64 GB de RAM.",[12,29231,29232],{},"Latencia para São Paulo en la franja de 200 a 230 ms. Inviable para cualquier interacción síncrona con usuario en Sudamérica — perceptible como lentitud. Viable para workloads de fondo, procesamiento batch, análisis de datos, ambientes de staging que nadie usa en tiempo real.",[12,29234,29235],{},"Bueno para: workloads non-customer-facing, infraestructura de build, base de datos secundaria para analytics, archivado.",[12,29237,29238],{},"Cuidado con: todo lo que tiene un humano esperando del otro lado.",[368,29240,29242],{"id":29241},"proveedores-locales","Proveedores locales",[12,29244,29245],{},"Facturación en moneda local, factura nacional, atención en español comercial. Para contabilidad local, simplifica el registro. Para empresa que necesita demostrar proveedor nacional para auditoría pública o contrato público, es exigencia.",[12,29247,29248],{},"Los precios por vCPU y GB tienden a ser 20 a 50% peores que cloud internacional. La oferta de producto también es más limitada — más énfasis en hospedaje tradicional, menos en primitivas modernas tipo block storage, snapshot y API programática consistente.",[12,29250,29251],{},"Bueno para: empresa con obligación contractual de proveedor nacional, equipo que valora atención en español durante incidentes, proyecto público con reglas de proveedor local.",[12,29253,29254],{},"Cuidado con: API y herramental generalmente menos pulidos. Documentación en español es ventaja; documentación incompleta se vuelve trampa cuando el problema es específico.",[368,29256,29258],{"id":29257},"cloud-nacional-emergente-magalu-cloud-dloud-similares","Cloud nacional emergente (Magalu Cloud, dloud, similares)",[12,29260,29261],{},"La categoría más nueva, en maduración a lo largo de 2025 y 2026. Operadores brasileños ofreciendo VPS, object storage y gestionados básicos con precio en moneda local y datacenter en territorio nacional.",[12,29263,29264],{},"Atractivo principal: cumplimiento con datos quedándose explícitamente en el país, sin transferencia internacional para demostrar en auditoría. Facturación en moneda local elimina exposición cambiaria.",[12,29266,29267],{},"Madurez aún en construcción. Catálogo de servicios bastante más limitado que AWS São Paulo. Documentación a veces incompleta. Latencia intra-país es buena por construcción.",[12,29269,29270],{},"Bueno para: empresa donde data residency local es diferencial competitivo, proyectos públicos, equipos que quieren cero exposición cambiaria.",[12,29272,29273],{},"Cuidado con: inmadurez del catálogo. Faltan recursos avanzados que existen en AWS hace cinco años.",[19,29275,29277],{"id":29276},"cumplimiento-y-auto-hospedado","Cumplimiento y auto-hospedado",[12,29279,29280],{},"Las leyes de protección de datos (LGPD en Brasil, GDPR en Europa, leyes equivalentes en otros países) están en vigor y la fiscalización activa ha producido multas substanciales y jurisprudencia inicial.",[12,29282,29283],{},"Estas leyes generalmente no exigen residencia nacional explícita de los datos. Pero exigen:",[2735,29285,29286,29289,29292,29295],{},[70,29287,29288],{},"Tratamiento adecuado de datos personales (base legal documentada, propósito claro, retención justificada).",[70,29290,29291],{},"En caso de transferencia internacional, salvaguarda contractual con la entidad destinataria.",[70,29293,29294],{},"Capacidad de demostrar a la auditoría interna en incident response: quién accedió a qué, cuándo, con qué finalidad.",[70,29296,29297],{},"Registro de incidentes y notificación a la autoridad en plazo razonable (interpretación actual: 48 a 72 horas para incidentes graves).",[12,29299,29300],{},"Auto-hospedado en un proveedor con región en el país simplifica tres cosas. Primera: sin transferencia internacional para demostrar — los datos nunca salieron del territorio nacional. Segunda: el cluster es tuyo, así que el registro de quién accedió a qué es controlable internamente, sin depender de terceros. Tercera: backup gestionado dentro del propio cluster reduce la superficie de exposición con proveedores adicionales.",[12,29302,29303],{},"La edición Business de HeroCtl incluye auditoría detallada que registra cada acción administrativa por usuario, con timestamp y contexto. En incident response, ese registro se vuelve evidencia de buena fe operacional.",[12,29305,29306],{},"El cumplimiento local no es argumento universal para auto-hospedado — empresa global con ingresos en dólar y clientes en EE.UU. ya tiene que preocuparse con GDPR, con framework americano, y con salvaguarda contractual en varios sentidos. Para esas, la complejidad ya existe. Para empresa local atendiendo cliente local, simplificar la topología jurídica de datos es una ganancia concreta.",[19,29308,29310],{"id":29309},"cuando-kubernetes-gestionado-tiene-sentido","Cuándo Kubernetes gestionado tiene sentido",[12,29312,29313],{},"No es nunca. Hay escenarios donde la cuenta se invierte.",[12,29315,29316,29319],{},[27,29317,29318],{},"Empresa con ingresos predominantes en dólar y clientes globales",": el coste en USD de la plataforma es gasto en moneda fuerte, no riesgo cambiario. La volatilidad se vuelve hedge natural, no exposición.",[12,29321,29322,29325],{},[27,29323,29324],{},"Cumplimiento internacional ya mapeado en Kubernetes",": empresas en proceso de SOC 2 Type II o ISO 27001 frecuentemente tienen consultorías y auditores que conocen Kubernetes. El camino es más corto que presentar una stack alternativa para cada auditor — incluso cuando la stack alternativa es técnicamente equivalente o superior.",[12,29327,29328,29331],{},[27,29329,29330],{},"Equipo de plataforma con 3 o más personas dedicadas",": el ecosistema Kubernetes premia escala de operación. Con 3+ ingenieros dedicados, tienes capacidad de extraer valor real de operadores especializados, malla de servicios, observabilidad avanzada. Por debajo de eso, todo eso se vuelve peso.",[12,29333,29334,29337],{},[27,29335,29336],{},"Workload por encima de 50 servidores",": en esa franja, las primitivas del coloso empiezan a rendir. Multi-tenancy real, aislamiento de namespace, federación entre clusters — cosas que nadie necesita en 4 servidores, pero que importan en 50.",[12,29339,29340],{},"Caso contrario: probablemente overkill. La pregunta correcta no es \"¿Kubernetes es bueno?\" — es \"¿Kubernetes es bueno para el tamaño de problema que tengo hoy, y para los próximos 18 meses?\". Para startup pre-Serie A, la respuesta honesta suele ser no.",[19,29342,29344],{"id":29343},"stack-tipica-recomendada-para-equipo-pequeno","Stack típica recomendada para equipo pequeño",[12,29346,29347],{},"Receta práctica para quien empieza desde cero o migra de una plataforma cara.",[2735,29349,29350,29356,29362,29368,29373,29379,29385],{},[70,29351,29352,29355],{},[27,29353,29354],{},"3 a 4 VPS Linux con Docker",": DigitalOcean, Hetzner o proveedor local, dependiendo del trade-off de latencia y cambio que tenga sentido. Franja de US$100 a US$200\u002Fmes.",[70,29357,29358,29361],{},[27,29359,29360],{},"HeroCtl Community",": gratuito, sin límite de servidores. Configura el cluster con plano de control replicado en 3 o más servidores, así la pérdida de cualquier servidor único no derriba el cluster.",[70,29363,29364,29367],{},[27,29365,29366],{},"Base de datos",": Postgres como job en el propio cluster para proyectos donde el cumplimiento lo permita. Para casos con exigencia regulatoria fuerte, RDS São Paulo gestionado, conectado vía VPN o IP autorizado.",[70,29369,29370,29372],{},[27,29371,11370],{},": certificados Let's Encrypt automáticos, ingress sin montaje extra de operadores.",[70,29374,29375,29378],{},[27,29376,29377],{},"Métricas y logs",": jobs internos del propio sistema. Sin DataDog, sin New Relic externo — esos cobran en USD en la escala de US$15 a US$31 por host al mes, lo que para 4 hosts ya pasa de US$120\u002Fmes solo en observabilidad.",[70,29380,29381,29384],{},[27,29382,29383],{},"Backup",": rotación semanal a bucket S3 en São Paulo o CloudFlare R2 (R2 tiene egress gratuito, lo que para restore es diferencial).",[70,29386,29387,29389],{},[27,29388,12132],{},": CloudFlare gratis. Tienen API programática estable.",[12,29391,29392],{},"Total operacional de esa stack en la franja de US$120 a US$220\u002Fmes de infra, más 10 a 20% del tiempo de una persona del equipo. Soporta de cero a algunos cientos de miles de requests por día sin necesidad de repensar arquitectura.",[19,29394,17389],{"id":17388},[12,29396,29397],{},"Cuatro caminos, diez criterios. Sin columna sin matiz.",[119,29399,29400,29418],{},[122,29401,29402],{},[125,29403,29404,29406,29409,29412,29415],{},[128,29405,2983],{},[128,29407,29408],{},"K8s gestionado (EKS-SP)",[128,29410,29411],{},"PaaS gestionada externa (Render\u002FRailway)",[128,29413,29414],{},"Auto-hospedado simple (Coolify)",[128,29416,29417],{},"Auto-hospedado HA (HeroCtl)",[141,29419,29420,29437,29451,29467,29481,29495,29511,29525,29542,29558],{},[125,29421,29422,29425,29428,29431,29434],{},[146,29423,29424],{},"Coste mínimo de plataforma\u002Fmes",[146,29426,29427],{},"~US$170",[146,29429,29430],{},"US$0 a US$40 (free tier + first apps)",[146,29432,29433],{},"US$40 a US$100 (1 VPS)",[146,29435,29436],{},"US$100 a US$200 (3-4 VPS)",[125,29438,29439,29442,29444,29446,29449],{},[146,29440,29441],{},"Tipo de cambio",[146,29443,15176],{},[146,29445,15176],{},[146,29447,29448],{},"Mixto (VPS USD o local)",[146,29450,29448],{},[125,29452,29453,29456,29459,29462,29465],{},[146,29454,29455],{},"Latencia para São Paulo",[146,29457,29458],{},"1-5 ms",[146,29460,29461],{},"100-200 ms (servidores en EE.UU.)",[146,29463,29464],{},"depende del VPS",[146,29466,29464],{},[125,29468,29469,29471,29474,29477,29479],{},[146,29470,16410],{},[146,29472,29473],{},"1-2 SREs dedicados",[146,29475,29476],{},"0,1 dev part-time",[146,29478,22214],{},[146,29480,22214],{},[125,29482,29483,29485,29487,29490,29493],{},[146,29484,16336],{},[146,29486,3065],{},[146,29488,29489],{},"Sí (gestionado por el proveedor)",[146,29491,29492],{},"No — single-server",[146,29494,3065],{},[125,29496,29497,29500,29503,29506,29509],{},[146,29498,29499],{},"Data residency local",[146,29501,29502],{},"Sí (sa-east-1)",[146,29504,29505],{},"No nativo",[146,29507,29508],{},"Sí, si VPS es local",[146,29510,29508],{},[125,29512,29513,29516,29518,29520,29522],{},[146,29514,29515],{},"Atención en español",[146,29517,26185],{},[146,29519,3059],{},[146,29521,7228],{},[146,29523,29524],{},"Sí (Business\u002FEnterprise)",[125,29526,29527,29530,29533,29536,29539],{},[146,29528,29529],{},"Riesgo de cambio de términos",[146,29531,29532],{},"Medio (proveedor ya cambió política antes)",[146,29534,29535],{},"Alto (proveedor puede cerrar tier free)",[146,29537,29538],{},"Bajo (open-source)",[146,29540,29541],{},"Bajo (precio congelado contractualmente)",[125,29543,29544,29547,29549,29552,29555],{},[146,29545,29546],{},"Líneas de configuración para app+TLS+ingress",[146,29548,3048],{},[146,29550,29551],{},"5 a 10 (UI)",[146,29553,29554],{},"20 a 30 (UI)",[146,29556,29557],{},"~50 (archivo)",[125,29559,29560,29563,29566,29569,29575],{},[146,29561,29562],{},"Camino para crecer a 50 servidores",[146,29564,29565],{},"Directo",[146,29567,29568],{},"Costoso (precio crece linear)",[146,29570,29571,29572,16057],{},"Rehacer arquitectura (",[3337,29573,29574],{"href":16704},"salir de Coolify single-server",[146,29576,29565],{},[12,29578,29579],{},"La línea de coste mínimo de plataforma por sí sola no decide. La línea que más suele decidir es la de equipo mínimo para operar — porque equipo cuesta, en promedio, 100 veces más que plataforma para el tamaño de operación que estamos discutiendo.",[19,29581,29583],{"id":29582},"cuando-no-ir-de-auto-hospedado","Cuándo NO ir de auto-hospedado",[12,29585,29586],{},"La tesis de este post es directa, pero tiene tres escenarios donde la recomendación se invierte.",[12,29588,29589,29592],{},[27,29590,29591],{},"Equipo de 1 a 2 devs sin tiempo para cuidar servidor",": en ese caso, Render, Railway o Heroku son la respuesta correcta. Pagas en USD, pero cambias tiempo (que no tienes) por dinero (que tienes lo suficiente para cubrir en esa fase). Cuando el equipo crezca a 4+ devs y la factura se vuelva incómoda, migrar es viable. Por ahora, foco en el producto.",[12,29594,29595,29598],{},[27,29596,29597],{},"Aplicación cuyo coste de plataforma es trivial vs ingresos",": SaaS B2B con US$40k de MRR y factura de plataforma de US$600\u002Fmes. No optimices prematuramente. Usa el tiempo del equipo para construir feature que aumenta MRR, no para ahorrar 0,5% de los ingresos en infra.",[12,29600,29601,29604],{},[27,29602,29603],{},"Cumplimiento que exige proveedor nominalmente listado y auditado por tercera parte",": algunos frameworks específicos (gobierno, salud regulada) exigen que el proveedor esté en lista pre-aprobada. Esas listas cambian despacio. Si necesitas el nombre AWS o Microsoft en el contrato, auto-hospedado en VPS genérico no atiende. Espera HeroCtl llegar a listas formales o usa la stack que ya está listada.",[19,29606,29608],{"id":29607},"heroctl-en-el-contexto-local-especificamente","HeroCtl en el contexto local específicamente",[12,29610,29611],{},"La discusión hasta aquí fue sobre arquitectura. Vale cerrar con lo que HeroCtl hace específicamente por el contexto local.",[12,29613,29614,29617],{},[27,29615,29616],{},"Plan Community gratuito permanente",", sin licencia en USD para presupuestar, sin suscripción, sin límite de servidores o de jobs. Corre toda la stack descrita arriba — alta disponibilidad real, router, certificados automáticos, métricas, logs.",[12,29619,29620,29623],{},[27,29621,29622],{},"Corre en cualquier VPS Linux con Docker."," Cualquier proveedor local o internacional sirve. El cluster no sabe ni le importa si está en DigitalOcean Nueva York, AWS São Paulo, Hetzner Alemania, Magalu Cloud Brasil o mezclando providers. La primitiva es sistema operativo Linux + Docker, y eso corre en todo lugar.",[12,29625,29626,29628],{},[27,29627,24645],{}," en las ediciones Business y Enterprise. Equipo de producto y soporte alineado con tu zona horaria — tu incidente de las 14h no se vuelve \"vamos a verlo mañana por la mañana\".",[12,29630,29631,29634],{},[27,29632,29633],{},"Precios de Business y Enterprise publicados",", congelados contractualmente para clientes existentes. Sin cláusula de aumento retroactivo, sin cambio de licencia mid-flight como ocurrió con un proveedor competidor en 2023. El contrato que firmas hoy es el contrato que vale.",[12,29636,29637,29639],{},[27,29638,4895],{}," desde el inicio, no como traducción posterior. Errores, mensajes de log, panel administrativo, todo en español como primera lengua.",[12,29641,29642,29645],{},[27,29643,29644],{},"Sin phone-home obligatorio",", sin kill-switch remoto. Una vez instalado, tu cluster funciona offline indefinidamente. Las ediciones Enterprise incluyen escrow de código fuente: si la empresa detrás del producto cierra operaciones, el código se entrega a los clientes pagantes vía tercera parte custodiante.",[19,29647,7352],{"id":7351},[12,29649,29650,29653],{},[27,29651,29652],{},"¿Kubernetes gestionado en São Paulo es suficiente para data residency?","\nTécnicamente sí — la región sa-east-1 mantiene los datos en territorio nacional. Operacionalmente, depende. Quien usa servicios gestionados (RDS, S3, CloudWatch) necesita configurar cada uno para que quede exclusivamente en sa-east-1, y demostrar eso en auditoría. Auto-hospedado en VPS local simplifica la demostración: el cluster entero tiene una dirección IP, en un datacenter conocido, y punto.",[12,29655,29656,29659],{},[27,29657,29658],{},"¿Puedo correr HeroCtl en VPS pequeño?","\nSí. El requisito mínimo es Linux con Docker y 1 GB de RAM por servidor (recomendado 2 GB+). Funciona en VPS de US$10\u002Fmes para cluster de prueba, o para entorno de desarrollo. Para producción sostenible, se recomienda 4 GB+ por servidor.",[12,29661,29662,29665],{},[27,29663,29664],{},"¿Cuánto consume en RAM y CPU en servidor pequeño?","\nEl plano de control ocupa entre 200 y 400 MB de RAM por servidor. En VPS de 1 GB, sobra ~600 MB para workload. En VPS de 2 GB, sobra ~1,6 GB. Como referencia, el plano de control de una versión gestionada de Kubernetes empieza en ~700 MB por nodo-master antes de que cualquier aplicación suba, y raramente corre en VPS de menos de 4 GB.",[12,29667,29668,29671],{},[27,29669,29670],{},"¿Tiene atención en español?","\nSí, en Business y Enterprise. Community usa documentación y foro en español, sin SLA de respuesta. Business tiene soporte directo en español comercial con SLA de respuesta. Enterprise añade horario extendido y canal dedicado.",[12,29673,29674,29677],{},[27,29675,29676],{},"¿Y para escalar a 50+ servidores en el futuro?","\nLa franja de aplicación probada es de 1 a 500 servidores. Por encima de 500, el ecosistema de Kubernetes ofrece herramientas que aún no tenemos. Entre 50 y 500, HeroCtl corre cómodamente — no exige rehacer arquitectura como ocurre cuando sales de Coolify single-server a HA real. La migración es continuación, no recomienzo.",[12,29679,29680,29683],{},[27,29681,29682],{},"¿Y el soporte 24×7 en horario comercial?","\nEnterprise incluye soporte 24×7 con persona real respondiendo en español. Para equipo que tiene incidente a las 23h del miércoles, es el equivalente operacional al soporte que clientes americanos reciben en horario americano — solo que para tu zona horaria.",[12,29685,29686,29689],{},[27,29687,29688],{},"¿Puedo pagar en moneda local?","\nSí. Business y Enterprise se facturan en moneda local, con factura nacional. Sin exposición cambiaria, sin conversión de tarjeta internacional. La contabilidad local lo procesa como cualquier otro proveedor nacional.",[19,29691,3310],{"id":3309},[12,29693,29694],{},"La pregunta correcta para equipo pequeño en 2026 no es \"¿cuál es el mejor orquestador?\". Es \"¿qué orquestador tiene sentido en mi hoja de cálculo de coste, en mi zona horaria, con mi equipo, atendiendo a mi cliente, bajo la ley que regula mis datos?\".",[12,29696,29697],{},"La respuesta varía. Para algunas empresas, es Kubernetes gestionado en sa-east-1. Para otras, es Render o Railway pagando en USD mientras MRR lo justifique. Para la mayoría de las startups pre-Serie A — presupuesto ajustado, equipo reducido, cliente local — la respuesta es auto-hospedado en VPS, con plano de control replicado de verdad.",[12,29699,29700],{},"Para ese caso, construimos HeroCtl. Instalación:",[224,29702,29703],{"className":226,"code":2949,"language":228,"meta":229,"style":229},[231,29704,29705],{"__ignoreMap":229},[234,29706,29707,29709,29711,29713,29715],{"class":236,"line":237},[234,29708,1220],{"class":247},[234,29710,2958],{"class":251},[234,29712,2961],{"class":255},[234,29714,2964],{"class":383},[234,29716,2967],{"class":247},[12,29718,29719],{},"En 5 minutos tienes cluster con 3 servidores, plano de control replicado, router integrado y certificados Let's Encrypt automáticos. A partir de ahí, es solo enviar aplicaciones.",[12,29721,29722,29723,29725,29726,29728],{},"Para contexto adicional, lee ",[3337,29724,6546],{"href":6545}," (la historia de la brecha que ninguna de las tres alternativas existentes llenaba) y ",[3337,29727,21924],{"href":15790}," (la versión general, no específica del contexto local, del mismo argumento).",[12,29730,3349],{},[3351,29732,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":29734},[29735,29736,29737,29738,29745,29746,29747,29748,29749,29750,29751,29752],{"id":29047,"depth":244,"text":29048},{"id":29111,"depth":244,"text":29112},{"id":29159,"depth":244,"text":29160},{"id":29192,"depth":244,"text":29193,"children":29739},[29740,29741,29742,29743,29744],{"id":29199,"depth":271,"text":29092},{"id":14945,"depth":271,"text":14362},{"id":29225,"depth":271,"text":29226},{"id":29241,"depth":271,"text":29242},{"id":29257,"depth":271,"text":29258},{"id":29276,"depth":244,"text":29277},{"id":29309,"depth":244,"text":29310},{"id":29343,"depth":244,"text":29344},{"id":17388,"depth":244,"text":17389},{"id":29582,"depth":244,"text":29583},{"id":29607,"depth":244,"text":29608},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2025-11-25","Equipos pequeños operan con restricciones diferentes: presupuesto ajustado, hospedaje en DigitalOcean o AWS, regulaciones locales. Cómo eso cambia la elección de orquestador.",{},{"title":29030,"description":29754},{"loc":14883},"es\u002Fblog\u002Falternativa-kubernetes-paas-auto-hospedado",[20406,24194,29760,6394,15817],"cumplimiento","B2MuyfkNT1DdhwsVFgpbR1MqV8ePSxv9an4rhHHwAfM",{"id":29763,"title":29764,"author":7,"body":29765,"category":8761,"cover":3380,"date":30364,"description":30365,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":30366,"navigation":411,"path":19773,"readingTime":3387,"seo":30367,"sitemap":30368,"stem":30369,"tags":30370,"__hash__":30372},"blog_es\u002Fes\u002Fblog\u002Fheroku-auto-hospedado-2026.md","Heroku auto-hospedado en 2026: el estado del segmento",{"type":9,"value":29766,"toc":30343},[29767,29770,29773,29776,29780,29786,29789,29792,29798,29804,29810,29813,29816,29820,29824,29827,29833,29839,29844,29847,29851,29854,29866,29869,29872,29876,29883,29886,29890,29893,29898,29903,29908,29911,29915,29918,29923,29926,29928,30144,30147,30151,30154,30160,30166,30172,30178,30182,30186,30189,30192,30195,30198,30202,30205,30208,30211,30215,30218,30221,30224,30228,30231,30237,30243,30249,30252,30256,30259,30262,30265,30268,30271,30273,30279,30285,30291,30297,30303,30309,30315,30317,30320,30323,30326,30331,30340],[12,29768,29769],{},"El 28 de noviembre de 2022, Salesforce apagó el plan gratuito de Heroku. La empresa que compró Heroku en 2010 cumplió el aviso publicado tres meses antes — todas las dynos free, todos los bancos hobby, todos los redises gratuitos fueron terminados en la misma ventana. Cientos de miles de hobby projects, MVPs, demos de portfolio y prototipos universitarios desaparecieron del aire de una sola vez.",[12,29771,29772],{},"La reacción fue previsible. Quien tenía cobro en la tarjeta migró al plan pago y siguió. Quien no tenía buscó otro lugar. Y en las semanas siguientes, un movimiento que existía en estado adormecido desde 2013 explotó: \"Heroku auto-hospedado\".",[12,29774,29775],{},"En 2026, tres años y medio después, el segmento maduró. Hay al menos seis productos serios disputando atención, más un puñado de proyectos hospedados que se venden como \"Heroku-like\" sin el auto. Este post es el mapa.",[19,29777,29779],{"id":29778},"por-que-heroku-auto-hospedado-se-volvio-una-categoria","Por qué \"Heroku auto-hospedado\" se volvió una categoría",[12,29781,29782,29783,29785],{},"Lo primero que necesita decirse es que Heroku resolvió el problema correcto. En 2010, deploy de aplicación web tenía dos formas: subir tarball a un servidor que tú administrabas, o pagar caro para que alguien administre por ti. Heroku inventó el tercer camino — ",[231,29784,23667],{},", slider de escala, base gestionada embebida, certificado emitido automáticamente, sub-dominio funcional en segundos.",[12,29787,29788],{},"Ese patrón quedó. El concepto de \"deploy es un push, escala es un slider, TLS es automático\" se volvió la expectativa-base de cualquier desarrollador formado después de 2012. Todo lo que vino después — Render, Railway, Fly.io, Vercel para frontend, Cloud Run, App Runner — es variación encima de ese modelo.",[12,29790,29791],{},"Pero tres cosas cambiaron entre 2010 y 2022.",[12,29793,29794,29797],{},[27,29795,29796],{},"Cloud bare-metal se volvió barato."," En 2010, un servidor virtual decente costaba US$40\u002Fmes. En 2026, US$5\u002Fmes compra un VPS con 1 vCPU, 2 GB de RAM, 50 GB de disco y 2 TB de tráfico — más que suficiente para ejecutar cinco aplicaciones pequeñas. La economía de cerrar dynos para ejecutar containers propios se invirtió.",[12,29799,29800,29803],{},[27,29801,29802],{},"Docker se volvió estándar."," La gran virtud de Heroku original eran los \"buildpacks\" — recetas que tomaban tu código Ruby o Node y producían un artefacto aislado listo para ejecutar. Docker volvió ese encapsulamiento commodity. Hoy cualquiera produce una imagen reproducible en tres líneas de Dockerfile, y cualquier servidor con 100 MB de RAM libre puede hospedarla.",[12,29805,29806,29809],{},[27,29807,29808],{},"La comunidad aprendió a operar."," En 2010, \"ejecutar un servidor Linux\" era oficio de SRE. En 2026, cualquier desarrollador full-stack ya configuró nginx, lidió con certbot, montó systemd unit, debugueó OOM-killer por dmesg. El nivel medio subió. Aquello que justificaba pagar US$25\u002Fmes para que Heroku cuide se volvió un ejercicio de una tarde.",[12,29811,29812],{},"Cuando el gratuito murió, montar \"tu propio Heroku\" dejó de ser ejercicio de orgullo de hacker y se volvió cuenta de panadería. US$10\u002Fmes de VPS contra US$25\u002Fmes mínimo en el Heroku-pago — y eso por aplicación. Cinco aplicaciones en Heroku cuestan US$125\u002Fmes. Cinco aplicaciones en un VPS de US$10\u002Fmes siguen costando US$10\u002Fmes.",[12,29814,29815],{},"La categoría que respondió a esa cuenta tiene cinco subgéneros distintos hoy. Vale la pena separar.",[19,29817,29819],{"id":29818},"el-segmento-en-2026","El segmento en 2026",[368,29821,29823],{"id":29822},"single-server-simple-instalo-en-un-vps-y-olvido","Single-server simple — \"instalo en un VPS y olvido\"",[12,29825,29826],{},"El subgénero más antiguo y más habitado. La premisa es directa: un único servidor, un instalador, un panel o CLI, y tienes dynos. Sin cluster, sin alta disponibilidad, sin complicación.",[12,29828,29829,29832],{},[27,29830,29831],{},"Dokku"," es el abuelito del segmento, activo desde 2013. El motor es Bash más Docker. UX es mayoritariamente CLI — empujas código vía git remoto, construye con buildpacks Heroku-compatibles, sube el container, registra en el router interno. La comunidad es pequeña pero leal, el producto es estable, y la curva de aprendizaje es empinada en los primeros días y plana después de eso. Quien pasó de esos primeros días raramente cambia. Está fuera de moda en el sentido de que la comunidad nueva prefiere paneles web — pero el producto sigue siendo sólido, con más de doce años de operación real en producción en miles de instalaciones por el mundo.",[12,29834,29835,29838],{},[27,29836,29837],{},"Caprover"," ocupa el medio del espectro. Panel web, sistema de plugins, instalación razonablemente fácil. El producto tiene cerca de trece mil estrellas en repositorios públicos y una comunidad activa, aunque menor que la de los competidores más nuevos. La evolución es más lenta — releases vienen en cadencia mensual o bimestral, y features grandes tardan. Para quien prioriza estabilidad sobre novedades, es una elección defendible.",[12,29840,29841,29843],{},[27,29842,2771],{}," es el líder actual de mindshare. Por encima de cuarenta mil estrellas, panel web moderno, ecosistema de plugins activo, comunidad ruidosa en foros y en chat. El producto evolucionó rápido entre 2023 y 2025, agregando soporte a base gestionada embebida, deploy vía git, certificados automáticos, monitoreo de containers. Es la recomendación default que circula en foros de indie hackers hoy.",[12,29845,29846],{},"El defecto principal de Coolify, y la razón de que aparezca también en la sección sobre trampas más abajo, es arquitectural: fue diseñado single-server first. Multi-server fue añadido después, pero el panel central sigue siendo un único proceso en un único servidor. Si ese servidor se cae, pierdes acceso a todos los demás.",[368,29848,29850],{"id":29849},"single-server-moderno-deploy-sin-panel","Single-server moderno — \"deploy sin panel\"",[12,29852,29853],{},"Subgénero más nuevo, con filosofía opuesta a la anterior. En lugar de panel web, herramienta de línea de comando que opera por SSH.",[12,29855,29856,29858,29859,29862,29863,101],{},[27,29857,2998],{}," es el representante casi exclusivo. Salió del equipo de 37signals en 2024, escrito por gente cercana a DHH. La premisa es radical: ningún panel, ningún control plane, ningún agente residente en los servidores. Escribes un archivo de configuración, corres ",[231,29860,29861],{},"kamal deploy",", hace SSH en cada servidor, hace pull de la imagen, cambia el container y sigue. DHH publicó en 2024 que economizó cerca de tres millones de dólares al año migrando los apps propios de Basecamp y de HEY de la cloud a hardware propio con Kamal. Donde la tesis del \"sin orquestación\" empieza a doler está en ",[3337,29864,29865],{"href":25898},"HeroCtl vs Kamal",[12,29867,29868],{},"La virtud es la transparencia absoluta — no hay nada sucediendo que no veas en el terminal. El defecto es que multi-server no es orquestación, es deploy paralelo. No hay elección de líder, no hay rebalanceo, no hay failover. Cada servidor es un destino independiente. Si uno se cae, notificas tu monitoreo y rehaces el deploy excluyendo aquel host.",[12,29870,29871],{},"Para un equipo pequeño operando dos o tres aplicaciones en tres a cinco servidores, con hábitos disciplinados de deploy, Kamal es elegante. Para cualquier cosa que necesite \"si un servidor se cae, el cluster decide qué hacer solo\", no es la herramienta correcta.",[368,29873,29875],{"id":29874},"cloud-native-moderno-heroku-reembrulhado","Cloud-native moderno — \"Heroku reembrulhado\"",[12,29877,29878,29880,29881,101],{},[27,29879,2777],{}," es el producto más reciente que entró en la conversación. Por encima de diez mil estrellas, en crecimiento rápido, UX visualmente parecida con Coolify pero arquitectura subyacente sobre Docker Swarm. Atractivo principal: multi-server real \"fuera de la caja\", sin necesitar montar a mano. La lectura punto a punto de la elección técnica que Dokploy hizo está en ",[3337,29882,16710],{"href":16709},[12,29884,29885],{},"El defecto estructural es la fundación. Docker Swarm está en modo de mantenimiento hace años — Docker Inc. no invierte en features nuevas desde 2019, y el roadmap público es esencialmente \"mantener funcionando\". Construir producto nuevo encima de tecnología en mantenimiento es una apuesta. Si Swarm fuera discontinuada formalmente, Dokploy necesita migrar de fundación entera o reescribir — y el usuario paga esa cuenta en mitad de camino. El ecosistema de plugins aún es menor que el de Coolify, pero viene subiendo rápido.",[368,29887,29889],{"id":29888},"hospedado-pero-prefiero-self-hosted-vercelrender-pero-en-mi-servidor","Hospedado-pero-prefiero-self-hosted — \"Vercel\u002FRender pero en mi servidor\"",[12,29891,29892],{},"Técnicamente fuera de la categoría del título del post, pero vale la pena mencionar porque muchos equipos comparan. Quien busca \"alternativa a Heroku\" frecuentemente acaba no en el auto-hospedado, y sí en otro hospedado.",[12,29894,29895,29897],{},[27,29896,15024],{}," es el sucesor más directo de Heroku en el espíritu. UX limpia, precios previsibles, free tier generoso (pero no infinito — tiene suspensión automática por inactividad). Base Postgres y Redis gestionadas, deploy vía git, build logs en el panel. El precio sube de forma lineal con uso real, sin trampas grandes. Es la elección obvia para quien quiere \"Heroku que funciona en 2026\" sin preocuparse con servidor.",[12,29899,29900,29902],{},[27,29901,15027],{}," es hospedado, foco más fuerte en devs solo, precio por uso de recursos (CPU\u002FRAM\u002Ftráfico) en lugar de tier fijo. Funciona bien para hobby project que no va a escalar; puede ponerse caro rápido si olvidas un worker corriendo.",[12,29904,29905,29907],{},[27,29906,23817],{}," tiene propuesta diferente: hospedaje distribuido en múltiples regiones, primitivas más crudas, próxima a \"VM como servicio con TLS automático\" que de \"PaaS al estilo Heroku\". Es la elección de quien quiere baja latencia mundial sin montarlo a mano. La curva de aprendizaje es mayor que Render o Railway.",[12,29909,29910],{},"Los tres son opciones legítimas. La nota importante es lo que viene en la sección de trampas: free tier de hospedado pisa más cada año, y el camino histórico de Heroku — empezó gratuito, se volvió US$25\u002Fmes mínimo — es la previsión default para cualquier plan gratuito de empresa privada.",[368,29912,29914],{"id":29913},"cluster-real-necesito-alta-disponibilidad","Cluster real — \"necesito alta disponibilidad\"",[12,29916,29917],{},"Categoría corta, con pocos productos serios. Aquí la premisa no es \"ejecutar deploy en más de un servidor\", es \"si un servidor se cae, el cluster sigue funcionando solo sin intervención humana\". La diferencia es grande, y la mayoría del segmento no atraviesa esa línea.",[12,29919,29920,29922],{},[27,29921,2995],{}," es el producto que estamos construyendo. Plano de control replicado entre tres o más servidores desde el primer día. Elección automática de coordinador en alrededor de siete segundos cuando el servidor que coordina se cae. Router integrado, certificados automáticos, métricas y logs embebidos en el propio binario. Modelo comercial con Community gratuito permanente, Business y Enterprise pagos con precio publicado. Franja ideal: de uno a quinientos servidores.",[12,29924,29925],{},"La diferencia operacional importa cuando el cliente entra. Mientras el panel central de un Coolify multi-server es un punto único de fallo, en HeroCtl no hay central — cualquiera de los tres primeros servidores puede coordinar, y la transición entre ellos es automática.",[19,29927,17389],{"id":17388},[119,29929,29930,29950],{},[122,29931,29932],{},[125,29933,29934,29936,29938,29940,29942,29944,29946,29948],{},[128,29935,2983],{},[128,29937,29831],{},[128,29939,29837],{},[128,29941,2771],{},[128,29943,2998],{},[128,29945,2777],{},[128,29947,15024],{},[128,29949,2995],{},[141,29951,29952,29972,29990,30008,30026,30044,30062,30080,30099,30121],{},[125,29953,29954,29956,29958,29961,29963,29965,29967,29970],{},[146,29955,27233],{},[146,29957,3014],{},[146,29959,29960],{},"10 min",[146,29962,3020],{},[146,29964,3020],{},[146,29966,29960],{},[146,29968,29969],{},"n\u002Fa (hospedado)",[146,29971,3020],{},[125,29973,29974,29976,29978,29980,29982,29984,29986,29988],{},[146,29975,25614],{},[146,29977,3059],{},[146,29979,3065],{},[146,29981,3065],{},[146,29983,3059],{},[146,29985,3065],{},[146,29987,3065],{},[146,29989,3065],{},[125,29991,29992,29994,29996,29998,30000,30002,30004,30006],{},[146,29993,26658],{},[146,29995,3059],{},[146,29997,3140],{},[146,29999,3140],{},[146,30001,3140],{},[146,30003,3065],{},[146,30005,28074],{},[146,30007,3065],{},[125,30009,30010,30012,30014,30016,30018,30020,30022,30024],{},[146,30011,16336],{},[146,30013,3059],{},[146,30015,3059],{},[146,30017,3059],{},[146,30019,3059],{},[146,30021,3140],{},[146,30023,3065],{},[146,30025,3065],{},[125,30027,30028,30030,30032,30034,30036,30038,30040,30042],{},[146,30029,3924],{},[146,30031,3065],{},[146,30033,3065],{},[146,30035,3065],{},[146,30037,3065],{},[146,30039,3065],{},[146,30041,3065],{},[146,30043,3065],{},[125,30045,30046,30048,30050,30052,30054,30056,30058,30060],{},[146,30047,23315],{},[146,30049,3059],{},[146,30051,3059],{},[146,30053,3059],{},[146,30055,3059],{},[146,30057,3059],{},[146,30059,3065],{},[146,30061,3065],{},[125,30063,30064,30066,30068,30070,30072,30074,30076,30078],{},[146,30065,22795],{},[146,30067,3059],{},[146,30069,19366],{},[146,30071,3065],{},[146,30073,3059],{},[146,30075,3065],{},[146,30077,3065],{},[146,30079,3065],{},[125,30081,30082,30085,30087,30089,30091,30093,30095,30097],{},[146,30083,30084],{},"Logs embebidos",[146,30086,3059],{},[146,30088,19366],{},[146,30090,3065],{},[146,30092,3059],{},[146,30094,3065],{},[146,30096,3065],{},[146,30098,3065],{},[125,30100,30101,30103,30106,30108,30111,30113,30115,30118],{},[146,30102,22839],{},[146,30104,30105],{},"Open-source",[146,30107,30105],{},[146,30109,30110],{},"Open-source + cloud paga",[146,30112,30105],{},[146,30114,30105],{},[146,30116,30117],{},"Hospedado pago",[146,30119,30120],{},"Community gratuito + Business\u002FEnterprise",[125,30122,30123,30126,30129,30132,30134,30137,30140,30142],{},[146,30124,30125],{},"Franja ideal",[146,30127,30128],{},"1 servidor",[146,30130,30131],{},"1–3 servidores",[146,30133,30131],{},[146,30135,30136],{},"1–10 servidores",[146,30138,30139],{},"3–10 servidores",[146,30141,28074],{},[146,30143,26208],{},[12,30145,30146],{},"La columna que separa el segmento en dos mitades es \"alta disponibilidad real\". A la izquierda de ella, todos los productos comparten la misma premisa: multi-server es destino de deploy, no cluster con consenso. A la derecha, el panel\u002Fcontrol plane es replicado y sobrevive a la pérdida de cualquier servidor.",[19,30148,30150],{"id":30149},"decision-por-perfil-de-uso","Decisión por perfil de uso",[12,30152,30153],{},"Cuatro perfiles cubren la mayoría de los casos.",[12,30155,30156,30159],{},[27,30157,30158],{},"Solo dev, hobby project, un VPS."," Dokku si te gusta CLI y quieres estabilidad. Coolify si prefieres panel web. Kamal si estás en un stack Rails o Node y ya trabajas bien con SSH y archivos de configuración. Cualquiera de los tres resuelve. La elección es más de gusto que de capacidad técnica.",[12,30161,30162,30165],{},[27,30163,30164],{},"Indie hacker con uno a tres SaaS pequeños, aún un servidor."," Coolify o Dokploy. La diferencia práctica es el ecosistema de plugins (Coolify tiene más) y la fundación técnica (Dokploy apuesta en Swarm). Para los próximos doce meses, cualquiera de los dos funciona; la migración entre ellos es factible porque ambos ejecutan containers Docker estándar. La decisión arquitectural importante es diferente: cuando pases de un servidor a dos, vas a sentir el punto único de fallo del panel — y esa es la hora de evaluar si la próxima migración es Dokploy multi-server o un cluster de verdad.",[12,30167,30168,30171],{},[27,30169,30170],{},"Startup con primer cliente serio, SLA contractual entrando en vigor."," HeroCtl. Aquí el panel single-server se vuelve pasivo legal — cualquier SLA escrito en contrato comercial asume que la infraestructura sobrevive a la pérdida de un nodo, y ningún panel single-server hace eso. Puedes intentar montar redundancia manual encima de Coolify o Dokploy, pero el resultado va a ser frágil y costoso de operar. La regla simple es: a la hora en que el contrato con cliente menciona \"uptime\", el cluster con consenso deja de ser lujo.",[12,30173,30174,30177],{},[27,30175,30176],{},"Empresa establecida, cincuenta servidores o más, equipo de plataforma con tres personas dedicadas."," Aquí la conversación cambia. K8s gestionado en proveedor cloud pasa a ser la opción sensata, porque el ecosistema de operadores es mayor y el equipo tiene competencia para absorber la complejidad. HeroCtl ejecuta en esa franja también — testeamos cientos de nodos en laboratorio, decenas en producción de clientes — pero por encima de cien servidores el techo de nuestra biblioteca de operadores especializados empieza a aparecer.",[19,30179,30181],{"id":30180},"las-tres-trampas-del-segmento","Las tres trampas del segmento",[368,30183,30185],{"id":30184},"multi-server-no-significa-alta-disponibilidad-real","\"Multi-server\" no significa \"alta disponibilidad real\"",[12,30187,30188],{},"La confusión más cara. La mayoría de los paneles lista \"multi-server\" como feature, y el lector casual interpreta eso como \"si un servidor se cae, el sistema sigue funcionando\". No es lo que está siendo ofrecido. Multi-server en la mayoría de los paneles significa: el panel central, ejecutando en un servidor único, es capaz de hacer deploy en varios servidores remotos.",[12,30190,30191],{},"Cuando el servidor del panel se cae, pierdes control. Los containers en producción siguen ejecutando — Docker no para por causa de eso — pero ya no logras hacer deploy, leer logs centralizados, reiniciar servicio, escalar. Quedas esperando volver.",[12,30193,30194],{},"Alta disponibilidad real exige consenso entre múltiples servidores: al menos tres procesos del panel ejecutando, elección automática de coordinador, replicación del estado entre ellos. Si el coordinador se cae, otro asume en segundos. Esa es una arquitectura diferente, más cara de construir y más cara de operar. Por eso pocos productos del segmento entregan.",[12,30196,30197],{},"La pregunta concreta para hacer al evaluar cualquier producto: \"si el servidor donde ejecuta el panel fuera apagado ahora, ¿en cuánto tiempo el sistema vuelve a aceptar deploys, y esa vuelta es automática o manual?\". Si la respuesta involucra a un humano abriendo SSH en algún lugar, no es alta disponibilidad.",[368,30199,30201],{"id":30200},"plugin-ecosystem-puede-ser-dependencia-disfrazada","\"Plugin ecosystem\" puede ser dependencia disfrazada",[12,30203,30204],{},"Los paneles con tienda de plugins parecen completos: instalas un plugin para tener Postgres gestionado, otro para Redis, otro para Sentry-like, otro para backup automático, otro para monitoreo. Cada uno resuelve un pedazo, y el conjunto suma un Heroku.",[12,30206,30207],{},"El problema aparece dos años después. El plugin de backup fue escrito por un voluntario en 2024 y paró de recibir commits en 2025. La versión nueva del panel rompió compatibilidad con él y nadie actualizó. Lo descubres en la hora que necesitas restaurar un backup — y la restauración nunca fue testeada con la versión actual.",[12,30209,30210],{},"Ese patrón se repite para cada plugin. Cuanto más funcionalidades dependan del ecosistema externo, mayor la superficie de riesgo. La defensa estructural es simple: da preferencia a productos con batería incluida — donde Postgres, métricas, logs, certificados, enrutamiento son parte del producto principal y mantenidos por el mismo equipo que mantiene el resto. Plugin es cómodo en el corto plazo y costoso en el medio.",[368,30212,30214],{"id":30213},"free-tier-del-hospedado-no-es-gratuito-largo-plazo","\"Free tier\" del hospedado no es gratuito largo plazo",[12,30216,30217],{},"Render, Railway, Fly.io tienen planes gratuitos generosos hoy. Heroku tenía en 2021. La historia del segmento muestra un patrón consistente: free tiers de empresas privadas pisan más cada ronda de levantamiento de capital. Primero suspende por inactividad, después reduce cota, después añade límite de horas, después transforma en trial de treinta días, después encierra.",[12,30219,30220],{},"No es maldad — es matemática de negocio. Hospedar workload cuesta dinero, y el inversor cobra retorno. La única excepción estructural es hospedaje subsidiado por otro producto de la misma empresa (cloud cubriendo PaaS gratuita para atraer desarrolladores al cloud principal), e incluso esas cambian cuando cambia el CFO.",[12,30222,30223],{},"Auto-hospedado es la única defensa estructural. Pagas la cuenta del VPS directo al proveedor de infraestructura, sin intermediario. Cuando el intermediario desaparece, tu aplicación no desaparece junto.",[19,30225,30227],{"id":30226},"cuando-quedarse-en-heroku-render-o-railway-sin-ironia","Cuándo quedarse en Heroku, Render o Railway sin ironía",[12,30229,30230],{},"Vale la pena decir con claridad: no todo equipo necesita salir de hospedaje gestionado. Hay tres situaciones en las que quedarse es la decisión correcta.",[12,30232,30233,30236],{},[27,30234,30235],{},"Equipo pequeño sin competencia operacional disponible para cuidar de servidor."," Si la equipa entera son dos desarrolladores de producto, ninguno con experiencia previa en Linux\u002FDocker\u002Fnetworking, el coste cognitivo de operar infraestructura es mayor que la economía mensual. Paga los US$200\u002Fmes de Render y mantén foco en producto.",[12,30238,30239,30242],{},[27,30240,30241],{},"Aplicación cuyo coste de plataforma es despreciable comparado al revenue."," Si la empresa factura US$50k\u002Fmes y la cuenta de Heroku es US$300, optimizar esa cuenta es trabajo mal alocado. El retorno marginal de migrar es bajo, y el riesgo operacional no compensa.",[12,30244,30245,30248],{},[27,30246,30247],{},"Equipo alocado en producto, no en infra."," Algunas startups son tan dependientes de iteración rápida en producto que cualquier hora gastada en infra es hora robada del diferencial competitivo. Para esas, el trade-off de pagar a más para no pensar en servidor es valor real, no desperdicio.",[12,30250,30251],{},"La regla simple: si la infra es commodity invisible para tu negocio, deja que alguien cobre por ser invisible para ti. Si la infra es capacidad que diferencia el producto (latencia baja, regiones específicas, compliance específico, uptime contractual), el control compensa el trabajo.",[19,30253,30255],{"id":30254},"heroctl-en-el-segmento","HeroCtl en el segmento",[12,30257,30258],{},"Posicionamiento honesto: HeroCtl no compite con Dokku o Coolify en el caso de hobby project en un VPS. Para ese caso, es más máquina de la que necesitas. Un indie hacker con una aplicación Django en un servidor de US$5\u002Fmes debe usar Dokku o Coolify y seguir el día.",[12,30260,30261],{},"Donde HeroCtl compite es donde Coolify multi-server, Dokploy y Nomad también compiten: el caso de cliente serio con SLA, en que single-server se vuelve pasivo legal. Aquí la diferencia que ofrecemos es cluster con consenso desde el primer día, batería incluida en lugar de cinco productos para montar (router, certificados, métricas, logs y criptografía entre servicios ya en el binario), y contrato comercial publicado y congelado — sin cambio retroactivo de términos.",[12,30263,30264],{},"El cluster de demostración ejecuta cuatro servidores totalizando cinco vCPUs y diez gigabytes de RAM, con dieciséis containers activos sirviendo cinco sitios. El plano de control ocupa entre 200 y 400 MB por servidor. Comparativamente, el plano de control de una versión gestionada del orquestador grande empieza en alrededor de 700 MB por nodo-maestro antes de que cualquier aplicación suba.",[12,30266,30267],{},"El job spec típico tiene alrededor de cincuenta líneas — describe servicio, ingress, secretos, recursos. El equivalente en el orquestador grande pasa de trescientas líneas para cubrir la misma funcionalidad.",[12,30269,30270],{},"HeroCtl no compite con cloud gestionado en escala de cien nodos o más. La franja ideal es uno a quinientos servidores. Por encima de eso, el ecosistema externo de operadores especializados aún da ventaja al orquestador grande, y ser honesto sobre eso es parte del contrato.",[19,30272,7352],{"id":7351},[12,30274,30275,30278],{},[27,30276,30277],{},"¿Puedo migrar de Heroku directo a HeroCtl?","\nSí, con algunas adaptaciones. Aplicación web stateless con Postgres separado migra fácil — la containerizas con Dockerfile, describes el job en cincuenta líneas, subes. Workers separados (Sidekiq, Celery) se vuelven jobs adicionales en el mismo cluster. Lo que necesita ser repensado es lo que dependía de add-ons gestionados.",[12,30280,30281,30284],{},[27,30282,30283],{},"¿Y los add-ons (Postgres, Redis, Sentry)?","\nPostgres lo ejecutas como job en el propio cluster, con volume persistente, y cuidas de backup como humano cuida — no hay operador automático que haga eso mejor que tú haciéndolo bien hecho. Redis idem. Sentry self-hosted existe y ejecuta en cualquier cluster Docker — y hay producto comercial hospedado si prefieres no operar. La regla general: datos críticos ejecutan en el cluster, observabilidad puede ejecutar fuera.",[12,30286,30287,30290],{},[27,30288,30289],{},"¿Cuánto cuesta en comparación?","\nTomando como base una startup con cinco aplicaciones pequeñas: Heroku-pago sale alrededor de US$125\u002Fmes mínimo, sin add-ons. Render sale entre US$50 y US$150 dependiendo del uso. Cluster propio en VPS de tres nodos sale US$30 a US$60\u002Fmes total en el proveedor de infraestructura. La economía directa es real, y se vuelve más expresiva conforme las aplicaciones crecen.",[12,30292,30293,30296],{},[27,30294,30295],{},"¿Y si ya estoy en Coolify?","\nNo hay urgencia de migrar mientras operas con un único servidor. La hora de considerar es cuando el panel single-server se vuelve punto único de fallo contractual — primer cliente serio con SLA escrito. Hasta entonces, Coolify funciona bien.",[12,30298,30299,30302],{},[27,30300,30301],{},"¿Y para una app Django con Celery, o Rails con Sidekiq?","\nFunciona naturalmente. Defines un job para el proceso web y otro job para el proceso de worker, ambos compartiendo la misma imagen pero con comandos diferentes. El cluster orquesta los dos independientemente, y el broker (Redis o similar) es un job más en el mismo cluster.",[12,30304,30305,30308],{},[27,30306,30307],{},"¿Y para una app Node.js con workers separados?","\nMisma historia. Worker es solo otro proceso, definido como otro job. No hay distinción arquitectural entre \"web\" y \"worker\" en el nivel del orquestador — son containers que ejecutan código.",[12,30310,30311,30314],{},[27,30312,30313],{},"¿Los precios de Business salen cuándo?","\nLa página de planes publica los valores. La línea de corte está dibujada para que solo pagues Business cuando la empresa sea grande lo suficiente para que SSO, RBAC granular y auditoría detallada sean exigencias reales — no preferencia. Para todo el resto, Community resuelve, y Community es gratuito permanente sin feature gate artificial.",[19,30316,3310],{"id":3309},[12,30318,30319],{},"El segmento de \"Heroku auto-hospedado\" maduró. En 2026, hay productos serios para cada perfil de uso, y la decisión depende menos de \"cuál es el mejor\" y más de \"cuál cabe en mi caso\". Hobby project no necesita cluster con consenso. Cliente serio con SLA no cabe en panel single-server.",[12,30321,30322],{},"Para quien está decidiendo ahora, tres recomendaciones finales. Primero, lee el contrato comercial antes de adoptar — huye de términos que permitan cambio retroactivo. Segundo, prefiere batería incluida a ecosistemas de plugins donde sea posible — superficie de riesgo menor. Tercero, prueba el camino de fallo antes del incidente real — apaga un servidor y mira lo que sucede, con calma, durante el día.",[12,30324,30325],{},"Para empezar con HeroCtl en tres servidores Linux:",[224,30327,30329],{"className":30328,"code":5318,"language":2530},[2528],[231,30330,5318],{"__ignoreMap":229},[12,30332,30333,30334,30336,30337,30339],{},"Si quieres leer más antes, hay dos posts adyacentes: ",[3337,30335,16705],{"href":16704}," explica la comparación directa con el líder de mindshare del segmento single-server, y ",[3337,30338,21746],{"href":6545}," explica el raciocinio que llevó a la existencia del producto.",[12,30341,30342],{},"Orquestación de containers, sin ceremonia.",{"title":229,"searchDepth":244,"depth":244,"links":30344},[30345,30346,30353,30354,30355,30360,30361,30362,30363],{"id":29778,"depth":244,"text":29779},{"id":29818,"depth":244,"text":29819,"children":30347},[30348,30349,30350,30351,30352],{"id":29822,"depth":271,"text":29823},{"id":29849,"depth":271,"text":29850},{"id":29874,"depth":271,"text":29875},{"id":29888,"depth":271,"text":29889},{"id":29913,"depth":271,"text":29914},{"id":17388,"depth":244,"text":17389},{"id":30149,"depth":244,"text":30150},{"id":30180,"depth":244,"text":30181,"children":30356},[30357,30358,30359],{"id":30184,"depth":271,"text":30185},{"id":30200,"depth":271,"text":30201},{"id":30213,"depth":271,"text":30214},{"id":30226,"depth":244,"text":30227},{"id":30254,"depth":244,"text":30255},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2025-11-19","Desde que Salesforce mató el plan gratuito de Heroku en noviembre\u002F2022, surgieron decenas de alternativas auto-hospedadas. Mapa honesto del segmento y cómo elegir.",{},{"title":29764,"description":30365},{"loc":19773},"es\u002Fblog\u002Fheroku-auto-hospedado-2026",[20512,22492,24194,8775,30371],"segmento","J5M3m2d92QlrguvxnAMs21frRlJR445Q660-rbfHvOs",{"id":30374,"title":15791,"author":7,"body":30375,"category":3379,"cover":3380,"date":31039,"description":31040,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":31041,"navigation":411,"path":15790,"readingTime":3387,"seo":31042,"sitemap":31043,"stem":31044,"tags":31045,"__hash__":31048},"blog_es\u002Fes\u002Fblog\u002Fkubernetes-overkill-cuando-no-lo-necesitas.md",{"type":9,"value":30376,"toc":31026},[30377,30380,30383,30386,30390,30393,30400,30403,30406,30409,30411,30417,30428,30431,30436,30439,30446,30449,30456,30463,30466,30469,30471,30474,30481,30488,30504,30511,30514,30517,30521,30524,30562,30565,30568,30572,30575,30613,30620,30626,30632,30636,30639,30656,30662,30665,30668,30675,30678,30682,30685,30832,30835,30839,30842,30845,30855,30862,30868,30891,30895,30898,30930,30933,30935,30941,30947,30953,30959,30965,30979,30985,30987,30990,30993,30996,31012,31015,31021,31024],[12,30378,30379],{},"La pregunta correcta en 2026 no es \"¿Kubernetes es bueno?\". Ese debate terminó — sí, lo es. La pregunta correcta es otra, y casi ningún CTO de startup la hace en voz alta: \"¿necesito esto para lo que estoy construyendo?\".",[12,30381,30382],{},"Para la mayoría de los equipos que están decidiendo arquitectura ahora, la respuesta honesta es no. Pero el sistema de incentivos de la industria empuja en la dirección contraria. Reclutadores filtran currículum por palabra clave. Conferencias premian a quien muestra YAML en proyector. Inversor de Serie A pregunta \"¿están en K8s?\" como si fuera sello de seriedad. El resultado colectivo es una capa gigante de complejidad adoptada por equipos que no tenían el problema que esa complejidad resuelve.",[12,30384,30385],{},"Este post es la defensa explícita del \"no lo necesitas\", con la cuenta en la mano. No es sobre Kubernetes ser malo — es sobre elegir la herramienta correcta para el tamaño real del problema que tienes hoy, y no para la foto que quieres proyectar.",[19,30387,30389],{"id":30388},"la-seduccion-es-real-y-tiene-nombre","La seducción es real (y tiene nombre)",[12,30391,30392],{},"La primera cosa a admitir es que la adopción excesiva de Kubernetes no es irracional. Tiene todo sentido — para el individuo. El nombre de la fuerza que opera aquí es resume-driven development.",[12,30394,30395,30396,30399],{},"Ingeniero de plataforma que aprende Kubernetes gana, en promedio, ",[27,30397,30398],{},"30% más"," en el siguiente empleo. Es la habilidad técnica con mayor premio salarial en listados de vacante en 2026 entre todo lo que involucra operación. Quien pone \"operó cluster multi-region en producción\" en LinkedIn tiene treinta reclutadores en la semana. Quien pone \"operó panel auto-hospedado en tres servidores\" tiene dos.",[12,30401,30402],{},"Para el ingeniero, es racional aprender Kubernetes incluso cuando el trabajo no lo pide. Para el CTO, es racional adoptar Kubernetes incluso cuando el producto no lo pide — señaliza al mercado que la empresa \"está lista para escalar\", que es el vocabulario que el inversor entiende. Para el equipo de plataforma, es racional sugerir Kubernetes en cualquier proyecto nuevo — garantiza relevancia en los próximos cinco años.",[12,30404,30405],{},"Cada uno de esos cálculos individuales es defendible. El agregado es desastroso. La empresa paga la cuenta de una decisión que nadie tomó pensando en la empresa.",[12,30407,30408],{},"El punto de partida de este post es asumir esa tensión. Tú, leyendo, tal vez estés siendo presionado por una de las tres fuerzas arriba. Reconocer la presión es el primer paso para decidir con base en el problema real, no en el incentivo de quien te está aconsejando.",[19,30410,16852],{"id":16851},[12,30412,30413,30414,101],{},"Vamos a poner números. Reales, brasileños, en 2026. Para la versión de esa cuenta con la lente brasileña completa — cambio, LGPD, hospedaje nacional — hay un post específico en ",[3337,30415,30416],{"href":14883},"Alternativa a Kubernetes en 2026: PaaS auto-hospedado",[12,30418,30419,30420,30423,30424,30427],{},"Ingeniero de plataforma sénior en São Paulo o Florianópolis, capaz de operar Kubernetes en producción sin supervisión, cuesta hoy entre ",[27,30421,30422],{},"R$25 mil y R$40 mil al mes en CLT",", o entre ",[27,30425,30426],{},"US$8 mil y US$12 mil al mes en PJ",". Vamos a usar R$30 mil como promedio conservador — es el salario que consigues cerrar con alguien competente que todavía no alcanzó el techo de mercado.",[12,30429,30430],{},"Pero R$30 mil es solo una persona. Cluster en producción necesita guardia 24×7. La ley laboral brasileña no permite que una única persona cargue guardia indefinida — y aunque lo permitiera, la salud mental del operador único colapsa en seis meses. Necesitas como mínimo dos personas turnándose, con descanso real entre escalas.",[12,30432,30433],{},[27,30434,30435],{},"R$30 mil × 2 personas × 12 meses = R$720 mil al año solo en nómina.",[12,30437,30438],{},"Sobre esa nómina, agrega cargas (CLT corre en torno de 70-100% por encima del salario base; PJ varía pero generalmente queda en 30-40% si quieres tratar a la persona decentemente). Y sobre eso, costos reales de un equipo de plataforma: licencias de herramientas auxiliares, capacitación, certificaciones que el mercado pide, conferencias, eventual contratación de consultoría puntual cuando algo se rompe de un modo que nadie de la casa vio antes.",[12,30440,30441,30442,30445],{},"En la infraestructura propiamente, la cuenta tampoco es barata. Versión gestionada del coloso (EKS, GKE, AKS) cobra cerca de ",[27,30443,30444],{},"US$73 al mes por cluster"," solo por el plano de control — eso son unos R$370 al mes. Sobre eso entra NAT Gateway (US$40 al mes mínimo), Application Load Balancer (US$25 al mes mínimo), tráfico de salida cobrado por gigabyte, snapshots de disco, costos de observabilidad que crecen con el número de pods y métricas exportadas.",[12,30447,30448],{},"Empresas serias corren al menos dos ambientes (staging y producción), y muchas tienen un tercer ambiente de desarrollo u homologación dedicado. Multiplica.",[12,30450,30451,30452,30455],{},"Estimación total año 1, con dos ingenieros de plataforma y dos ambientes gestionados: ",[27,30453,30454],{},"entre R$770 mil y R$800 mil",". Eso antes del primer cliente serio, antes del primer real de ingreso recurrente, antes de la segunda contratación de producto.",[12,30457,30458,30459,30462],{},"Haz la comparación inversa. Un equipo de tres desarrolladores full-stack a R$15 mil cada uno: ",[27,30460,30461],{},"R$540 mil al año",". Con cargas, digamos R$720 mil. Es exactamente la misma franja.",[12,30464,30465],{},"La pregunta concreta es esa: ¿prefieres tener tres personas más shippando código que el cliente va a usar, o prefieres tener dos personas manteniendo plataforma que el cliente nunca va a ver?",[12,30467,30468],{},"No hay respuesta universal. Pero casi siempre, en la etapa en que esa decisión es tomada — empresa pre-Serie A, equipo de cinco a quince personas, producto buscando product-market fit — la respuesta correcta es shippar producto.",[19,30470,17177],{"id":17176},[12,30472,30473],{},"Dinero capturas o ahorras. Tiempo no recuperas. La cuenta de tiempo pesa más que la cuenta de R$.",[12,30475,30476,30477,30480],{},"Setup de Kubernetes gestionado para producción mínimamente decente lleva ",[27,30478,30479],{},"2 a 4 semanas",". No es instalar el cluster — eso son minutos. Es configurar el ingress controller, el emisor de certificados, el stack de monitoreo (en general tres productos coordinados), el sistema de logs centralizado, backup automático de los volúmenes persistentes, alertas, política de red entre pods, segregación de namespaces. Cada componente tiene cinco elecciones legítimas y tres trampas conocidas.",[12,30482,30483,30484,30487],{},"Primer deploy de aplicación real después de eso: más ",[27,30485,30486],{},"una semana",". Manifiestos para la aplicación, manifiestos para los componentes auxiliares, definición de probes de salud (liveness, readiness, startup), ajuste de recursos solicitados versus límites, pruebas de carga para calibrar autoscaling, pruebas de falla para calibrar política de reinicio.",[12,30489,30490,30491,30494,30495,30497,30498,30501,30502,101],{},"Cada feature nueva de plataforma después de eso se vuelve proyecto. Secretos rotados automáticamente: ",[27,30492,30493],{},"una a dos semanas",". Métricas customizadas integradas al panel: ",[27,30496,30486],{},". Malla de comunicación entre servicios con observabilidad punta a punta: ",[27,30499,30500],{},"dos a tres semanas",", y eso si eliges una de las opciones estables de entrada. Política de red granular por namespace con auditoría: ",[27,30503,30486],{},[12,30505,30506,30507,30510],{},"Gastas los primeros ",[27,30508,30509],{},"seis meses"," montando plataforma. Ese es el escenario optimista, con gente competente y sin grandes incidentes.",[12,30512,30513],{},"Mientras tanto, el competidor más pequeño que eligió un stack más simple está shippando features. Cuando terminas la \"plataforma mínimamente decente\", él ya tiene tres features que no tienes, ocho clientes que tomaron decisión de compra con base en esas features, y un ciclo de feedback corriendo que va a componer las próximas features de él con más precisión.",[12,30515,30516],{},"En mercados donde el ganador es decidido en los primeros doce meses — casi todo mercado de SaaS B2B — ese atraso es fatal. Puedes tener la infraestructura más robusta del segmento y perder el segmento entero porque llegaste tres meses tarde con la feature que importa.",[19,30518,30520],{"id":30519},"el-perfil-que-no-necesita-kubernetes","El perfil que NO necesita Kubernetes",[12,30522,30523],{},"Aquí mora la mayoría de los equipos que están decidiendo eso en 2026. Si encajas en todos los criterios abajo, Kubernetes es overkill — casi con certeza:",[2735,30525,30526,30532,30538,30544,30550,30556],{},[70,30527,30528,30531],{},[27,30529,30530],{},"Equipo de 1 a 15 ingenieros."," No tienes cómo dedicar dos personas solo a plataforma sin comprometer 15-30% de la capacidad de entrega.",[70,30533,30534,30537],{},[27,30535,30536],{},"1 a 50 servidores totales en producción."," En ese tamaño, abstracciones simples todavía funcionan. Logras listar todos los servidores en una página.",[70,30539,30540,30543],{},[27,30541,30542],{},"1 a 100 servicios o aplicaciones distintas."," El ecosistema del coloso brilla cuando tienes miles de microservicios con dependencias cruzadas. Por debajo de 100, la complejidad del orquestador es mayor que la complejidad del sistema que orquesta.",[70,30545,30546,30549],{},[27,30547,30548],{},"Tráfico previsible."," No tiene pico de 100× en 30 segundos. Si tu carga oscila dos o tres veces entre el valle y el pico a lo largo del día, no necesitas autoscaling milimétrico.",[70,30551,30552,30555],{},[27,30553,30554],{},"Workloads HTTP\u002Fweb típicos."," Aplicación web, API REST, worker de cola, base gestionada. Sin necesidades exóticas como GPU sharding, ML inference a gran escala, procesamiento batch petabyte por noche.",[70,30557,30558,30561],{},[27,30559,30560],{},"Operación en 1 a 3 regiones cloud."," Atiendes un país, o como máximo dos continentes cercanos. No estás orquestando workloads que migran entre cinco datacenters en tiempo real.",[12,30563,30564],{},"Esa es la abrumadora mayoría de los equipos que adoptan Kubernetes hoy. Encajan en los seis criterios y aun así eligieron la herramienta diseñada para resolver el opuesto de cada criterio.",[12,30566,30567],{},"Si te reconoces aquí, la próxima sección puede ser incómoda — pero lee hasta el final antes de descartar.",[19,30569,30571],{"id":30570},"el-perfil-que-necesita-kubernetes","El perfil que NECESITA Kubernetes",[12,30573,30574],{},"Para no caer en \"Kubernetes nunca sirve\", aquí está el lado honesto. Esos son los perfiles en que adoptar el coloso es la elección correcta, no overkill:",[2735,30576,30577,30583,30589,30595,30601,30607],{},[70,30578,30579,30582],{},[27,30580,30581],{},"SaaS multi-tenant con aislamiento por namespace, con requisitos de cuota de recursos, política de red granular, y auditoría por inquilino."," Bancos, fintechs reguladas, plataformas que venden hosting a otros desarrolladores. El modelo de namespaces del coloso es el mejor primitivo disponible para ese problema.",[70,30584,30585,30588],{},[27,30586,30587],{},"Operación real multi-region con workloads moviéndose entre datacenters en respuesta a falla o demanda."," No es \"tengo réplicas en dos regiones para DR\". Es \"muevo cargas de trabajo activas entre cuatro regiones con gestión automática de estado y latencia\". Empresa muy grande, con mucho dinero.",[70,30590,30591,30594],{},[27,30592,30593],{},"Dependencia de operadores especializados maduros que valen el overhead."," Postgres con replicación automática, Kafka con balanceo continuo, Cassandra con bootstrap orquestado, Spark en batch. Si tu arquitectura tiene tres o más de esos componentes operados por automatización especializada, el ecosistema del coloso es el lugar donde esa automatización maduró.",[70,30596,30597,30600],{},[27,30598,30599],{},"Equipo de plataforma de cinco o más personas dedicadas."," Tienes capacidad humana real para mantener el sistema sin comprometer entrega de producto. No es una persona haciendo \"también\" plataforma; es un departamento.",[70,30602,30603,30606],{},[27,30604,30605],{},"Compliance que exige nombres de herramientas pre-aprobadas."," FedRAMP, ITAR, algunos contratos de gobierno, algunos frameworks de salud en EE. UU. Si tu auditor necesita apuntar a un certificado existente en una lista, el coloso está en esa lista. Otras alternativas, en general, todavía no.",[70,30608,30609,30612],{},[27,30610,30611],{},"Escala de cientos a miles de nodos."," Por encima de 500 servidores sales del rango donde alternativas más simples brillan y entras en el rango donde el coloso fue proyectado para trabajar. No hay sustituto serio aquí.",[12,30614,30615,30616,30619],{},"Si tienes ",[27,30617,30618],{},"tres o más"," de esos, Kubernetes es la elección correcta, no overkill. Adopta sin culpa, contrata el equipo, gasta el dinero — está alineado.",[12,30621,30615,30622,30625],{},[27,30623,30624],{},"uno o dos",", presta atención: probablemente se puede resolver con algo más simple y migrar después, si de hecho escala hasta necesitar más. Evalúa con calma.",[12,30627,30615,30628,30631],{},[27,30629,30630],{},"cero",", cualquier adopción de Kubernetes es decisión de currículum, no de producto. Sé honesto con el equipo y contigo mismo.",[19,30633,30635],{"id":30634},"la-zona-gris-donde-mora-el-error-mas-comun","La zona gris — donde mora el error más común",[12,30637,30638],{},"Existe una franja intermedia donde la decisión es más difícil, y es donde el error más común sucede. Vamos a describirla con precisión:",[2735,30640,30641,30644,30647,30650,30653],{},[70,30642,30643],{},"Equipo de 5 a 15 ingenieros",[70,30645,30646],{},"5 a 20 servidores",[70,30648,30649],{},"10 a 50 servicios o aplicaciones",[70,30651,30652],{},"1 o 2 regiones cloud",[70,30654,30655],{},"Crecimiento esperado pero no explosivo (digamos, duplicar de tamaño en 18 meses)",[12,30657,30658,30659,101],{},"Aquí mora el 70% de los equipos de SaaS pre-Serie B en Brasil en 2026. Y aquí mora la frase fatal: ",[27,30660,30661],{},"\"vamos a crecer rápido entonces mejor ya empezar con Kubernetes\"",[12,30663,30664],{},"La falacia es doble. Primera: no vas a crecer 100× en seis meses. Crecimiento real de SaaS exitoso queda entre 2× y 5× al año en los primeros tres años. Tienes tiempo de migrar si de hecho lo necesitas.",[12,30666,30667],{},"Segunda, y más importante: el stack que eliges para un equipo de cinco personas raramente es el stack que vas a correr con cincuenta. Las prioridades cambian, los requisitos cambian, los trade-offs cambian. Empresas que escalaron de cinco a cincuenta personas y mantuvieron el mismo stack son excepción, no regla. Vas a migrar de cualquier forma — solo la pregunta es cuándo, y qué vas a tener shippado hasta ahí.",[12,30669,30670,30671,30674],{},"La heurística correcta es: ",[27,30672,30673],{},"optimiza para hoy + 18 meses, no para hipótesis de 5 años",". Si en los próximos 18 meses tu infra no va a exigir Kubernetes, no lo adoptes ahora. Cuando el problema aparezca, tendrás ingresos para contratar al equipo que opera, y claridad sobre los requisitos reales (que serán diferentes a lo que imaginas hoy).",[12,30676,30677],{},"La ingeniería que envejece bien es la que resuelve el problema actual con holgura, no la que intenta anticipar todos los problemas hipotéticos.",[19,30679,30681],{"id":30680},"lo-que-ganas-en-cada-camino","Lo que ganas en cada camino",[12,30683,30684],{},"Para organizar la decisión, tres caminos lado a lado en diez criterios. Las notas son honestas — todo camino tiene reservas.",[119,30686,30687,30701],{},[122,30688,30689],{},[125,30690,30691,30693,30696,30699],{},[128,30692,2983],{},[128,30694,30695],{},"K8s gestionado",[128,30697,30698],{},"Panel auto-hospedado simple",[128,30700,2995],{},[141,30702,30703,30717,30731,30743,30757,30769,30781,30794,30805,30819],{},[125,30704,30705,30708,30711,30714],{},[146,30706,30707],{},"Costo de plataforma año 1 (R$)",[146,30709,30710],{},"700-800k",[146,30712,30713],{},"40-80k (1 dev part-time)",[146,30715,30716],{},"60-120k (1 dev part-time + plan)",[125,30718,30719,30722,30725,30728],{},[146,30720,30721],{},"Tiempo hasta primera app en producción",[146,30723,30724],{},"2-4 semanas",[146,30726,30727],{},"5 minutos a 1 día",[146,30729,30730],{},"5 minutos a 1 hora",[125,30732,30733,30736,30739,30741],{},[146,30734,30735],{},"Equipo mínimo dedicado",[146,30737,30738],{},"2 SREs en guardia",[146,30740,22214],{},[146,30742,22214],{},[125,30744,30745,30748,30751,30754],{},[146,30746,30747],{},"Alta disponibilidad real (sobrevive a caída de servidor)",[146,30749,30750],{},"Sí, con 5+ componentes coordinados",[146,30752,30753],{},"No (servidor único)",[146,30755,30756],{},"Sí, embebida",[125,30758,30759,30762,30764,30766],{},[146,30760,30761],{},"Escala máxima validada en producción",[146,30763,23373],{},[146,30765,30128],{},[146,30767,30768],{},"Cientos de nodos",[125,30770,30771,30774,30777,30779],{},[146,30772,30773],{},"Router HTTP + certificados automáticos",[146,30775,30776],{},"Operador externo (instala separado)",[146,30778,23300],{},[146,30780,23300],{},[125,30782,30783,30786,30789,30792],{},[146,30784,30785],{},"Métricas con retención razonable",[146,30787,30788],{},"Stack externa (3+ productos)",[146,30790,30791],{},"Plugin opcional",[146,30793,25646],{},[125,30795,30796,30798,30801,30803],{},[146,30797,22806],{},[146,30799,30800],{},"Stack externa (2+ productos)",[146,30802,30791],{},[146,30804,22329],{},[125,30806,30807,30810,30813,30816],{},[146,30808,30809],{},"Secretos cifrados en reposo",[146,30811,30812],{},"Componente externo o bóveda dedicada",[146,30814,30815],{},"Variable de ambiente",[146,30817,30818],{},"Embebido en el plano de control",[125,30820,30821,30824,30827,30829],{},[146,30822,30823],{},"Rolling update seguro",[146,30825,30826],{},"Sí (configuras tú mismo)",[146,30828,3062],{},[146,30830,30831],{},"Embebido con health check",[12,30833,30834],{},"La columna del medio resuelve el caso \"un servidor, sin presión de SLA\" — y resuelve bien. La columna de la izquierda resuelve \"cientos de nodos, equipo dedicado, requisitos complejos\" — y resuelve bien. La columna de la derecha resuelve la franja entre los dos extremos, que es donde la mayoría de los equipos de SaaS vive hoy en Brasil.",[19,30836,30838],{"id":30837},"heroctl-como-el-medio-termino-honesto","HeroCtl como el medio término honesto",[12,30840,30841],{},"Para ser directo contigo: este blog es del HeroCtl, y el pitch existe. Pero solo tiene sentido para quien encaja.",[12,30843,30844],{},"HeroCtl preserva el modelo operacional de los paneles auto-hospedados simples — un archivo ejecutable, instala en servidores Linux, gestiona todo desde un panel embebido. La curva de aprendizaje es de horas, no de semanas. No necesitas aprender vocabulario nuevo, conceptos abstractos, herramientas adyacentes obligatorias. Subes la aplicación, abres el panel, ves lo que está corriendo.",[12,30846,30847,30848,30851,30852,30854],{},"Pero, diferente de los paneles simples, HeroCtl corre como cluster replicado de verdad desde el día uno. Tres servidores o más y el plano de control sobrevive a la caída de cualquiera de ellos, sin intervención manual. La elección de coordinador ocurre en ",[27,30849,30850],{},"cerca de 7 segundos"," después de una caída dura — probado en laboratorio con ",[231,30853,23217],{}," repetido. Respondes \"¿cuál es el SLA?\" al primer cliente serio con la cara limpia.",[12,30856,30857,30858,30861],{},"Y sin la complejidad del coloso. Sin manifiestos de 300 líneas — el equivalente en HeroCtl corre en ",[27,30859,30860],{},"cerca de 50 líneas",". Sin operadores especializados para cada subsistema — router, certificados, métricas y logs vienen embebidos. Sin montar tres productos de observabilidad — el stack público vive dentro del propio cluster.",[12,30863,30864,30865,30867],{},"Rango de aplicación práctico: ",[27,30866,22834],{},". Por encima de eso, el ecosistema del coloso te da herramientas que todavía no tenemos, y somos honestos sobre eso. Por debajo de eso, la economía operacional es grande — generalmente cambia dos ingenieros de plataforma en guardia por un desarrollador part-time gestionando el stack entero.",[12,30869,30870,30871,30874,30875,30878,30879,30882,30883,30886,30887,30890],{},"Los números del cluster público para calibrar expectativa: ",[27,30872,30873],{},"4 servidores totalizando 5 vCPUs y 10 GB de RAM",", corriendo ",[27,30876,30877],{},"16 contenedores"," que sirven ",[27,30880,30881],{},"5 sitios distintos"," con TLS automático. El plano de control ocupa ",[27,30884,30885],{},"entre 200 y 400 MB por servidor",". Comparativamente, el plano de control de una versión gestionada del coloso parte de cerca de ",[27,30888,30889],{},"700 MB por nodo-maestro"," antes de que cualquier aplicación suba.",[19,30892,30894],{"id":30893},"decision-practica-arbol-de-decision","Decisión práctica (árbol de decisión)",[12,30896,30897],{},"Para quien necesita una respuesta hoy, sin leer el post entero de nuevo:",[67,30899,30900,30906,30912,30918,30924],{},[70,30901,30902,30905],{},[27,30903,30904],{},"¿Tienes equipo de plataforma dedicado de 3 o más personas, hoy, contratadas?"," Si sí → Kubernetes es viable. Si no → sigue.",[70,30907,30908,30911],{},[27,30909,30910],{},"¿Tienes requisito formal de compliance que lista Kubernetes nominalmente?"," Si sí → Kubernetes es obligatorio. Si no → sigue.",[70,30913,30914,30917],{},[27,30915,30916],{},"¿Operas 100 o más servidores en producción, hoy?"," Si sí → Kubernetes o un orquestador equivalente es la elección correcta. Si no → sigue.",[70,30919,30920,30923],{},[27,30921,30922],{},"¿Tienes un único servidor y cero presión de SLA?"," Si sí → panel auto-hospedado simple resuelve. Si no → sigue.",[70,30925,30926,30929],{},[27,30927,30928],{},"¿Estás entre 2 y 500 servidores, con requisito de SLA real, y quieres evitar la cuenta de la plataforma del coloso?"," → HeroCtl es el medio término honesto.",[12,30931,30932],{},"Casi todo equipo de SaaS pre-Serie B en Brasil en 2026 cae en el caso 5. Quien cae en el caso 1 o 3 ya lo sabe y probablemente no está leyendo este post. Quien cae en el caso 2 tiene regulación dictando.",[19,30934,7352],{"id":7351},[12,30936,30937,30940],{},[27,30938,30939],{},"¿Y si crezco y necesito el coloso después?","\nCrece primero. Migra después. Migración de 50 servidores corriendo HeroCtl a Kubernetes es un proyecto de un trimestre con equipo pequeño — bastante más barato que cargar plataforma del coloso por dos años sin necesitar. Y cuando de hecho lo necesites, tendrás ingresos para contratar a quien opera.",[12,30942,30943,30946],{},[27,30944,30945],{},"¿Puedo usar Kubernetes solo para parte del stack?","\nPuedes, y a veces tiene sentido. Workload específico que se beneficia de operador especializado maduro (Spark batch, ML inference de gran escala) puede correr en cluster del coloso dedicado, mientras el resto del producto corre en algo más simple. El costo es mantener dos modelos operacionales — vale si el subconjunto aislado realmente compensa.",[12,30948,30949,30952],{},[27,30950,30951],{},"¿Y si mi cliente exige Kubernetes contractualmente?","\nAhí Kubernetes se vuelve requisito de venta, no decisión de arquitectura. Si el ingreso lo justifica, adopta para el contrato en cuestión. Pero exige el ítem por escrito — muchas veces el cliente \"exige Kubernetes\" porque el equipo técnico de él asumió, sin que nadie haya escrito en una cláusula. Vale revisar.",[12,30954,30955,30958],{},[27,30956,30957],{},"¿Y si ya invertí 2 años aprendiendo Kubernetes?","\nEl conocimiento no se pierde. Kubernetes va a seguir relevante por décadas — es la infraestructura estándar de empresas grandes, y empresas grandes no desaparecen. Tienes capital intelectual aplicable cuando la empresa crezca, o cuando cambies de empleo a una que de hecho lo necesite. La elección de no usarlo ahora no invalida el aprendizaje; solo atrasa el uso.",[12,30960,30961,30964],{},[27,30962,30963],{},"¿Hay caso de migración de Kubernetes a algo más simple?","\nSí, más común de lo que se discute públicamente. Empresas que adoptaron temprano, percibieron que los requisitos no lo justificaban, y migraron para reducir costo operacional y recuperar velocidad de entrega. En general queda fuera de blog post porque admitir \"volvimos atrás\" es incómodo. Pero sucede, y casi siempre el equipo reporta productividad mayor después.",[12,30966,30967,30970,30971,30974,30975,30978],{},[27,30968,30969],{},"¿Cuánto tiempo lleva para un equipo aprender HeroCtl versus Kubernetes?","\nHeroCtl: un desarrollador competente corre el stack entero en producción en ",[27,30972,30973],{},"un día",". Documentación cabe en un post largo, conceptos suman a unos cinco. Kubernetes: el tutorial oficial lleva una semana, y el tiempo hasta \"operar con confianza en producción\" varía de ",[27,30976,30977],{},"tres a doce meses",", dependiendo de la complejidad del stack adyacente. No es la misma escala.",[12,30980,30981,30984],{},[27,30982,30983],{},"¿Y para quien no puede pagar nada de plataforma?","\nEl plan Community de HeroCtl es gratuito permanente. Sin límite artificial de servidores, sin feature gate en alta disponibilidad, sin expiración. Corres todo el stack descrito aquí — coordinación, router, certificados, métricas y logs — sin pagar nada. Los planes pagados (Business y Enterprise) agregan cosas que solo importan cuando la empresa crece: SSO corporativo, auditoría detallada, escrow de código fuente, soporte con SLA. El contrato de precio actual es congelado para quien firma hoy — sin cláusula que permita cambio retroactivo.",[19,30986,3310],{"id":3309},[12,30988,30989],{},"La pregunta con que abrimos no es retórica. \"¿Necesito esto para lo que estoy construyendo?\" merece respuesta honesta, del tamaño de tu problema real, sin el filtro de la presión de currículum, de la reunión con inversor, o de la charla de conferencia de la semana pasada.",[12,30991,30992],{},"Para la mayoría de los equipos de SaaS pre-Serie B en Brasil en 2026, la respuesta honesta es no. No porque Kubernetes sea malo — es excelente para lo que fue diseñado. Pero porque lo que fue diseñado para resolver no es tu problema actual. Estás plantando plántula; él es una excavadora.",[12,30994,30995],{},"Hay camino del medio. Si quieres experimentar:",[224,30997,30998],{"className":226,"code":5318,"language":228,"meta":229,"style":229},[231,30999,31000],{"__ignoreMap":229},[234,31001,31002,31004,31006,31008,31010],{"class":236,"line":237},[234,31003,1220],{"class":247},[234,31005,2958],{"class":251},[234,31007,5329],{"class":255},[234,31009,2964],{"class":383},[234,31011,2967],{"class":247},[12,31013,31014],{},"Corre en cualquier servidor Linux con Docker. Sin registro, sin tarjeta, sin phone-home. Si te gusta, escala a tres servidores y ganas alta disponibilidad real. Si no te gusta, desinstalas y vuelves a lo que estabas usando — sin dato preso, sin dependencia embebida.",[12,31016,31017,31018,31020],{},"La historia larga de por qué elegimos construir esto, en lugar de apuntar a una de las alternativas existentes, está en ",[3337,31019,6545],{"href":6545},". Es la lectura complementaria para quien quiere entender el razonamiento antes de la herramienta.",[12,31022,31023],{},"La intención es simple: orquestación de contenedores, sin ceremonia. Y sin el costo del coloso cuando no lo necesitas.",[3351,31025,4377],{},{"title":229,"searchDepth":244,"depth":244,"links":31027},[31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038],{"id":30388,"depth":244,"text":30389},{"id":16851,"depth":244,"text":16852},{"id":17176,"depth":244,"text":17177},{"id":30519,"depth":244,"text":30520},{"id":30570,"depth":244,"text":30571},{"id":30634,"depth":244,"text":30635},{"id":30680,"depth":244,"text":30681},{"id":30837,"depth":244,"text":30838},{"id":30893,"depth":244,"text":30894},{"id":7351,"depth":244,"text":7352},{"id":3309,"depth":244,"text":3310},"2025-11-17","80% de los equipos que adoptan Kubernetes no lo necesitan. La cuenta es directa: salario de SRE × tiempo hasta el primer feature shippado. Cuándo vale la pena saltarse el coloso.",{},{"title":15791,"description":31040},{"loc":15790},"es\u002Fblog\u002Fkubernetes-overkill-cuando-no-lo-necesitas",[20406,31046,31047,6394],"complejidad","decision-arquitectural","FLcaUzPqzFiRc4kxXyMbp2jtmnvJhbEZdwD_w0E8QtY",{"id":31050,"title":21746,"author":7,"body":31051,"category":20654,"cover":3380,"date":31499,"description":31500,"draft":3383,"extension":3384,"lastReviewed":3380,"meta":31501,"navigation":411,"path":6545,"readingTime":26424,"seo":31502,"sitemap":31503,"stem":31504,"tags":31505,"__hash__":31507},"blog_es\u002Fes\u002Fblog\u002Fpor-que-creamos-heroctl.md",{"type":9,"value":31052,"toc":31488},[31053,31056,31060,31063,31068,31077,31080,31084,31090,31093,31096,31100,31103,31114,31117,31120,31124,31127,31158,31161,31163,31166,31328,31335,31339,31342,31345,31348,31351,31354,31358,31361,31367,31373,31379,31385,31387,31393,31399,31405,31411,31426,31429,31435,31441,31445,31448,31483,31486],[12,31054,31055],{},"Cada cluster que opera en producción hoy tiene que decidir entre tres caminos, y ninguno de ellos es lo bastante bueno para el equipo de cinco personas que intenta lanzar un SaaS.",[19,31057,31059],{"id":31058},"el-camino-doloroso-kubernetes","El camino doloroso: Kubernetes",[12,31061,31062],{},"Abres un manifiesto de \"hello world\" y tiene 300 líneas. Añades un templating manager para organizar — ahora son 300 líneas más 200 líneas de plantillas. Decides usar una versión gestionada en la nube para evitar mantener el plano de control — pagas US$73\u002Fmes por cluster, más NAT, más Application Load Balancer. ¿Necesitas TLS automático? Instalas un operador especializado. ¿Métricas? Otro operador. ¿Enrutamiento entre servicios con cifrado? Dos operadores más y dos días estudiando service mesh. ¿Logs centralizados? Otro stack más.",[12,31064,31065,31066,101],{},"La complejidad no es accidental. El sistema es una plataforma para construir plataformas — hecha por un equipo que necesitaba orquestar 100 mil máquinas. Cuando una startup con cuatro servidores adopta la misma herramienta, está usando una excavadora para plantar un esqueje. Tratamos la tesis general en ",[3337,31067,15791],{"href":15790},[31069,31070,31071],"blockquote",{},[12,31072,31073,31074],{},"\"Most development teams find Kubernetes overkill for dev environments.\"\n— ",[179,31075,31076],{},"Top 13 Kubernetes Alternatives 2026",[12,31078,31079],{},"El coste real no es la infra, es el equipo. Operadores serios de ese sistema cobran salarios de seis cifras. Necesitas al menos uno en el equipo — preferiblemente dos para guardia. Es tu primer ingeniero contratado después del CTO. Antes del diseñador, antes del segundo dev de producto, antes de cualquier cosa que entregue valor al usuario.",[19,31081,31083],{"id":31082},"el-camino-facil-paneles-self-hosted-modernos","El camino fácil: paneles self-hosted modernos",[12,31085,31086,31087,101],{},"Un comando de instalación en un único servidor, abres el panel, despliegas en cinco minutos. Funciona. Los dos líderes de ese segmento suman 80 mil estrellas en repositorios públicos. La comunidad explotó en los últimos dos años porque resolvió el problema correcto: la mayoría de los equipos no necesita el coloso, necesita ",[3337,31088,31089],{"href":19773},"Heroku auto-hospedado",[12,31091,31092],{},"El problema solo aparece después. Creces, el cliente pide SLA, el servidor único se convierte en punto único de fallo. Intentas replicar a dos o tres servidores — esos paneles no tienen consenso distribuido, no tienen elección de líder. Son aplicaciones web sobre Docker. Elegantes para un servidor; frágiles para tres.",[12,31094,31095],{},"Cuando tu primer cliente serio pregunte \"¿cuál es el SLA?\", tendrás que responder \"best-effort\" o empezar a migrar — probablemente al coloso. Reempezar desde cero en el segundo año de la empresa.",[19,31097,31099],{"id":31098},"el-camino-tecnico-que-existia","El camino técnico que existía",[12,31101,31102],{},"Hay un orquestador que es técnicamente lo que quieres. Binario único, consenso distribuido de verdad, multi-tenant, escala a miles de nodos. El proveedor invirtió ocho años puliéndolo, y quien lo ha corrido en producción no tiene quejas del core.",[12,31104,31105,31106,31109,31110,31113],{},"Pero en ",[27,31107,31108],{},"agosto de 2023"," el proveedor cambió la licencia de una OSS legítima a una licencia \"source available\" que restringe el uso comercial. En ",[27,31111,31112],{},"febrero de 2025",", la empresa fue comprada por un conglomerado históricamente conocido por contratos de cinco años y amarre de plataforma. Hoy aquel orquestador forma parte de la cartera del conglomerado — y la licencia te impide ofrecer la tecnología como servicio o embeberla en producto sin licenciamiento comercial.",[12,31115,31116],{},"Para empresas que ya lo tenían en producción, es un problema gestionable. Para ti adoptándolo hoy en 2026, es un asterisco grande: la próxima feature crítica puede subir solo a la versión de pago, o la licencia puede cambiar de nuevo en una próxima reorganización.",[12,31118,31119],{},"La lección que sacamos de esto no es \"open source o nada\" — es \"publica el contrato comercial desde el día uno, sin cambio retroactivo\". Software comercial honesto es mejor que software abierto que se vuelve comercial a mitad de camino. El problema del orquestador técnico no fue volverse de pago; fue cambiar las reglas para quien ya había apostado.",[19,31121,31123],{"id":31122},"la-brecha","La brecha",[12,31125,31126],{},"Ninguno de los tres caminos combina:",[2735,31128,31129,31135,31140,31146,31152],{},[70,31130,31131,31134],{},[27,31132,31133],{},"Binario único"," (operacional simple)",[70,31136,31137,31139],{},[27,31138,16336],{}," (consenso entre múltiples servidores, elección de líder, durabilidad)",[70,31141,31142,31145],{},[27,31143,31144],{},"Experiencia tipo Heroku"," (cero archivo de orquestación extenso, panel web, certificados automáticos)",[70,31147,31148,31151],{},[27,31149,31150],{},"Contrato comercial explícito desde el día uno"," (plan gratuito permanente, planes de pago publicados — sin cambio retroactivo de términos)",[70,31153,31154,31157],{},[27,31155,31156],{},"Batería incluida"," (enrutamiento, malla entre servicios, métricas — sin montar cinco productos)",[12,31159,31160],{},"Los paneles modernos tienen la experiencia y el contrato gratuito, pero pierden en alta disponibilidad. El orquestador técnico tiene la HA pero cambió el contrato con quien ya lo había adoptado y nunca priorizó la experiencia. El coloso tiene todo eso solo si lo montas manualmente — y el \"manualmente\" cuesta un equipo.",[19,31162,4825],{"id":4824},[12,31164,31165],{},"La tabla de abajo es la versión honesta de la decisión. No hay columna sin matiz — todo orquestador es un conjunto de tradeoffs, y el nuestro también.",[119,31167,31168,31185],{},[122,31169,31170],{},[125,31171,31172,31174,31177,31180,31183],{},[128,31173,2983],{},[128,31175,31176],{},"Coloso (K8s)",[128,31178,31179],{},"Panel self-hosted",[128,31181,31182],{},"Orquestador ex-OSS",[128,31184,2995],{},[141,31186,31187,31200,31214,31228,31241,31255,31269,31282,31298,31312],{},[125,31188,31189,31191,31194,31196,31198],{},[146,31190,27233],{},[146,31192,31193],{},"4 horas a 4 días",[146,31195,27236],{},[146,31197,16326],{},[146,31199,27236],{},[125,31201,31202,31204,31206,31209,31212],{},[146,31203,29546],{},[146,31205,3048],{},[146,31207,31208],{},"30 (UI)",[146,31210,31211],{},"80–120",[146,31213,3042],{},[125,31215,31216,31218,31221,31224,31226],{},[146,31217,16336],{},[146,31219,31220],{},"Sí, con 5+ componentes",[146,31222,31223],{},"No (single-server)",[146,31225,3065],{},[146,31227,3065],{},[125,31229,31230,31232,31235,31237,31239],{},[146,31231,26131],{},[146,31233,31234],{},"Operador externo",[146,31236,23300],{},[146,31238,31234],{},[146,31240,23300],{},[125,31242,31243,31246,31249,31251,31253],{},[146,31244,31245],{},"Cifrado entre servicios",[146,31247,31248],{},"Operador especializado",[146,31250,3059],{},[146,31252,31248],{},[146,31254,23300],{},[125,31256,31257,31259,31262,31264,31267],{},[146,31258,25641],{},[146,31260,31261],{},"Stack externo (3+ productos)",[146,31263,19366],{},[146,31265,31266],{},"Stack externo",[146,31268,25646],{},[125,31270,31271,31273,31276,31278,31280],{},[146,31272,22806],{},[146,31274,31275],{},"Stack externo (2+ productos)",[146,31277,19366],{},[146,31279,31266],{},[146,31281,22329],{},[125,31283,31284,31286,31289,31292,31295],{},[146,31285,22839],{},[146,31287,31288],{},"Gratuito + alto coste operacional",[146,31290,31291],{},"Gratuito (single-server)",[146,31293,31294],{},"Comercial restringido (fue gratuito hasta 2023)",[146,31296,31297],{},"Plan gratuito permanente + Business\u002FEnterprise de pago",[125,31299,31300,31302,31305,31307,31310],{},[146,31301,16410],{},[146,31303,31304],{},"1–2 SREs dedicados",[146,31306,22214],{},[146,31308,31309],{},"1 SRE dedicado",[146,31311,22214],{},[125,31313,31314,31316,31319,31322,31325],{},[146,31315,5014],{},[146,31317,31318],{},"50+ máquinas",[146,31320,31321],{},"1 máquina",[146,31323,31324],{},"5–500 máquinas",[146,31326,31327],{},"1–500 máquinas",[12,31329,31330,31331,31334],{},"La columna que importa es la penúltima: ",[27,31332,31333],{},"equipo mínimo para operar",". Ahí vive el coste verdadero. Los otros criterios son la explicación del porqué.",[19,31336,31338],{"id":31337},"lo-que-estamos-construyendo","Lo que estamos construyendo",[12,31340,31341],{},"HeroCtl es un único archivo ejecutable que instalas en N servidores Linux con Docker. Los primeros tres forman el quórum del plano de control replicado. Tú envías jobs vía CLI, API o panel web embebido — el cluster decide dónde correr, hace health check, gestiona rolling updates, emite certificados Let's Encrypt automáticamente vía router integrado.",[12,31343,31344],{},"Sin CRDs, sin operadores especializados, sin charts. El job spec es un archivo de configuración simple (50 líneas para app+ingress+secretos, no 300). Cifrado entre servicios y PKI automática vienen embebidos. Métricas persistentes corren como job del propio sistema. Logs con arquitectura de escritor único (sin montar Fluentd, sin montar Loki).",[12,31346,31347],{},"Hoy el stack público corre en producción: cuatro nodos en proveedor cloud, cinco sitios con TLS automático, dieciséis contenedores, downtime cero en rolling updates. El cluster sobrevivió a una batería completa de caos: kill -9 del servidor que coordina (elección en siete segundos), partición de red de 30 segundos, pérdida de quórum, wipe de disco, drain forzado. Cada uno de esos escenarios da para un post propio.",[12,31349,31350],{},"El resultado práctico es un modelo operacional radicalmente más corto. Subir una aplicación nueva son tres pasos: describes el servicio en un archivo de configuración de cincuenta líneas, lo envías vía CLI, y el cluster decide dónde correr, abre puerto, registra en el router, emite certificado Let's Encrypt y empieza a servir tráfico. Actualizar es un cuarto paso: cambias la versión de la imagen en el archivo, lo envías de nuevo, y el cluster orquesta la sustitución en rolling — sin ventana de mantenimiento, sin feature flag, sin migración manual de tráfico.",[12,31352,31353],{},"Depurar es la prueba real de cualquier orquestador. Cuando algo falla a las tres de la mañana, necesitas un camino corto entre \"el sitio cayó\" y \"sé exactamente qué pasó\". En HeroCtl, ese camino es único: el panel muestra qué contenedor falló, en qué servidor estaba corriendo, último log antes de morir, métricas de los últimos minutos, historial de versiones. Sin grep en tres productos diferentes, sin reconstituir contexto a partir de cinco dashboards, sin alternar entre herramientas de proveedores distintos solo para entender un fallo.",[19,31355,31357],{"id":31356},"cuando-heroctl-no-es-para-ti","Cuándo HeroCtl no es para ti",[12,31359,31360],{},"La honestidad es el mecanismo de defensa de una herramienta nueva: contar dónde no encaja es lo que mantiene el producto enfocado. Cuatro perfiles en los que recomendamos otro camino.",[12,31362,31363,31366],{},[27,31364,31365],{},"Operas a nivel de cientos de miles de máquinas.","\nEmpresas que corren diez mil nodos o más eligieron el coloso por una razón real: fue diseñado para ese tamaño. HeroCtl es honesto sobre el techo: probamos hasta cientos de nodos en laboratorio, validamos algunas decenas en producción de clientes, y el roadmap apunta al rango \"1 a 500 servidores\". Por encima, el ecosistema del coloso te da herramientas que aún no tenemos — y construirlas solo para atender al 0,1% de los casos no es prioridad.",[12,31368,31369,31372],{},[27,31370,31371],{},"Tienes requisitos de compliance que listan herramientas nominalmente.","\nAlgunos frameworks de auditoría (FedRAMP, ITAR, ciertos contratos de gobierno) exigen que el stack corra sobre componentes específicos preaprobados. HeroCtl es demasiado joven para estar en esas listas. Si tu compliance officer necesita apuntar a un certificado existente, hoy la respuesta correcta es el coloso o el orquestador ex-OSS. Pero si necesitas el nombre de una herramienta en la lista de auditoría, no es HeroCtl todavía.",[12,31374,31375,31378],{},[27,31376,31377],{},"Necesitas una biblioteca profunda de operadores especializados.","\nEl ecosistema del coloso tiene cientos de operadores listos — Postgres con replicación automática, Kafka con balanceo, Cassandra con bootstrap. Si tu arquitectura depende de cuatro de esos operadores corriendo en producción desde el día uno, HeroCtl no sustituye. Nuestra propuesta es distinta: corres tu Postgres como un job común, cuidando del backup y la replicación como un humano cuida — sin delegar en un operador que tardó tres años en estabilizarse.",[12,31380,31381,31384],{},[27,31382,31383],{},"Quieres multi-cloud con workloads moviéndose entre proveedores en tiempo real.","\nHeroCtl corre en cualquier servidor Linux con Docker, así que técnicamente puedes mezclar proveedores. Pero las primitivas para mover storage cifrado entre regiones, replicar bases a otro proveedor con failover automático, u orquestar redes virtuales entre nubes — eso el ecosistema del coloso lo resuelve mejor hoy. Está en nuestro roadmap, no en la versión actual.",[19,31386,7352],{"id":7351},[12,31388,31389,31392],{},[27,31390,31391],{},"¿HeroCtl es otro wrapper de Docker más?","\nNo. Los wrappers de Docker no hacen consenso entre servidores, no eligen coordinador, no sobreviven a la pérdida de un nodo con redistribución automática de trabajo. HeroCtl es un plano de control replicado que coordina agentes en cada servidor. Docker queda como runtime de contenedor — una decisión de implementación, no la sustancia del producto.",[12,31394,31395,31398],{},[27,31396,31397],{},"¿Y si la empresa detrás de HeroCtl quiebra?","\nTres protecciones contractuales. Primero, el binario no tiene phone-home obligatorio — una vez instalado, tu cluster sigue funcionando sin hablar nunca con servidor nuestro. No hay kill-switch remoto, no hay activación periódica que expira. Segundo, los contratos Enterprise incluyen escrow de código fuente: si la empresa cierra operaciones, el código se entrega a los clientes pagantes vía tercera parte custodia, con licencia para continuidad interna. Tercero, el contrato de precio actual está congelado para quien firma hoy — no hay cláusula que permita cambio retroactivo de términos. Lo que pasó con el orquestador técnico en 2023 y en 2025 está estructuralmente impedido aquí.",[12,31400,31401,31404],{},[27,31402,31403],{},"¿Cuánto consume de RAM y CPU en cluster pequeño?","\nEl cluster público de demostración corre en cuatro servidores totalizando cinco vCPUs y diez gigabytes de RAM, con dieciséis contenedores activos sirviendo cinco sitios. El plano de control ocupa entre 200 y 400 MB por servidor — sobra para workload real. Comparativamente, el plano de control de una versión gestionada del coloso empieza en cerca de 700 MB por nodo-maestro antes de que suba ninguna aplicación.",[12,31406,31407,31410],{},[27,31408,31409],{},"¿Puedo migrar del orquestador ex-OSS a HeroCtl?","\nSí. Las primitivas son similares (job, group, task; cluster con plano de control replicado; agentes en cada servidor). La diferencia grande está en el archivo de configuración — el nuestro es más corto y tiene menos abstracciones. Para equipos con pocas decenas de jobs, la migración es manual y lleva una tarde. Por encima tenemos un convertidor experimental que cubre los casos comunes. Escríbenos si es tu caso.",[12,31412,31413,31416,31417,31419,31420,31422,31423,31425],{},[27,31414,31415],{},"¿Cómo funciona el pago?","\nTres planes con línea clara entre ellos. ",[27,31418,4352],{}," es gratuito para siempre, sin límite de servidores, sin límite de jobs, sin feature gates artificiales — corre todo el stack descrito arriba, incluyendo HA, router, certificados automáticos, métricas y logs. Individuos y equipos pequeños nunca necesitan salir de aquí. ",[27,31421,4356],{}," añade SSO\u002FSAML, RBAC granular, auditoría detallada, backup gestionado y soporte con SLA — para equipos con requisitos formales de plataforma. ",[27,31424,4360],{}," añade escrow de código fuente, contrato de continuidad, soporte 24×7 y desarrollo dedicado.",[12,31427,31428],{},"Los precios de Business y Enterprise están publicados en la página de planes — sin \"habla con ventas\" obligatorio. La línea de corte está diseñada para que solo pagues cuando la empresa sea lo bastante grande para que SSO y auditoría sean exigencias reales, no preferencia.",[12,31430,31431,31434],{},[27,31432,31433],{},"¿Está listo para producción?","\nEstá corriendo el stack público desde hace seis meses, sobrevivió a una batería documentada de escenarios de caos, y soporta el blog que estás leyendo ahora. \"Listo\" depende de tu apetito al riesgo y del tamaño de tu equipo. Para un indie hacker, tres servidores y un SaaS de US$10k MRR, está más que listo. Para un banco regulado por tres organismos, espera unos trimestres más y conversa con nosotros sobre Business Edition primero.",[12,31436,31437,31440],{},[27,31438,31439],{},"¿Dónde corren los datos sensibles (secretos, certificados, configuraciones)?","\nEn el propio cluster, cifrados en reposo. El cluster es la caja fuerte — no hay servicio externo de bóveda obligatorio. Si quieres integrar con una bóveda externa de tu nube (KMS de proveedor cloud), hay punto de extensión; pero la configuración por defecto es autosuficiente.",[19,31442,31444],{"id":31443},"lo-que-viene-en-los-proximos-posts","Lo que viene en los próximos posts",[12,31446,31447],{},"La intención del blog es técnica y directa: sin fluff de marketing.",[2735,31449,31450,31456,31471,31477],{},[70,31451,31452,31455],{},[27,31453,31454],{},"Ingeniería",": cómo se configura el consenso, cómo funciona la defensa contra contenedores-zombi reteniendo puertos, por qué elegimos snapshot en memoria en lugar de bitmap persistido para asignación de puertos",[70,31457,31458,6562,31461,571,31463,571,31466,571,31468,31470],{},[27,31459,31460],{},"Comparativos",[3337,31462,16705],{"href":16704},[3337,31464,31465],{"href":23631},"HeroCtl vs Nomad",[3337,31467,29865],{"href":25898},[3337,31469,16710],{"href":16709}," — números reales, no opinión",[70,31472,31473,31476],{},[27,31474,31475],{},"Casos de uso",": setup con 1 servidor (sustituir panel simple), 3 servidores (HA real), 10+ servidores (escala)",[70,31478,31479,31482],{},[27,31480,31481],{},"Releases",": changelog narrativo de las features que se entregan",[12,31484,31485],{},"Si eres desarrollador sintiendo que el coloso es demasiado y el panel auto-hospedado es poco, quédate por aquí. Si operas el orquestador técnico y estás incierto sobre el futuro post-adquisición, escríbenos — hay camino de migración.",[12,31487,26405],{},{"title":229,"searchDepth":244,"depth":244,"links":31489},[31490,31491,31492,31493,31494,31495,31496,31497,31498],{"id":31058,"depth":244,"text":31059},{"id":31082,"depth":244,"text":31083},{"id":31098,"depth":244,"text":31099},{"id":31122,"depth":244,"text":31123},{"id":4824,"depth":244,"text":4825},{"id":31337,"depth":244,"text":31338},{"id":31356,"depth":244,"text":31357},{"id":7351,"depth":244,"text":7352},{"id":31443,"depth":244,"text":31444},"2025-11-12","Kubernetes exige un equipo de SRE. Los paneles simples no tienen alta disponibilidad real. El competidor técnico más cercano cambió de licencia y fue adquirido. Faltaba una alternativa — así que la construimos.",{},{"title":21746,"description":31500},{"loc":6545},"es\u002Fblog\u002Fpor-que-creamos-heroctl",[31506,20406,7512,27534],"manifiesto","0tW4VdbPggCXBZOqNdrDLbTn9SVLrzhw3yEiGQglZis",1777362205106]