Tu Django o Flask no aguanta el crecimiento. Latencia subiendo, factura de Cloud disparada, GIL bloqueando lo que debería ser concurrente. Migramos a Go con strangler pattern, sin big-bang, manteniendo el negocio en pie cada sprint.
No es una reescritura ciega ni un purismo de lenguaje. Es una migración por dominio, con métricas antes y después, y compatibilidad de API mientras dura el cambio.
−40%
Coste de Cloud Run típico tras migrar el path crítico
10×
Throughput por instancia con goroutines vs uvicorn workers
<100 ms
Cold-start típico, vs 1–3 s de un proceso Python con dependencias pesadas
0
Big-bang. Migración progresiva con strangler pattern
Cuándo migrar
No todo backend Python necesita migrarse. Estos son los síntomas concretos donde Go aporta más de lo que cuesta.
El GIL serializa la concurrencia real. Cuando subes RPS, p99 se dispara aunque la CPU esté al 30%. Añadir uvicorn workers compra tiempo, no resuelve el problema.
Para servir el mismo throughput, Python necesita 3–10× más instancias que Go. En Cloud Run con autoscaling, eso es factura directa. Migrar el path caliente reduce coste sin cambiar la lógica.
Python + Django/FastAPI + dependencias ML carga 1–3 s al arrancar. En Cloud Run con scale-to-zero, eso son request fallidas o timeouts. Un binario Go arranca en <100 ms.
asyncio es funcional pero el modelo mental es complejo y rompe en librerías sync. Celery + Redis para tareas async es operativamente caro. En Go, una goroutine + canal cubre el 90% de los casos.
mypy ayuda pero no es vinculante. En Go, el compilador rechaza tipos incompatibles antes de que lleguen a CI. La curva de bugs por lanzamiento se aplana visiblemente.
Imágenes Docker Python con NumPy, PyTorch, etc. pasan de 1 GB. En Go, un binario estático en una imagen scratch o distroless ronda los 30 MB. Deploys más rápidos, superficie de ataque menor.
Cuándo NO migrar
Comparativa honesta
Cada lenguaje gana en lo suyo. Esta es la comparativa que damos a CTOs en duda — sin sectarismo de stack.
| Dimensión | Python | Go | Veredicto |
|---|---|---|---|
| Latencia p99 a alta concurrencia | Limitada por el GIL · workarounds con uvicorn workers | Estable bajo carga · goroutines nativas | Go |
| Cold-start (Cloud Run / Lambda) | 1–3 s típico con dependencias | <100 ms con binario optimizado | Go |
| Footprint de imagen | 300 MB – 2 GB | <30 MB con multi-stage | Go |
| Velocidad de prototipado | Inmejorable · notebook → script → service | Más boilerplate · compila siempre | Python |
| Ecosistema ML / data science | El estándar de facto · NumPy, PyTorch, scikit | Limitado · ONNX runtime para inferencia | Python |
| Tipado y captura de errores en compilación | mypy / pyright son opcionales · runtime errors | Compilador estricto · errores explícitos | Go |
| Concurrencia | asyncio funciona pero rompe en libs sync · GIL | Goroutines + canales · idioma de primer nivel | Go |
| Talento disponible | Abundante a todos los niveles | Más nicho · pero alto nivel medio | Empate |
| Deployment a Cloud Run | Razonable · ajustes de Dockerfile constantes | Idiomático · imagen scratch/distroless | Go |
| Coste mensual a igual throughput | Línea base | Típicamente −40% al −60% | Go |
Cómo migramos
El servicio Go nuevo recibe progresivamente porcentajes del tráfico vía proxy o feature flags. La API mantiene compatibilidad. El monolito Python sigue vivo hasta que el último endpoint se ha migrado.
01
Auditoría del monolito actual: endpoints, latencia por endpoint, cobertura de tests, dependencias críticas, observabilidad existente. Identificamos los 3–5 endpoints calientes que justifican empezar la migración. Definimos el SLO objetivo.
1–2 sem
02
El servicio Go nuevo expone exactamente las mismas APIs que el monolito Python. OpenAPI / Protobuf como contrato firmado, contract testing en CI. Sin cambios de cliente — el frontend o las apps móviles no tocan código.
1 sem
03
Reescribimos el endpoint o conjunto de endpoints más caliente en Go. Misma DB, mismo Redis, misma cola. Tests de integración contra fixtures reales. Despliegue inicial al 0% de tráfico — sombra completa para validar paridad de comportamiento.
3–6 sem
04
Routing del 1% → 5% → 25% → 100% del tráfico al servicio Go via proxy (Envoy, Cloud Load Balancer) o feature flags por usuario. Métricas comparadas en cada salto: latencia, error rate, paridad de respuesta. Rollback en segundos si algo se desvía.
2–3 sem por dominio
05
Repetimos el ciclo por dominio. Cuando el último endpoint Python ha migrado, apagamos el monolito. Documentación operacional, runbooks, dashboards Grafana / Cloud Monitoring entregados al equipo del cliente.
Variable según alcance
Qué migramos
No siempre se migra todo. A veces solo el path caliente. Estos son los patrones más frecuentes que vemos en producción.
El Django/Flask que sirve a la app móvil o al SPA. Suele ser el path con más tráfico y el más fácil de migrar — aprovecha al máximo las goroutines y reduce coste de Cloud inmediatamente.
Lo que hoy hace Celery + Redis lo asume un servicio Go con Pub/Sub o NATS. Pool de goroutines acotado, dead-letter queue, backpressure controlada. 10× throughput por instancia sin tocar la lógica de negocio.
La parte de orquestación (function calling, retries, streaming) en Go; la parte ML pura (entrenamiento, fine-tuning) sigue en Python. Patrón híbrido común — lo aplicamos en CityXerpa.
Trocear un Django monolítico por dominio (auth, billing, catalogue, notifications). Cada dominio se vuelve un microservicio Go independiente con su DB. Strangler pattern por dominio, sin tocar el resto.
Donde p99 < 100 ms es contractual. Python no llega; Java/JVM funciona pero pesa más. Go encaja exacto: latencia y footprint correctos, talento más barato que Java.
Endpoints que reciben webhooks (Stripe, Twilio, GitHub) y disparan procesamiento. Go hace estos endpoints irrompibles a saturación con goroutines + Pub/Sub para decoupling del path crítico.
FAQ técnica
Depende del tamaño y la fragmentación del monolito. Un servicio Python mediano con 8–15 endpoints calientes se migra en 3–5 meses con el strangler pattern, sin downtime y manteniendo el negocio operativo. Monolitos grandes con cientos de endpoints son proyectos de 9–18 meses, pero el ROI suele aparecer en el mes 3 con la migración del primer dominio caliente.
Los tests unitarios sí — son específicos del lenguaje. Los tests de integración y end-to-end (que llaman a la API) NO: precisamente esos validan que el Go nuevo entrega la misma respuesta que el Python viejo. Mantenerlos durante toda la migración es la red de seguridad principal.
Caso típico. Tres opciones: (1) Dribba implementa la migración y entrega + handover con documentación + sesiones de pairing 2 semanas; (2) modelo híbrido — nuestros engineers Go integrados con vuestro equipo Python para transferir conocimiento mientras migran; (3) formación previa intensiva (1–2 semanas) para el equipo, después acompañamiento. Los engineers Python con experiencia aprenden Go en 4–8 semanas — la curva es corta.
Total. La API expuesta no cambia mientras dura la migración. Mismos endpoints, mismos schemas, mismos códigos de error. El frontend o las apps móviles no se enteran. Si después de la migración queréis evolucionar la API a v2, lo hacemos como proyecto separado.
Por defecto, solo la capa de aplicación. La DB se mantiene (Postgres normalmente). El servicio Go usa pgx o sqlc para acceder a las mismas tablas. Si la DB es parte del problema (modelo mal diseñado, queries pesadas, índices incorrectos), lo flagamos en el discovery y proponemos mejoras como track separado.
No las migramos. PyTorch, TensorFlow, scikit-learn, NumPy/pandas se quedan en Python — Go no compite ahí. La separación es: capa de servicio HTTP en Go, capa ML en Python (FastAPI minimal o gRPC server). El servicio Go llama al Python por gRPC interno. Patrón común y eficaz.
Cuatro métricas en cada salto de tráfico: (1) latencia p50/p95/p99 del nuevo servicio Go vs el viejo Python; (2) error rate por endpoint; (3) paridad de respuesta — comparación byte-a-byte de respuesta para 1000 requests aleatorios; (4) coste de Cloud Run por request. Dashboards Grafana o Cloud Monitoring con alertas automáticas si cualquier métrica se desvía >5%.
Migración del path caliente (3–5 endpoints en un servicio Python mediano) entre 60.000 y 120.000 € en 3–5 meses. Migración completa de un monolito a una arquitectura de microservicios Go entre 150.000 y 400.000 € en 9–18 meses. Precio fijo por dominio tras Discovery. La factura suele amortizarse en 6–12 meses por el ahorro en Cloud.
¿Tu monolito Python ha dejado de escalar?
Te entregamos un informe con: endpoints calientes, paridad de tests, plan de strangler por dominio, estimación de coste y de ROI. Aunque el plan no nos contrate.
Equipo 100% senior in-house en Barcelona y Andorra · Respuesta en 24 h