Módulo 4: Merge Avanzado y Fan-Out / Fan-In
Patrón: Combinar Fuentes con Combine
Descripción de la cápsula
El caso más útil de Merge en práctica: tienes datos en 2 fuentes (Sheet + CRM, API A + API B, DB + spreadsheet) y necesitas unirlos por un campo común. Equivale a un SQL JOIN, pero visualmente con nodos.
En esta cápsula vas a profundizar Combine en escenarios reales, los patrones para preparar datos antes del Combine, cómo manejar claves de match heterogéneas (un sistema usa email, otro user_id), y los workflows completos donde Combine es la pieza central.
Lo que vas a aprender
- ✅ Aplicar Combine en casos de negocio reales
- ✅ Preparar datos antes del Combine para matches limpios
- ✅ Manejar keys distintas entre fuentes
- ✅ Detectar inconsistencias entre fuentes con Keep Non-Matches
El caso clásico: enrichment
Caso: Sheet con leads básicos (nombre, email). CRM con datos extra (fuente, score, último contacto). Quieres combinarlos.
Workflow
[Schedule diario]
│
├─→ [Sheet: leer leads] ← Input 1: básicos
│
└─→ [HTTP: CRM API leads] ← Input 2: con datos extra
│
▼
[Merge: Combine Enrich Input 1 by email]
│
[Procesar leads enriquecidos]
Output: todos los leads del Sheet, enriquecidos con datos del CRM cuando hay match.
Preparar datos antes del Combine
Combine matchea exactamente. Diferencias sutiles rompen matches. Patterns para preparar:
Pattern 1: Normalizar formato del key
[Sheet read]
│
[Set: normalizar email]
email_normalized: {{ $json.email.toLowerCase().trim() }}
Hacer lo mismo en Input 2. Combine ahora matchea email_normalized.
Pattern 2: Convertir tipos
[API read]
│
[Set: convertir id]
id_str: {{ String($json.id) }}
Si Sheet tiene id como string y API como number, normalizar a uno.
Pattern 3: Resolver claves diferentes
Sheet usa email. API usa user_email. Mapear en el Combine:
- Input 1 Field:
email - Input 2 Field:
user_email
n8n compara los valores, aunque los nombres sean distintos.
Caso: detectar leads "huérfanos"
Caso: quieres encontrar leads que están en tu CRM pero no en el Sheet activo (probablemente dormidos, candidatos a reactivar).
[Sheet read activos]
│
├──┐
│ │
[API CRM read todos]
│ │
▼
[Merge: Combine Keep Non-Matches by email — solo los del Input 2 que no están en Input 1]
│
[Slack: "Lista de leads dormidos: ..."]
Output: leads en CRM no en Sheet activo → candidatos a campaña de reactivación.
Caso: validar consistencia entre sistemas
Caso: Sheet de inventory y API de Shopify deberían tener mismos productos. Detectar discrepancias.
[Sheet: productos en sheet]
│
├──┐
│ │
[Shopify API: productos]
│ │
▼
[Merge: Combine Keep Non-Matches by sku]
│
[Sheets: append "discrepancies.csv"]
│
[Slack: "Detectadas N discrepancias"]
Cada vez que corre, te reporta items que no matchean.
Caso: pricing dinámico con tabla externa
Caso: Webhook con pedido. Necesitas pricing actualizado desde Sheet de pricing dinámico.
[Webhook: pedido con product_id]
│
├──┐
│ │
[Sheet read: pricing.csv]
│ │
▼
[Merge: Combine Enrich Input 1 by product_id]
│
[Output: pedido + price actualizado]
Cada pedido se enriquece con el price actual del Sheet. Útil para reglas de pricing que cambian seguido.
Caso: agregar contexto desde múltiples fuentes
Pattern de 3+ fuentes:
[Webhook: lead]
│
├──[Combine 1: Lead + Clearbit data]
│ │
│ ├──[Combine 2: + datos de redes sociales]
│ │ │
│ │ ├──[Combine 3: + score interno]
│ │ ▼
│ │ [Resultado: lead super enriquecido]
Cascada de Combines, cada uno agregando una fuente.
Trampas comunes
Trampa 1: Whitespace en keys
Qué pasa: Sheet tiene email: "mike@nieva.team " (espacio al final). API tiene email: "mike@nieva.team". Combine no matchea.
Cómo evitar: Trim keys siempre antes de Combine.
Trampa 2: Capitalization
Qué pasa: Mike@nieva.team vs mike@nieva.team. No matchea.
Cómo evitar: toLowerCase todos los emails antes de Combine.
Trampa 3: Keys con tipos distintos
Qué pasa: Number vs string. 1 vs "1". No matchea.
Cómo evitar: Convertir explícitamente: String(id) o Number(id).
Trampa 4: Multiple matches in Input 2
Qué pasa: Input 1 tiene 1 lead con email X. Input 2 tiene 3 records con email X (duplicados). Output depende del modo — puede tener 3 items para ese lead o solo el primero.
Cómo evitar:
- Dedupar Input 2 antes del Combine
- O entender qué comportamiento esperas y validarlo con test
Trampa 5: Combine con datasets enormes
Qué pasa: Combine de 10,000 items × 10,000 items. n8n carga ambos en memoria.
Cómo evitar:
- Para volúmenes grandes, considera procesar en batches (SplitInBatches de Input 1, lookup en Input 2 por batch)
- O usar DB con JOIN nativo si es muy grande
Ejercicio: workflow Combine real
Objetivo: practicar con datos reales.
Tu tarea
-
Sheet A:
leads_basiccon columnasemail, name, source. Llena con 10 leads. -
Sheet B:
leads_scorescon columnasemail, score, last_activity. Llena con 7 emails (5 que matchean Sheet A, 2 que no). -
Workflow:
- Manual Trigger
- Sheet A read (Input 1)
- Sheet B read (Input 2)
- Combine Enrich Input 1 by email
- Slack: mensaje con cada lead + score (o "sin score" si no matchea)
-
Pruebas:
- Cambia uno de los emails a MAYÚSCULA. Verifica que no matchea.
- Agrega Set para normalizar (lowercase) antes del Combine. Verifica que ahora sí matchea.
Resumen y siguiente paso
- Combine es el patrón más útil de Merge en práctica
- Preparar datos antes (normalizar, convertir tipos)
- 3 casos comunes: enrichment, detectar huérfanos, validar consistencia
- Cascada de Combines para multi-source
- 5 trampas: whitespace, capitalization, tipos, multi-match, datasets enormes
Lo que sigue: Paralelismo con sincronización — el patrón Wait para esperar a múltiples ramas.
Creado: Mayo 11, 2026 Versión: 1.0