Si tu backend Go arranca en Cloud Run por debajo de 100-300 ms, el cold start no es tu problema. El problema casi nunca es Go: es qué metes en la ruta de arranque y si escalas a cero cuando tu producto no se lo puede permitir. Esta guía es la checklist que seguimos antes de poner un servicio Go en producción sobre Cloud Run, y la decisión que va antes que la checklist: ¿debes escalar a cero o no?
Qué es un cold start en Cloud Run
Un cold start es el tiempo que pasa desde que Cloud Run decide que necesita una instancia nueva hasta que esa instancia acepta su primera petición. Dentro caben cuatro cosas: descargar la imagen del contenedor, arrancar el contenedor, ejecutar tu entrypoint y correr tu código de inicialización hasta que el servidor escucha en el puerto.
Hay dos momentos en los que ocurre, y conviene no confundirlos:
- Desde cero. No hay ninguna instancia viva y llega una petición. Pagas el arranque completo.
- En scale-out. Ya hay instancias sirviendo, pero el tráfico sube y Cloud Run levanta más. Cada instancia nueva también arranca en frío, aunque tengas otras calientes.
Esta distinción importa porque cambia qué palanca resuelve tu caso. Poner un mínimo de instancias mata el primer cold start, pero no el segundo.
Por qué Go parte con ventaja
Go compila a un binario estático único. Eso te deja meterlo en una imagen scratch o distroless de unos pocos megas, y una imagen pequeña se descarga antes. El runtime arranca rápido porque no hay intérprete que calentar ni máquina virtual que levantar. En nuestros servicios el binario final suele quedar por debajo de 30 MB y el arranque en frío por debajo de 100 ms.
Esa ventaja es real, pero no te salva sola. Un backend Go mal arrancado tarda lo mismo que cualquier otro. Las tres formas más comunes de tirarla:
- Trabajo pesado en
init()o antes de escuchar: precargar catálogos enteros, abrir todas las conexiones, leer ficheros grandes. GOMAXPROCSmal configurado. Hasta Go 1.25 el runtime veía las CPU del host, no el límite de CPU del contenedor. En Cloud Run eso significaba un runtime que cree tener 8 núcleos cuando tiene 1, con el planificador peleándose consigo mismo. Go 1.25 lo hace consciente del contenedor; si estás en una versión anterior,go.uber.org/automaxprocshace el mismo trabajo.- Panics en el arranque. Un panic durante la inicialización mata la instancia, y Cloud Run tiene que levantar otra con las peticiones en cola. Un cold start se convierte en dos.
La decisión que va primero: ¿escalar a cero?
Antes de tocar ninguna palanca, decide si este servicio debe poder bajar a cero instancias. Es la decisión que más dinero y más latencia mueve, y depende del servicio, no de una regla general.
| Scale-to-zero | Mínimo de instancias | |
|---|---|---|
| Coste en reposo | Cero | Pagas las instancias mínimas aunque nadie entre |
| Latencia del primer usuario | Paga el cold start | Sin cold start desde cero |
| Encaja con | Tráfico intermitente, herramientas internas, entornos de staging, jobs | p99 bajo garantizado, checkout, webhooks con timeout corto |
Escala a cero cuando el tráfico es a ratos y nadie se juega nada en el primer milisegundo: paneles internos, back-office, un cron que despierta cada hora, los entornos que no son producción. Ahí pagar instancias en reposo es tirar dinero.
No escales a cero cuando un humano está esperando esa respuesta y tienes un p99 que cumplir, cuando un proveedor de pagos te manda un webhook con un timeout de tres segundos y reintenta si no contestas, o cuando el que espera es alguien delante de un agente que ya de por sí tarda. En esos casos un mínimo de una o dos instancias es barato comparado con el usuario que se va.
Un mínimo de instancias no elimina los cold starts, solo el de arrancar desde cero. Si tu pico de tráfico levanta cinco instancias nuevas, esas cinco arrancan en frío igual. El mínimo te cubre la línea base, no la subida.
La checklist de arranque
Decidido lo anterior, estas son las palancas concretas, de la que más devuelve a la que menos.
-
Imagen mínima. Binario estático sobre
distrolessoscratch, multi-stage build, sin herramientas de compilación en la imagen final. Cada mega que quitas es descarga que no pagas en cada arranque. -
Nada pesado antes de escuchar. Empieza a aceptar peticiones cuanto antes y conecta lo demás bajo demanda. Un pool de base de datos se puede abrir perezoso; un catálogo en memoria se puede cargar en segundo plano. Lo que esté en la ruta crítica del arranque es latencia que paga tu primer usuario.
-
GOMAXPROCSconsciente del contenedor. Go 1.25 o superior lo resuelve de serie; por debajo,automaxprocs. Sin esto, un servicio con 1 vCPU asignada se comporta como si tuviera los núcleos del host, y el coste no se nota en un benchmark pero sí bajo carga real. -
Startup CPU boost. Cloud Run puede doblar la CPU durante el arranque y los primeros diez segundos de servicio: una instancia de 1 vCPU arranca con 2. Es gratis de activar y recorta el tramo de inicialización. Enciéndelo salvo que tengas una razón para no hacerlo.
-
Mínimo de instancias y concurrencia, calculados. La capacidad caliente es mínimo de instancias por concurrencia. Tres instancias con concurrencia 80 te cubren 240 peticiones simultáneas sin cold start. Ajusta la concurrencia a lo que tu handler aguanta de verdad, no al valor por defecto.
-
No crashees en el arranque. Valida configuración y degrada con criterio en vez de llamar a
log.Fatala la primera. Un fallo de arranque en producción es una instancia menos y una cola de peticiones esperando a la siguiente. -
Mídelo. Cloud Run expone el tiempo de arranque y la frecuencia de cold starts. Sin ese dato estás adivinando si tus usuarios ven el retardo a diario o solo cuando el servicio sube de cero. Ponlo en un panel antes de optimizar nada.
El caso de los backends de IA
Esto se ha vuelto más relevante con los backends de agentes y modelos. Un servicio que en el arranque instancia un cliente de LLM, carga un tokenizador o abre conexiones a una base vectorial tiene un cold start más caro que un CRUD. Y encima suele estar en la ruta donde un usuario espera la respuesta del agente.
Ahí la combinación que usamos es clara: mínimo de instancias para no arrancar desde cero, inicialización perezosa de todo lo que no haga falta en la primera petición, y medir el arranque como una métrica de producto, no de infraestructura. Si montas backends de este tipo, lo tratamos a fondo en nuestra página de backend Go en Cloud Run.
Qué hacemos nosotros
Por defecto escalamos a cero. La mayoría de los servicios que construimos tienen tráfico que no justifica pagar instancias en reposo, y Go arranca lo bastante rápido para que el cold start ocasional no se note. El mínimo de instancias lo reservamos para donde el p99 es un compromiso con el cliente o donde hay webhooks y pagos que no perdonan un segundo de más.
La razón es una cuenta de la servilleta: unas decenas de euros al mes en instancias calientes frente al usuario que abandona cuando la primera petición tarda. Casi siempre gana escalar a cero; cuando no, el mínimo es de los gastos más fáciles de justificar.
Si estás montando un backend Go sobre Cloud Run, o migrando uno de Python o Node y quieres saber qué se tensa en producción, así lo hacemos en Dribba y esto es lo que miramos al migrar.




