Cloud Run vs GKE: el marco de decisión para tu backend en Go (2026)
Si tienes que decidir hoy dónde desplegar un backend nuevo en Go, la respuesta corta es esta: empieza en Cloud Run y quédate ahí hasta que un requisito concreto te obligue a moverte a GKE. La mayoría de servicios que construimos nunca cruzan esa línea. Pero la línea existe, es nítida, y elegir mal en cualquiera de las dos direcciones cuesta dinero: de más en infraestructura ociosa si sobredimensionas con Kubernetes, o de más en horas de ingeniería peleándote con los límites de Cloud Run cuando tu carga ya no encaja.
Este artículo es el marco de decisión que aplicamos en Dribba, con criterios verificables en lugar de opiniones, un Dockerfile de referencia que sirve para ambos destinos, y —lo más importante— las señales concretas que indican que ha llegado el momento de migrar. Sin hype de "cloud native" y sin la falacia de que Kubernetes es sinónimo de "hacer las cosas bien".
Respuesta rápida: la tabla de decisión
Cloud Run y Google Kubernetes Engine (GKE) resuelven el mismo problema —ejecutar contenedores en producción sobre Google Cloud— pero optimizan cosas distintas. Cloud Run optimiza el coste operativo y el tiempo hasta producción; GKE optimiza el control y la densidad. Para un backend en Go, que compila a un binario pequeño y arranca en milisegundos, Cloud Run es casi siempre el punto de partida correcto.
| Criterio | Cloud Run | GKE |
|---|---|---|
| Modelo mental | "Dame un contenedor, olvídate del resto" | "Gestiona tú el clúster" |
| Escalado a cero | Sí (pagas solo por request) | No de forma nativa (nodos siempre encendidos) |
| Coste con tráfico irregular | Muy bajo | Alto (pagas el clúster ocioso) |
| Coste con tráfico alto y constante | Puede encarecerse | Más eficiente por densidad |
| Control de red / sidecars / DaemonSets | Limitado | Total |
| Curva operativa | Casi nula | Requiere equipo (o SRE) |
| Cargas stateful, colas largas, GPUs dedicadas | Encaja mal | Encaja bien |
| Multi-servicio con service mesh (mTLS, tracing) | Posible pero justo | Terreno natural |
La regla que usamos: si no puedes nombrar el requisito exacto que Cloud Run no cubre, no necesitas GKE.
Cuándo Cloud Run es la respuesta correcta
Cloud Run brilla cuando tu servicio es stateless, orientado a request/response o a eventos, y con tráfico que no es constante. Es decir: el 80% de las APIs, webhooks, BFF (backend-for-frontend) para apps móviles, y microservicios de integración que se construyen hoy.
Los motivos concretos por los que lo elegimos por defecto para backends en Go:
- Escala a cero. Si tu servicio no recibe tráfico de madrugada, pagas cero. Para un MVP, un entorno de staging o un servicio interno con uso puntual, esto cambia la factura por completo.
- Arranque en frío casi irrelevante en Go. El talón de Aquiles de Cloud Run son los cold starts. Con Go, un binario estático de pocos megas arranca en decenas de milisegundos, no en segundos como una JVM o un runtime de Node con dependencias pesadas. El lenguaje y la plataforma se complementan.
- Cero gestión de infraestructura. No hay nodos que parchear, ni versiones de Kubernetes que actualizar, ni
kubectlque dominar. El equipo de producto envía código, no opera un clúster. - Despliegue trivial desde CI/CD. Un
gcloud run deploy(o su equivalente en tu pipeline) y tienes tráfico enrutado, TLS gestionado y revisiones con rollback inmediato.
Si tu caso encaja aquí, meter Kubernetes en la ecuación no te hace más "senior": te añade una superficie operativa que alguien tendrá que mantener durante años.
Cuándo necesitas GKE (y no antes)
GKE deja de ser sobreingeniería y pasa a ser la opción correcta cuando aparece al menos uno de estos requisitos reales:
- Cargas de larga duración o stateful. Workers que procesan trabajos de minutos u horas, consumidores de colas que deben mantener conexiones persistentes, o servicios que necesitan almacenamiento con estado (
StatefulSets). Cloud Run está pensado para peticiones acotadas, no para procesos que viven indefinidamente. - Control fino de red. Necesitas sidecars (un proxy de service mesh como Istio/Linkerd),
DaemonSetspara agentes de observabilidad en cada nodo, políticas de red por pod, o IPs estáticas de salida con reglas complejas. - Densidad y coste a gran escala. Cuando tienes muchos servicios con tráfico alto y sostenido, empaquetarlos en un clúster que aprovechas al 70-80% sale más barato que pagar la abstracción por-request de Cloud Run servicio a servicio.
- Hardware específico y sostenido. GPUs dedicadas para inferencia constante, tipos de máquina concretos, o afinidad de nodos. (Ojo: Cloud Run ya ofrece GPU para inferencia serverless, así que valida si de verdad necesitas el clúster antes de asumirlo.)
- Portabilidad multi-cloud real. Si un requisito de negocio o regulatorio te exige poder mover la carga entre proveedores, Kubernetes es el estándar que te lo permite. "Real" es la palabra clave: la mayoría de proyectos que invocan multi-cloud nunca lo ejercen.
Si ninguno aplica, GKE es una decisión que pagarás en complejidad sin recibir nada a cambio.
El coste real (no es el que crees)
El error de cálculo más común es comparar solo la factura de cómputo. Con GKE pagas el clúster encendido las 24 horas, tenga o no tráfico, más el coste de gestión del plano de control, más —y esto es lo que casi nadie contabiliza— el coste humano de operarlo: actualizaciones de versión, gestión de nodos, tuning de autoscaling, respuesta a incidentes. Ese tiempo de ingeniería senior es, con frecuencia, el gasto más caro de todos.
Cloud Run invierte el modelo: pagas por uso real y el coste operativo tiende a cero. La contrapartida es que, a volúmenes muy altos y constantes, el precio por-request puede superar al de un clúster bien aprovechado. La pregunta correcta no es "¿cuál es más barato?" sino "¿a qué volumen se cruzan las curvas para mi patrón de tráfico?" — y para la mayoría de productos ese cruce llega mucho más tarde de lo que se teme.
Tu backend en Go, listo para cualquiera de los dos
La buena noticia: una imagen de contenedor bien construida se despliega igual en Cloud Run que en GKE. Si empaquetas tu servicio en Go correctamente, la decisión de plataforma no te obliga a reescribir nada. Este es el Dockerfile multi-stage que usamos como base:
# ---- build stage ----
FROM golang:1.26-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Binario estático, sin CGO, reproducible y pequeño
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /app ./cmd/server
# ---- run stage ----
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /app /app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app"]
Tres decisiones que importan: CGO_ENABLED=0 produce un binario estático que corre sobre una imagen distroless mínima (menos superficie de ataque, arranques más rápidos); distroless en lugar de alpine elimina la shell y los paquetes que no necesitas en producción; y nonroot evita ejecutar el proceso como root.
Para que el mismo servicio funcione bien en ambos destinos, exponte dos endpoints de salud. GKE los usa como readinessProbe y livenessProbe; Cloud Run se apoya en el startup para enrutar tráfico:
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) // liveness: el proceso está vivo
})
mux.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
if !db.Ping() { // readiness: ¿puede atender tráfico de verdad?
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
})
Y el detalle que evita cortes de tráfico en ambas plataformas: respeta el apagado ordenado. Escucha SIGTERM, deja de aceptar conexiones nuevas y termina las que están en curso antes de morir. En Go son unas líneas con http.Server.Shutdown(ctx); en Kubernetes marca la diferencia entre un despliegue limpio y errores 502 durante cada rollout.
Construir el servicio de forma portable primero, y decidir la plataforma después, es lo que te permite empezar en Cloud Run sin cerrarte la puerta a GKE.
Cuándo NO usar ninguno de los dos
Ser honestos también significa señalar cuándo esta comparación no aplica:
- Si tu backend es una capa fina sobre Firebase o Firestore, quizá no necesites un servicio contenedizado en absoluto: Cloud Functions o la propia lógica en el cliente pueden bastar. No montes un microservicio para envolver cuatro llamadas.
- Si estás validando una idea, no debates arquitectura de clústeres: despliega lo mínimo, mide, y arquitectura la que los datos justifiquen. La decisión Cloud Run vs GKE es un problema que se resuelve después de tener tracción, no antes.
- Si no tienes a nadie que opere Kubernetes, GKE no es una opción por mucho que encaje técnicamente. Un clúster sin quien lo mantenga es deuda que vence en el peor momento.
Nuestra recomendación
Para un backend nuevo en Go, empieza en Cloud Run. Construye la imagen de forma portable (multi-stage, distroless, SIGTERM limpio) para no atarte. Y ten identificada de antemano la señal que te hará migrar: cargas stateful de larga duración, necesidad de service mesh o sidecars, o un volumen constante donde las curvas de coste se crucen a favor del clúster. Cuando esa señal llegue —y en muchos productos no llega nunca— la migración a GKE será una decisión informada, no una apuesta.
En Dribba llevamos desde 2011 construyendo producto con equipos 100% senior in-house, y el backend en Go sobre Google Cloud es una de nuestras especialidades precisamente porque hemos hecho esta llamada decenas de veces, en más de 300 proyectos y 20 países. La mayoría de las veces, la respuesta responsable es la más simple.
Si estás en ese punto de decisión —o ya sientes que tu Cloud Run se queda corto y no sabes si es hora de dar el salto— podemos ayudarte a leer las señales con datos. Puedes ver por qué elegimos Go para proyectos de alto rendimiento, cómo orquestamos microservicios con Kubernetes para equipos mobile, o los principios de diseño de APIs que aplicamos en cada backend.




