Cómo migré SynapseOne de Render a GCP: por qué dejamos PaaS por una VM con Docker Compose"
Hace unos meses, SynapseOne corría en Render. Funcionaba bien para el arranque. Pero a medida que el volumen de datos de nuestros clientes creció y empezamos a diseñar los módulos de Inteligencia Artificial para predicciones de demanda, nos topamos con la dura realidad de los entornos PaaS: la falta de control total sobre los recursos del sistema y los límites rígidos de hardware.
SynapseOne es una plataforma SaaS de forecasting de inventario con IA, diseñada para negocios minoristas que manejan entre 50 y 5,000 productos. Si querés saber más sobre el producto, visitanos.
Este artículo es la historia de nuestra migración hacia Google Cloud Platform (GCP). No es un tutorial genérico; es una bitácora técnica honesta sobre cómo decidimos mover un stack moderno de Elixir / Ash Framework multi-tenant a una infraestructura propia, reduciendo costos y ganando control absoluto del microprocesador.
El problema con Render: El Techo de Cristal
Render es excelente para validar ideas. Lo configurás en 10 minutos, hacés un push y te olvidás. Sin embargo, para una SaaS con análisis intensivo de datos, empezamos a notar fricciones:
- Falta de acceso de bajo nivel: No podés auditar en vivo el comportamiento del núcleo de procesamiento ni optimizar las variables del kernel de Linux.
- Costos de escalabilidad: El salto de hardware en entornos administrados penaliza financieramente a las startups en etapa temprana.
- Aislamiento de red limitado: Necesitábamos flexibilidad total para gestionar contenedores aislados y volúmenes de datos locales.
Nuestra Filosofía: Arquitectura Consolidada en GCP (Evitando la trampa de los sobrecostos)
Cuando investigás migraciones a la nube, la documentación tradicional te empuja a comprar mil servicios separados: instancias Serverless (Cloud Run), bases de datos ultra-gestionadas (Cloud SQL) y almacenamiento distribuido. Para una startup, esto es una receta para inflar la factura con costos fantasmas de transferencia de red.
Nuestra decisión de ingeniería Senior fue ir contracorriente: Consolidar todo nuestro stack dentro de una instancia dedicada de Compute Engine (Máquina Virtual pura con Debian Linux) coordinada mediante Docker Compose.
La Arquitectura Real
- Servidor Web (Contenedor Phoenix + Bandit): Procesa las peticiones concurrentes de la app y los esquemas gestionados por Ash Framework.
- Base de Datos (Contenedor PostgreSQL 16 local): En lugar de pagar por un servicio externo como Cloud SQL, corremos el motor localmente con volúmenes persistentes en disco. Latencia de red: mínima.
- Gestión de Memoria Quirúrgica: Configuramos 2 GB de Swap a nivel de sistema operativo para actuar como colchón de seguridad ante picos de procesamiento de datos o generación masiva de reportes.
Comparativa de Costos (por qué una VM gana)
| Servicio | Costo/mes | ¿Por qué? |
|---|---|---|
| Render (Starter) | $7 | Staging, 512MB RAM |
| Render (Standard) | $25 | Producción, 2GB RAM |
| Render PostgreSQL | $6 | 256MB, compartido |
| Total Render | $46/mes | Sin control de HW |
| GCP Compute Engine (e2-small) | ~$18/mes | 2 vCPU, 2GB RAM, (+2GB swap) |
| GCP Postgres (contenedor) | $0 | Incluido en la VM |
| Total GCP | ~$25/mes | ¡50% más barato! |
Nota: Estos costos son para un perfil de startup con 1-10 organizaciones activas. A mayor escala, los costos pueden variar, pero la flexibilidad de una VM te permite ajustar recursos sin depender de planes fijos.
El Flujo de Despliegue (CI/CD Automatizado)
Olvídate de las interfaces pesadas. Diseñamos un oleoducto de despliegue directo usando GitHub Actions y un Makefile automatizado:
-
Al hacer
git pusha la rama de producción, GitHub compila la versión empaquetada de la BEAM y la aloja en el registro privado de GitHub (GHCR). - GitHub Actions se conecta de forma segura por SSH a nuestra máquina virtual en GCP.
-
El servidor ejecuta nuestra tarea automatizada en el Makefile (
make prod-up), descargando únicamente la imagen web actualizada, apagando el contenedor viejo y encendiendo el nuevo en menos de un segundo, sin interrumpir ni tocar la base de datos local.
El Makefile
COMPOSE_PROD=docker-compose.prod.yml
ENV_PROD=.env.prod
prod-pull:
docker compose --env-file $(ENV_PROD) -f $(COMPOSE_PROD) pull web
prod-up: prod-pull
docker compose --env-file $(ENV_PROD) -f $(COMPOSE_PROD) up -d
prod-migrate:
docker compose --env-file $(ENV_PROD) -f $(COMPOSE_PROD) \
exec web /app/bin/app rpc "Release.migrate()"
Desafíos del Mundo Real: El Misterio del 50% de CPU
Ninguna migración es perfecta. Al levantar la VM en GCP, notamos que la gráfica de monitoreo mostraba un consumo plano y constante del 50% de CPU en reposo, a pesar de que nuestra aplicación Elixir marcaba menos del 1% de uso.
Haciendo debugging fino mediante la terminal SSH descubrimos al culpable: el agente de telemetría por defecto de Google (Cloud Ops Agent) estaba atrapado en un bucle infinito intentando enviar métricas sin tener los permisos de IAM configurados en la consola.
¿La solución? Ejecutamos cirugía en caliente en systemd:
sudo systemctl stop google-cloud-ops-agent
sudo systemctl disable google-cloud-ops-agent
El resultado fue inmediato: la gráfica cayó por debajo del 50% y bajó al 0% real de uso en reposo, liberando toda la potencia térmica del procesador para las consultas concurrentes de nuestros Tenants.
Multi-tenencia con Ash Framework
Mantenemos nuestra estrategia de aislamiento de datos usando schemas separados por organización con Ash Multi-tenancy (org_<uuid>). Al correr Postgres de forma local y optimizada, el motor maneja las transacciones concurrentes de los diferentes clientes de forma nativa, veloz y sin degradación de memoria.
El Verdadero Súper Poder: Consola IEx en Producción y Pruebas en Caliente
Si programas en Elixir, sabes que una de las mayores joyas de la máquina virtual de Erlang (BEAM) es la capacidad de conectarte de forma interactiva a tu aplicación en producción mediante una sesión remota de IEx (Interactive Elixir).
En Render, esto era un sueño prohibido. Debido a los límites rígidos de hardware del plan básico (512MB/1GB), intentar levantar un proceso iex interactivo en paralelo al contenedor web bajo tráfico real era una sentencia de muerte: el OOM (Out Of Memory) Killer de Linux se despertaba y te tiraba el servidor abajo de inmediato. Vivíamos a ciegas, dependiendo únicamente de los logs estructurados.
Al migrar a nuestra infraestructura consolidada en GCP y configurar estratégicamente los 2 GB de Swap, ganamos el colchón de memoria necesario para desbloquear el flujo de trabajo definitivo.
Ahora, cuando necesitamos validar el comportamiento de un módulo de Inteligencia Artificial con datos reales, inspeccionar un proceso de Oban atascado, o realizar pruebas en caliente sin alterar el servicio de nuestros clientes, simplemente tiramos una línea vía SSH:
make prod-remote
O directamente:
docker compose --env-file $(ENV_PROD) -f $(COMPOSE_PROD) exec web /app/bin/app remote
Esto nos mete directo al corazón de la aplicación en vivo. Podemos consultar repositorios, lanzar funciones de prueba con Ash Framework y debugear en tiempo real con la tranquilidad de que el hardware tiene el presupuesto necesario para aguantar el camión. Pasar de la ceguera de un entorno PaaS hiper-restringido a la libertad de la consola de Elixir en caliente ha cambiado por completo nuestra velocidad de respuesta y calidad de ingeniería.
Conclusión
Si estás validando un prototipo con un puñado de usuarios, empezá con Render. Es simple y te quita fricción de encima.
Pero si tu SaaS empieza a procesar volúmenes reales de datos y necesitas exprimir cada ciclo del procesador, el camino no es saltar a arquitecturas complejas como Kubernetes o Cloud Run que añaden capas de costos innecesarios. Una máquina virtual limpia en GCP, Docker Compose bien estructurado, un archivo Swap de seguridad y automatización con un Makefile te darán el rendimiento de un gigante por una fracción del costo. En la ingeniería de software, la simplicidad bajo control siempre gana.
¿Querés probar el producto que corre en esa VM?
SynapseOne usa inteligencia artificial para predecir la demanda de inventario, comparar proveedores y sugerirte exactamente qué comprar y cuándo.