Appearance
CRM Sync Service
Documentación técnica del servicio de sincronización continua de datos entre GoHighLevel (CRM origen) e imcrmdev (nuestro CRM, MongoDB).
Concepto
No es una migración one-shot. Es un servicio que se mantiene corriendo y trae cambios de GHL a imcrmdev cada N minutos. La primera pasada (modo full) trae todo el histórico; las siguientes (modo incremental o loop) solo traen lo que cambió.
Cliente actual
| Campo | Valor |
|---|---|
| Nombre | Trebol Insurance |
| Giro | Seguros (insurance) |
| GHL Sub-Account ID | SW4v78LtTjzKHd3cnJ48 |
| Timezone | US/Eastern |
| País | US (Miami, FL) |
Volumen estimado en origen
| Recurso | Total aproximado |
|---|---|
| Contactos | 44,918 |
| Oportunidades | 51,495 |
| Conversaciones | 44,909 |
| Mensajes | ~10× conversaciones (aprox 450k) |
| Custom Fields (definiciones) | 227 |
| Pipelines de ventas | 27 |
| Stages | ~250 (suma de todos) |
| Calendarios | múltiples (uno por usuario) |
| Usuarios | varios (admin + asesores) |
Modos de operación
| Modo | Cuándo usarlo |
|---|---|
full | Carga inicial, o cuando hay sospecha de inconsistencia. Ignora last_sync_at y trae todo. |
incremental | Pasada única que solo trae cambios desde el último sync exitoso por recurso. Ideal para cron / systemd timer. |
loop | Mantiene el proceso vivo: corre incremental cada --interval segundos. Ideal como contenedor restart: always. |
Estrategia general
- Aislamiento total: el servicio escribe a una instancia Mongo nueva (Docker, puerto
27019) — no toca la base de SEMTEC ni el dev actual. - Idempotente: cada documento sincronizado lleva
external_id(= GHL id). Las upserts son seguras de re-correr cuántas veces sea. - Resumible: dentro de una pasada
full, persiste el cursor de paginación. Si el script muere a mitad de la carga, retoma donde quedó. - Filtro server-side cuando aplica:
contacts/searchyopportunities/searchreciben filtrosdateUpdated > last_sync_atpara no traer todo en cada pasada. - Filtro client-side defensivo: si la API ignora el filtro, hacemos early-stop al ver un registro más viejo que
since. - Sin pérdida: el JSON original de GHL se preserva en
_ghl_rawpor documento.