Skip to content
Volver al blog
GCP
BigQuery
Cloud Migration
Data Engineering

Mi Experiencia Migrando de On-Premise a Google Cloud

Lecciones aprendidas (y errores costosos) al mover una infraestructura de datos legada a GCP, sin interrumpir producción.

2 de abril de 202510 min de lectura

Migrar una infraestructura de datos legada a la nube es uno de esos proyectos que siempre dura el triple de lo estimado. Este artículo cuenta lo que hice bien, lo que hice mal, y qué haría diferente hoy.

El contexto

Arquitectura de migración on-premise a Google Cloud Platform

La empresa donde trabajé tenía todo on-premise: un data warehouse PostgreSQL con ~2 TB de datos históricos, scripts ETL en cron jobs de Linux, y dashboards en Metabase apuntando directamente a producción. La decisión de migrar a GCP fue técnica y económica — los costos de mantenimiento del hardware eran insostenibles.

Fase 1: Inventario (lo que más subestimé)

Antes de mover una sola tabla, dediqué tres semanas solo a documentar:

  • ¿Qué tablas tiene cada esquema?
  • ¿Quién las consulta y con qué frecuencia?
  • ¿Cuáles tienen dependencias circulares?
  • ¿Qué scripts ETL están activos vs zombies?
-- Query para identificar tablas más consultadas en los últimos 90 días
SELECT 
    schemaname,
    tablename,
    n_live_tup as filas_estimadas,
    last_analyze,
    seq_scan as escaneos_secuenciales
FROM pg_stat_user_tables
ORDER BY seq_scan DESC;

Este inventario salvó el proyecto. Descubrimos que el 40% de las tablas no tenían queries en los últimos 6 meses — migrarlas habría sido tiempo desperdiciado.

Fase 2: La estrategia de migración

Elegí el patrón Strangler Fig: en lugar de reescribir todo de golpe, fui migrando tabla por tabla mientras producción seguía funcionando en on-premise.

On-Premise (PostgreSQL)
    ↓
    ├── Tablas activas → BigQuery (migración progresiva)
    └── Dashboards → apuntan a BigQuery cuando la tabla está lista

Duración: 4 meses
Sin downtime

Errores costosos (para que no los repitas)

Error 1: No considerar los tipos de datos

PostgreSQL y BigQuery no son 100% compatibles. El campo TIMESTAMP WITH TIME ZONE se convierte en DATETIME en BigQuery, perdiendo la información de zona horaria.

# El problema: BigQuery no tiene TIMESTAMPTZ nativo
# La solución: normalizar todo a UTC antes de cargar

def normalizar_timestamp(ts: datetime, tz_origen: str) -> datetime:
    tz = pytz.timezone(tz_origen)
    return tz.localize(ts).astimezone(pytz.UTC).replace(tzinfo=None)

Error 2: Ignorar el costo de las queries durante el desarrollo

BigQuery cobra por datos escaneados. Durante la fase de desarrollo, sin LIMIT ni particionamiento, quemé ~$300 USD en una semana de pruebas.

Regla que aplico ahora: Toda tabla nueva en BigQuery va particionada por fecha desde el día uno.

Error 3: No preparar a los usuarios finales

Los analistas acostumbrados a SQL de PostgreSQL se perdieron con las diferencias de BigQuery (sin ILIKE, DATE_TRUNC diferente, etc.). Habría ahorrado mucho tiempo con un taller de 2 horas al inicio.

Lo que funcionó muy bien

Google Cloud Platform

Cloud Composer (Airflow managed): Reemplazar los cron jobs por DAGs de Airflow fue la mejor decisión. Visibilidad completa, reintentos automáticos, y alertas por email cuando algo falla.

dbt para transformaciones: Versionar las transformaciones SQL en Git cambió completamente la dinámica del equipo. De "quién tocó esta vista y por qué" a "el PR está en revisión".

Resultado final

  • Costos de infraestructura: -60% vs on-premise
  • Tiempo de carga del dashboard principal: de 45s a 8s (particionamiento + clustering en BigQuery)
  • Incidentes de datos en producción: de ~4/mes a ~0.5/mes

La migración no fue perfecta, pero valió cada hora invertida.