✈️ Pipeline de Datos de Vuelos: Arquitectura ELT con Procesamiento por Lotes
Un pipeline de datos que ingesta información de vuelos actuales desde OpenSky Network API utilizando procesamiento por lotes, implementando patrones modernos de Data Engineering con Airflow, dbt, SODA y BigQuery.
🎯 Filosofía del Proyecto: Decisiones de Arquitectura que Importan
Por qué ELT en lugar de ETL tradicional?
Decisión estratégica: Utilizar las capacidades de BigQuery para almacenamiento y consultas, mientras mantenemos las transformaciones locales con dbt.
# ❌ Enfoque ETL tradicional (evitado)
# 1. Extract → Pandas transformations → Load
# Problemas: Memory bottlenecks, escalabilidad limitada
# ✅ Enfoque ELT implementado
# 1. Extract → Load raw → Transform locally with dbt → Load transformed
# Beneficios: Separación clara de responsabilidades, BigQuery para storage optimizado
El procesamiento se realiza localmente usando dbt, pero aprovechamos BigQuery como almacén final optimizado para consultas analíticas.
Procesamiento por Lotes vs Streaming: Control de Costos
Principio: Procesamiento batch para optimizar costos, obteniendo datos actuales de la API pero procesándolos de forma controlada.
Aunque la API proporciona datos del momento actual, la estrategia de lotes permite:
- Control preciso de costos de BigQuery
- Procesamiento eficiente de volúmenes pequeños (promedio 11 vuelos en Perú)
- Evitar over-engineering para el contexto específico del país
Ventana Deslizante de 24 horas: Data Freshness Strategy
DELETE FROM `fly.current_flights_staging`
WHERE extracted_at < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
Rationale: Los datos de vuelos pierden relevancia rápidamente. Esta estrategia:
- Mantiene el dataset ágil y relevante
- Controla costos de almacenamiento
- Optimiza performance de queries
🔍 Validaciones Inteligentes:
Validación Geoespacial Contextual
# SODA check con contexto aeronáutico real
- invalid_count(baro_altitude) = 0:
valid_format: number_between -500 15000
name: "Altitud barométrica realista (-500m a 15000m)"
Por qué -500m a 15000m?
- -500m: Aeropuertos bajo el nivel del mar (Ej: región del Mar Muerto)
- 15000m: Límite práctico para aviación comercial (FL450)
- Esta validación no solo verifica el tipo de dato, sino también su coherencia operacional.
Freshness Crítico para Datos de Vuelo
- freshness(extracted_at) < 2h
- invalid_count(minutes_since_contact) = 0:
valid_format: number_between 0 120
Insight: En aviación, datos > 2 horas pierden relevancia operacional. Esta validación asegura que mantenemos información útil para análisis.
🚀 Transformaciones que Agregan Valor de Negocio
Enriquecimiento Inteligente: Flight Phase Detection
El modelo dbt no solo limpia datos, sino que infiere fases de vuelo:
-- Lógica de inferencia de fase de vuelo (simplificada)
CASE
WHEN on_ground THEN 'GROUND'
WHEN baro_altitude IS NULL THEN 'UNKNOWN_ALTITUDE'
WHEN baro_altitude < 1000 AND velocity > 50 THEN 'TAXI_TAKEOFF_LANDING'
WHEN vertical_rate > 500 THEN 'CLIMBING'
WHEN vertical_rate < -500 THEN 'DESCENDING'
WHEN baro_altitude > 10000 THEN 'CRUISE'
ELSE 'IN_FLIGHT'
END as flight_phase
Valor para el análisis: Permite análisis operacional como:
- Distribución de aeronaves por fase de vuelo
- Identificación de patrones de tráfico en tiempo real
- Alertas operacionales basadas en fase de vuelo
Composite Keys para Deduplicación Inteligente
- duplicate_count(flight_record_key) = 0
flight_record_key combina icao24 + extracted_at
, permitiendo:
- Múltiples registros del mismo vuelo en diferentes timestamps
- Deduplicación dentro de la misma extracción
- Trazabilidad temporal por aeronave
🏗️ Stack Tecnológico: Decisiones Justificadas
Astronomer Cosmos: dbt + Airflow Native Integration
from cosmos.config import ProfileConfig, ProjectConfig
DBT_CONFIG = ProfileConfig(
profile_name='fly_data_load',
target_name='dev',
profiles_yml_filepath=Path('/usr/local/airflow/include/dbt/profiles.yml')
)
Por qué Cosmos?
- Renderiza modelos dbt como tasks nativos de Airflow
- Dependency management automático
- Observabilidad unificada (logs, lineage, failures)
SODA para Validación Multi-Layer
Staged Validation Strategy:
- Source Layer: Validaciones de esquema y freshness
- Transform Layer: Validaciones de lógica de negocio post-dbt
# Source validation (technical)
- schema:
fail:
when required column missing: [icao24, callsign, ...]
# Transform validation (business logic)
- invalid_count(flight_phase) = 0:
valid_values: ['GROUND', 'CLIMBING', 'CRUISE', ...]
📊 Rendimiento del Pipeline
Prueba realizada: Pipeline procesando 8 vuelos completado en 1 minuto 29 segundos end-to-end.
Esto incluye:
- Extracción desde OpenSky API
- Carga a staging en BigQuery
- Validaciones con SODA
- Transformaciones con dbt
- Carga final
Contexto peruano: El promedio de vuelos simultáneos en Perú es de ~11 vuelos, comparado con países como España donde solo Madrid puede tener +300 vuelos. Esta diferencia justifica la estrategia de procesamiento por lotes y optimización de costos.
🎨 Configuración Rápida
Variables de Entorno Críticas
# OpenSky API (token temporal de 30min)
OPENSKY_TOKEN="your_token"
OPENSKY_CLIENT_ID="client_id"
OPENSKY_CLIENT_SECRET="j2Zfp78hJYR7aYI..."
# GCP Service Account path
GCP_SERVICE_ACCOUNT_PATH="/usr/local/airflow/include/gcp/service-account.json"
Stack Dependencies
# Core pipeline
astronomer-cosmos[dbt-bigquery]==1.0.3
soda-core-bigquery==3.0.45
protobuf==3.20.0
# API integration
requests
python-dotenv
🔧 Testing y Debugging
Comando de Testing Individual
# Test task específico sin afectar el scheduler
airflow tasks test fly create_fly_dataset 2025-06-07
# Test conexión SODA
soda test-connection -d fly -c include/soda/configuration.yml
# Test transformación dbt
dbt run --select current_flights --profiles-dir /usr/local/airflow/include/dbt/
📊 Métricas del Pipeline
- Latencia: ~1.5 minutos para 8 vuelos (end-to-end)
- Precisión: Validaciones SODA en múltiples capas
- Disponibilidad: Datos actuales (< 2 horas) garantizados
- Contexto: Optimizado para volumen peruano (~11 vuelos promedio)
Este proyecto demuestra cómo implementar un pipeline de datos moderno que no solo mueve datos, sino que agrega valor analítico real. La combinación de patrones ELT, validación multi-capa y enriquecimiento inteligente crea una base sólida para análisis avanzados.