Gabriel Segovia
ESEN
Escribime
Volver a proyectos

GoImport

Catálogo y panel · En producción

Catálogo minorista, catálogo mayorista y panel de administración para un importador. Más de 800 productos con precios según la cotización del día.

Captura de la página principal de GoImport

Datos rápidos

  • Rol: desarrollador full stack y encargado de la infraestructura.
  • Cliente: un importador con catálogo minorista y mayorista.
  • Migración: 02-10-2026.
  • Stack: Express, JavaScript, Supabase (PostgreSQL, Auth y Storage), Docker y Cloudflare Tunnel.

El problema

El sitio corría en Vercel con Supabase en la nube. Funcionaba, pero dependía de dos servicios de terceros. Yo ya tenía un servidor propio donde hospedo mis proyectos, y GoImport era el caso ideal para probarlo con un sistema real: mover un sitio en producción a mi propio entorno, con control total de los datos.

Las restricciones eran concretas:

  • 823 productos con fotos (unos 875 MB), más 67 productos mayoristas y 12 categorías.
  • 3 usuarios de administración que no podían perder el acceso.
  • Mi conexión de internet usa CG-NAT, así que no se pueden abrir puertos hacia el servidor.
  • El sitio tenía que seguir en línea durante todo el cambio.

Cómo lo encaré

Antes de tocar nada hice un inventario: tablas, políticas de seguridad (RLS), usuarios, el bucket de imágenes y cómo el frontend armaba las URLs de las fotos. Después tomé estas decisiones:

  • Supabase propio en Docker, aislado de mis otros proyectos, en vez de reescribir el backend. Así el frontend casi no cambió.
  • Configuración en tiempo de ejecución: el servidor genera el archivo con la dirección del backend. Cambiarla no obliga a reconstruir el sitio.
  • Proxy de imágenes: sirve las fotos en WebP y con el ancho que pide cada pantalla. Las URLs guardadas en la base se reconocen sin reescribir ninguna fila.
  • Cloudflare Tunnel para publicar el sitio. Resuelve el CG-NAT sin abrir puertos.
  • Migración repetible: los volcados de la base y la copia de imágenes se podían correr de nuevo, para sincronizar los datos nuevos antes del corte.

Un problema real: al descargar las imágenes de la nube con 8 conexiones en paralelo, el servicio respondía error 429 por exceso de pedidos. Bajé la concurrencia, agregué reintentos y dejé el script de modo que saltee lo que ya se copió.

Qué construí

  • La aplicación Express en un contenedor, Supabase en su propia red y el túnel de Cloudflare como única salida a internet.
  • Backups diarios con copia en otra máquina.
  • Monitoreo con 4 chequeos: web, mayorista, fotos y base de datos. El chequeo de la base consulta una fila real, no solo si el servidor responde.
  • Un interruptor de suspensión reversible: con una variable de entorno, todo el sitio responde 503 con una página neutra, sin tocar la base ni los archivos.

Resultados

Qué Antes Después
Dónde corre Vercel y Supabase en la nube Servidor propio con Docker
Productos 823 823, más 67 mayoristas y 12 categorías
Fotos 823 objetos, unos 875 MB 823 objetos, verificados a través del proxy
Usuarios de administración 3 3, con su acceso restaurado
Memoria del Supabase Stack completo, unos 2 GB Unos 650 MB, apagando 5 contenedores que no se usan
Copias de seguridad Sin documentar Diarias, propias, en otra máquina

El proyecto en la nube se eliminó el mismo día de la migración, después de guardar una copia final.

Qué aprendí

  • Medir antes de decidir. Medí cuánta memoria usa cada contenedor y apagué los que no hacían falta.
  • Reiniciar no recarga la configuración. docker restart no vuelve a leer el archivo de variables: hay que recrear el contenedor. Quedó anotado para no repetir el error.
  • Dejar todo escrito. Cada problema que resuelvo queda anotado con su síntoma, su causa y su solución.
CSSJavaScriptHTMLPostgreSQLExpressSupabaseDocker
Sitio

Escribime