Arquitectura de Data Extension: las elecciones de schema con las que vivís
Cada otro sistema de Marketing Cloud lee o escribe Data Extensions. Acertá el schema en bootstrap y el tenant opera limpio por años; equivocate y cada SQL Activity, cada Lookup de AMPscript, cada decision-split de Journey hereda el desastre. Diez items de production-note sobre naming, primary keys, tipos de columna, retención, y las elecciones estructurales que se componen.
Los Data Extensions son la fundación de cada otro sistema en Marketing Cloud. Las SQL Activities los querean. AMPscript los lee en render time. Los scripts SSJS los leen y escriben. Journey Builder rutea destinatarios a través de ellos. El reporting agrega desde ellos. Acertá la arquitectura de DE en bootstrap y el tenant opera limpio por años; equivocate y cada otro sistema hereda el desastre — cada query SQL carga el mismo LTRIM(RTRIM(CAST(... AS NVARCHAR(255)))) porque el tipo de SubscriberKey no se pineó, cada AMPscript lee una columna de DE que es NULL la mitad del tiempo porque la SQL Activity de audience-build no fue disciplinada.
Diez elecciones arquitectónicas que Cleon ha visto componerse a lo largo de rollouts multi-tenant. Cada una está apareada con la pregunta a responder en bootstrap y el costo de equivocarse. Mismo framing que los Gotchas de Config, más angosto en alcance a la capa de DE específicamente.
Las elecciones arquitectónicas
1. Cuatro roles de DE, cuatro prefijos de naming — elegidos una vez
Cada Data Extension cumple uno de cuatro roles. El Style Guide de SQL lista la convención de prefijo; este artículo es donde se justifica la convención.
| Rol | Prefijo | Qué contiene | Lifecycle |
|---|---|---|---|
| Master | DE_ | Data de subscriber propio; la fuente canónica de una entidad | Larga duración; updates vía SQL Activities controladas |
| Staging | de_stg_ | Resultado intermedio computado; seguro de truncar | Reconstruido en cada corrida; nunca leído por sends downstream directamente |
| Log | de_log_ | Registros append-only de corrida; instrumentación | Larga duración pero alto volumen; necesita política de retención |
| Lookup | de_lookup_ | Data de referencia / config; marketing edita sin SQL | Larga duración; bajo volumen; mantenido manualmente |
Elegir el prefijo importa en bootstrap porque retrofittearlo es brutal. Un tenant con 200 DEs nombrados inconsistentemente no puede renombrarse en batch (las Send Definitions, Automations, AMPscript, y Journeys todos sostienen referencias a DE por nombre). La convención Cleon: prefijo en la creación, documentá la convención en el runbook del equipo, cada code review verifica que el prefijo matchee el rol.
2. Sendable vs no-sendable — declarado, no implícito
Un DE es "sendable" cuando tiene una columna mapeada a SubscriberKey y un checkbox encendido en las propiedades del DE. Los DEs sendable se vuelven la fuente de las Send Activities; los DEs no-sendable son todo lo demás (staging, logs, lookups, data de referencia que no maneja un send).
La falla del hand-off: alguien necesita mandar a "todos los subscribers
en de_stg_active_recent". El DE no fue creado como sendable. El "fix" es
recrearlo (sendable no se puede togglear después de creado), que rompe
cada Automation downstream que referencia el nombre viejo del DE. El
equipo hace un DE sendable paralelo con una variación leve del nombre,
los dos DEs existen para siempre, cada code review futuro se pregunta
cuál es el actual.La defensa: cuando creás cualquier DE, decidí sendable-vs-no en el momento de la creación. Documentá el rol en la descripción del DE. Los DEs sendable solo deberían ser los que manejan Send Activities directamente — nombres estilo de_send_audience_* que hacen el rol visible desde una lista.
3. Tipo de SubscriberKey pineado a NVARCHAR(254) (o matcheado al origen)
SubscriberKey es la columna sobre la que cada DE joinea, y su tipo declarado determina si los joins funcionan sin coerción. El default de MC es NVARCHAR(254) (efectivamente ilimitado). Algunos tenants lo pinean a un tipo más angosto (NVARCHAR(50)) esperando ganancias de performance — las ganancias no se materializan, los joins arrancan a fallar cuando un origen downstream entrega una key más larga, y el casting se vuelve obligatorio en cada query.
La convención Cleon: NVARCHAR(254) en cada columna SubscriberKey, declarado en la creación del DE. Lo mismo para EmailAddress. El patrón estándar de join LTRIM(RTRIM(CAST(... AS NVARCHAR(255)))) de los gotchas de SQL se vuelve innecesario cuando los dos lados del join ya son el tipo correcto.
4. Primary key configurada en la creación — no después de la primera fila
Las primary keys en DEs son como MC determina qué filas son "la misma" para operaciones de upsert / update / dedup. Seteá la PK equivocada (o ninguna PK) y UpsertData inserta duplicados en silencio — el modo de falla que tanto el snippet de debugging de AMPscript como el snippet de debugging de SSJS diagnostican.
Reglas de PK:
- SubscriberKey es la PK en DEs keyeados por subscriber.
- Los DEs de log son PK-less append-only (o usan un GUID sintético).
- PKs compuestas (SubscriberKey + Date) para DEs de snapshot que
capturan estado en un momento dado.
- Los DEs de lookup tienen PK en la dimensión que se busca (ej.
TierCode, RegionCode).La UI de MC permite crear un DE sin especificar PK y agregar una después — pero agregar una PK a un DE poblado que tiene filas duplicadas para la key elegida falla. Seteá la PK en la creación, mientras el DE está vacío. Si descubrís que la PK está mal después de que el DE tiene data, estás reconstruyendo (truncar + reinsert de filas dedupeadas + setear la PK).
5. Tipos de columna declarados específicamente — no defaults NVARCHAR(4000)
La UI de MC defaultea las columnas de texto nuevas a NVARCHAR(4000). Esto es conveniente en la creación y desastroso a escala:
- El costo de storage es proporcional al ancho declarado incluso cuando los valores reales son cortos.
- El límite de 4000 chars trunca silenciosamente JSON / HTML / valores serializados pegados que lo excedan.
- La eficiencia del índice se degrada cuando las keys de join son muy anchas.
La convención Cleon para anchos de columna de texto:
- SubscriberKey NVARCHAR(254) # estándar de MC
- EmailAddress NVARCHAR(254) # RFC 5321 max + headroom
- FirstName / LastName NVARCHAR(50) # de sobra para cualquier nombre real
- Status / Tier NVARCHAR(20) # corto, vocabulario controlado
- Código de país NVARCHAR(2) o 3 # ISO-3166
- URLs NVARCHAR(2048) # max largo práctico de URL
- Comentarios free-text NVARCHAR(1000) # capear para evitar abuso de pegar payloadPineá los tipos en la creación. La falla del hand-off es un DE con todo NVARCHAR(4000) joineándose a un DE master con tipos correctos — MC tira un error de Conversión sobre el cast implícito, o peor, trunca silencioso.
6. Política de retención en la creación del DE, no en "nos estamos quedando sin espacio"
Los DEs crecen. Los DEs de log que capturan cada Send + Open + Click pueden llegar a cientos de millones de filas. Los snapshots de SDV guardados en de_log_sdv_* acumulan una fila por send-por-subscriber. Sin política de retención, el tenant acumula años de data histórica que nadie querea pero todos pagan.
La convención Cleon para retención por rol:
- de_log_ssjs_runs 90 días (rolling)
- de_log_ssjs_errors 180 días (los errores son oro de diagnóstico)
- de_log_sf_writes 180 días (audit trail)
- de_log_email_events 1 año mínimo (compliance + reporting)
- de_log_sdv_sent 2 años mínimo (historial CAN-SPAM de consent)
- de_stg_* truncate en cada corrida
- DEs Master sin rolling; archivar manualmente al borrarSeteá la retención vía Data Retention Policy en la creación del DE. Agregar retención a un DE poblado que ya tiene varios años causa un evento de mass-delete que puede lockear el DE por horas; configurá la retención en día 1.
7. Las relaciones sub-DE son por convención, no enforced
Marketing Cloud no tiene enforcement de foreign-key entre DEs. Una fila en de_log_ssjs_runs referencia un SubscriberKey que puede o no existir en _Subscribers. Una fila en un DE hijo referencia un padre que puede o no existir. No hay chequeo de integridad; nada alerta cuando una referencia queda colgada.
La convención Cleon: documentá las relaciones parent-child en la descripción del DE y tené una SQL Activity scheduleada que audite huérfanos. Un row count semanal a de_log_orphans por par de DE hace visible la integridad del data sin necesitar enforcement de FK en la capa de storage.
8. Shared DEs (Enterprise 2.0) — con moderación, documentados, owned
El sharing de data cross-BU pasa vía Shared DEs. El patrón es legítimo pero alto-riesgo: ¿qué BU escribe? ¿qué BUs leen? ¿qué pasa cuando el escritor se decomisiona? Ver arquitectura de BU — patrones a preferir.
Checklist de creación de Shared DE (convención Cleon):
- [ ] BU owner documentada (la que escribe)
- [ ] BUs reader documentadas (las que leen)
- [ ] Review de schema en la creación (sin Shared DEs de forma aleatoria)
- [ ] Política de retención explícita (los Shared DEs seguido sobreviven
a sus escritores)
- [ ] Plan de migración si la BU owner alguna vez se decomisiona
- [ ] Convención de naming incluye prefijo "Shared" (ej. shared_DE_*)Un Shared DE sin ownership documentada es un huérfano-en-espera. El equipo que lo escribió se va; las BUs dependientes siguen leyendo; nadie sabe quién puede cambiar el schema. La convención de naming hace visible la cualidad Shared de un vistazo.
9. La nullability de columna es una decisión, no un default
Cada columna tiene un checkbox Nullable en la UI de creación del DE. Defaultear todo a Nullable es conveniente pero pierde información — al leer una fila, no podés saber si un NULL significa "sin valor" o "nunca lo coleccionamos". La falla del hand-off es AMPscript downstream con IF Empty(@x) defaulteando NULLs y completes parciales al mismo fallback, ocultando la diferencia.
La convención Cleon: declarar nullability explícitamente por columna en la creación del DE. Columnas de identidad requeridas (SubscriberKey, EmailAddress) NOT NULL. Atributos opcionales (MiddleName, SecondaryEmail) Nullable. Columnas de status con un valor "desconocido" significativo tienen un default NOT NULL ('Unknown') en vez de permitir NULL.
10. Evolución de schema: aditiva solamente, nunca renames silenciosos
Una vez que un DE tiene consumidores downstream (SQL Activities, AMPscript, Journeys), los cambios de schema son visibles a lo largo del tenant. Agregar columnas es seguro; renombrar una columna rompe cada consumidor que referencia el nombre viejo; sacar una columna rompe cada consumidor que la referencia para nada.
La disciplina de migración de Cleon:
1. NUNCA renombrar una columna en producción. Agregá una columna nueva
con el nombre nuevo, migrá los consumidores downstream para leer la
columna nueva, después depreciá la columna vieja (marcala como
"deprecated" en la descripción pero dejala poblada por una ventana
de auditoría).
2. NUNCA sacar una columna sin un período de deprecación. Una remoción
que rompe un consumidor se encuentra en dev; una remoción que rompe
cinco consumidores se encuentra en producción a las 11pm.
3. Las columnas NUEVAS se agregan al final de la lista de columnas
(algunos consumidores API legacy se preocupan por el orden de columnas).
4. Cada cambio de schema documentado en el runbook del equipo con una
fecha, los consumidores que necesitaron update, y la ventana de
deprecación.La entrada del runbook es el recibo. Seis meses después de que se deprecó una columna, el runbook te dice si es seguro borrarla; sin el runbook, la respuesta es "no sé, esperemos otros seis meses" para siempre.
Cierre
Las decisiones de arquitectura de Data Extension no tienen una respuesta única satisfactoria — la elección "correcta" depende del perfil de volumen del tenant, la disciplina del equipo operacional, y los sistemas downstream que dependen de ella. El tema compartido a lo largo de estos diez items: en bootstrap, cada elección es reversible a bajo costo; seis meses adentro, cada elección es reversible a alto costo; dos años adentro, la mayoría de las elecciones son efectivamente permanentes.
La disciplina que previene los peores outcomes es un checklist de creación de DE enforced en code review — prefijo, sendable-o-no, PK, tipos de columna, política de retención, nullability, BU owner (para Shared DEs). El checklist de Cleon vive en el runbook del equipo al lado de los procedimientos de arquitectura de BU y SAP.
Si encontrás un patrón de arquitectura de DE que mordió a tu equipo y no está acá — escribinos a hello@wearecleon.com. Lo agregamos, con crédito.
Referencia: