← SCRAM AI Lab

Herramientas IA

Migración Mautic → CRM propio sin downtime

Estrategia técnica de dual-write y proxy edge para migrar de Mautic a un CRM propio sin pérdida de prospectos, inconsistencia de datos ni caída operativa.

May 21, 2026

438 lecturas

Migración Mautic → CRM propio sin downtime

El cutover hard es el patrón que te corre el director comercial al día siguiente

Llevamos cinco años viendo migraciones de Mautic terminar mal: cutover de viernes en la noche, lunes el equipo de marketing descubre que 8% de los contactos no llegaron, 15% de los segments se rompieron porque los filtros no mapean uno-a-uno, y el formulario de la landing principal estuvo apuntando al endpoint viejo durante 36 horas. El patrón que sí funciona tiene tres fases y dura un mes — pero nadie te despierta a las 3 AM.

¿Cómo migrar de Mautic a un CRM propio sin perder leads en el proceso?

Para migrar de Mautic a un CRM propio sin perder prospectos, se debe implementar una arquitectura de escritura dual asíncrona mediante colas de mensajes durante treinta días, complementada con redirecciones perimetrales 301 en el proxy inverso. Este esquema garantiza que los formularios activos sigan respondiendo mientras el nuevo sistema valida la integridad de los datos.

Comparativa de estrategias de migración

La elección de la técnica define el riesgo operativo del negocio. La siguiente matriz resume las tres metodologías más comunes observadas en despliegues corporativos:

Criterio Hard Cutover (Fin de semana) Export / Import Manual Dual-Write con Shadow Period
Tiempo de inactividad De 12 a 48 horas Variable (acumula retraso) Cero tiempo de inactividad
Riesgo de pérdida de leads Crítico (endpoints rotos o desalineados) Alto (desfase por cargas batch) Nulo (respaldo en cola asíncrona)
Complejidad técnica Baja en código, extrema en soporte Baja a media (scripts ad-hoc) Media a alta (requiere worker/proxy)
Capacidad de rollback Compleja o destructiva Inconsistente Inmediata (cambio de lectura en 5 min)

Fase 1: Dual-write con CRM nuevo leyendo

Los primeros 15 días el CRM nuevo es la fuente de verdad para lectura, pero todo lo que se escribe (forms, tracker, sync ERP) se duplica a Mautic en background. Mautic queda en read-only para UI humana — nadie puede tocarlo manualmente. Esto compra ventana de rollback: si algo explota, apuntas las lecturas a Mautic en 5 minutos.

// services/contact-write.service.ts
async function captureContact(data: ContactInput) {
  // Primario: CRM nuevo
  const contact = await prisma.crmContact.create({ data });

  // Espejo a Mautic (best-effort, no bloquea)
  this.mauticMirrorQueue.add('mirror-contact', {
    crmId: contact.id,
    email: data.email,
    phone: data.phone,
    payload: data,
  }, { attempts: 3, backoff: 'exponential' });

  return contact;
}

Fase 2: Backfill batch con dedup

En paralelo, un job nocturno baja contactos históricos de Mautic en batches de 10K. La parte crítica es la deduplicación compuesta: email exacto OR phone normalizado (sin lada, sin espacios). Mautic permite duplicados; tu CRM nuevo no debe.

async function backfillBatch(offset: number) {
  const mauticContacts = await mautic.getContacts({
    limit: 10000,
    offset,
    orderBy: 'date_modified',
  });

  for (const m of mauticContacts) {
    const phoneNorm = normalizePhone(m.phone); // +52 5512345678
    const existing = await prisma.crmContact.findFirst({
      where: {
        OR: [
          { email: m.email.toLowerCase() },
          phoneNorm ? { phone: phoneNorm } : undefined,
        ].filter(Boolean),
      },
    });

    if (existing) {
      await prisma.crmContact.update({
        where: { id: existing.id },
        data: { mauticId: m.id, ...mergeFields(existing, m) },
      });
    } else {
      await prisma.crmContact.create({ data: mapMauticToCrm(m) });
    }
  }
}

Números reales del caso AWALAB: 47K contactos, 12K segments, 6 horas de ejecución total. El cuello de botella no fue Postgres ni Mautic — fue la normalización de teléfonos con libphonenumber para detectar duplicados.

El desafío específico de los identificadores en LATAM

En bases de datos de México y América Latina, el identificador principal para ventas operativas suele ser WhatsApp antes que el correo electrónico. Mautic almacena teléfonos en texto libre, lo que genera variantes de un mismo número: formatos locales de diez dígitos, entradas con prefijo internacional +52, o registros antiguos que arrastran el prefijo móvil 1 eliminado por el IFT en 2019. Si no se homogeniza bajo el estándar internacional E.164 durante el backfill, el CRM generará cuentas duplicadas para el mismo prospecto y fragmentará las conversaciones comerciales.

Fase 3: Apagar Mautic con redirect 301

Después de 30 días de dual-write sin incidentes, dropeamos las escrituras a Mautic. Los endpoints viejos (/form/submit/mautic, /mtc.js) reciben redirect 301 a los equivalentes del CRM nuevo. Los 301 los procesa Traefik en el edge sin tocar Mautic — para entonces Mautic ya está apagado, solo Traefik conoce el mapeo.

# traefik dynamic config
http:
  routers:
    mautic-legacy:
      rule: "Host(`mautic.scram2k.com`) || PathPrefix(`/mtc.js`)"
      service: noop@internal
      middlewares: [redirect-to-crm]
  middlewares:
    redirect-to-crm:
      redirectRegex:
        regex: "^https://mautic\\.scram2k\\.com/(.*)"
        replacement: "https://api.scram2k.com/v1/tracker/$1"
        permanent: true

Qué puede salir mal en producción (y cómo mitigarlo)

Incluso con arquitectura dual-write, existen puntos ciegos técnicos que conviene monitorear:

  • Sobrecarga de la cola de sincronización: Si la API de Mautic responde lento por consumo intensivo de MySQL, la cola en BullMQ o Redis puede saturar memoria. Es indispensable configurar retries exponenciales limitados a 3 intentos y enviar los eventos fallidos a una cola Dead-Letter (DLQ) para auditoría manual.
  • Discrepancias en reglas de segmentación: Mautic procesa segmentos dinámicos mediante cron jobs en background (`mautic:segments:update`). El nuevo CRM probablemente utilice vistas materializadas de SQL o disparadores reactivos. Valida que las condiciones relacionales (como compras en los últimos 30 días) arrojen exactamente el mismo conteo en ambos sistemas antes de deshabilitar Mautic.
  • Cookies de rastreo huérfanas: Los usuarios que visitaron el sitio antes del corte conservarán la cookie de sesión de Mautic. El script sustituto debe leer esa cookie vieja, extraer el ID de tracking histórico y asociarlo al nuevo esquema analítico antes de descartarla.

El anti-patrón que vimos morir

Equipo que conozco intentó "lift and shift" en un fin de semana: export CSV de Mautic, import al CRM nuevo, apagar Mautic. Resultado: 12% de contactos con teléfono malformado quedaron como duplicados, segments dinámicos se convirtieron en listas estáticas (perdiendo la lógica), tracking JS apuntaba a endpoint inexistente por 4 días hasta que alguien notó que el formulario de demo no estaba capturando leads. Cutover hard sin shadow period es la receta para el postmortem.

La pregunta de seguimiento: ¿cuánto del código de espejo a Mautic se reusa para futuras migraciones (HubSpot, Salesforce)? Spoiler: el 80% si abstraes el adapter desde el día uno.

mautic
migracion
crm
← Volver a SCRAM AI Lab