(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo calcular tasas de retención en Real-Time Analytics: paso a paso

João Barros 08 de October de 2026 3 min de lectura

Vamos a crear un pipeline sencillo para calcular tasas de retención en Real-Time Analytics: medir cuántos usuarios que realizaron una acción en el día de referencia vuelven en días posteriores. Este cálculo es esencial para evaluar fidelidad, monitorizar A/B tests y medir el impacto de cambios de producto en tiempo real. La idea básica es formar cohortes por el primer día de acción y luego medir, para cada día relativo (day_index), cuántos usuarios de esa cohorte regresaron. En escenarios reales, es común observar retenciones de day 1 en el orden del 20–60% dependiendo del producto, y retenciones a 7 días de 5–30%.

Pre-requisitos

  • Fuente de eventos en streaming (por ejemplo, Event Hubs, Kafka u otra) con eventos que contengan user_id y event_timestamp. Idealmente cada evento tiene también event_id para deduplicación.
  • Plataforma de Real-Time Analytics que acepte consultas en streaming (por ejemplo, Azure Data Explorer / Kusto u otro motor compatible). Para grandes volúmenes considere soportes de stateful processing.
  • Herramienta para visualizar resultados (Power BI, dashboards o query explorer) que soporte tablas agregadas y heatmaps para cohortes.

Paso 1: Normalizar eventos y crear marcación de día

Es importante convertir timestamps a una marca de día consistente (UTC o una zona horaria elegida) para comparar días. La normalización evita que eventos cerca de medianoche queden asignados a días distintos por husos horarios. En el ejemplo en KQL transformamos el timestamp bruto a datetime y extraemos event_day con startofday(). En entornos con millones de eventos/día, haga esta transformación lo antes posible (en la ingestión) para reducir coste de procesamiento posterior.

// Exemplo KQL para normalizar eventos
Events
| where event_type == "action"
| extend event_time = todatetime(event_timestamp)
| extend event_day = startofday(event_time)
| project user_id, event_day

Paso 2: Identificar el primer día de evento por usuario (cohorte)

Para calcular retención necesitamos la cohorte: el primer día en que el usuario realizó la acción. Agrupamos por user_id y tomamos el mínimo event_day. En muestras controladas, si tenemos 1.000 usuarios con primera acción en 2026-10-01, ese cohort_day tendrá cohort_users = 1000. En producción, cuando se trata con millones de usuarios, es común usar aproximaciones (por ejemplo approx_dcount) para reducir coste, aceptando un error de 0.5–1%.

// Calcular la cohorte (primer día por user)
let FirstDay =
    Events
    | where event_type == "action"
    | extend event_time = todatetime(event_timestamp)
    | extend event_day = startofday(event_time)
    | summarize cohort_day = min(event_day) by user_id;

FirstDay

Paso 3: Asociar eventos a la cohorte y calcular diferencia en días

Unimos los eventos con la cohorte para cada usuario y calculamos el día relativo (day_index) desde la cohorte — por ejemplo, 0 es el día de la primera acción, 1 es el día siguiente, etc. Esto permite agregar por day_index y ver la evolución a lo largo del tiempo. En el ejemplo limitamos la ventana a 30 días, pero se puede extender a 90 días o a 180 días según necesidad. Atención al coste: mantener estado para muchas cohortes y ventanas largas incrementa almacenamiento y latencia.

// Eventos con day_index relativo a la cohorte
let EventsWithCohort =
    Events
    | where event_type == "action"
    | extend event_time = todatetime(event_timestamp)
    | extend event_day = startofday(event_time)
    | project user_id, event_day
    | join kind=inner (
        FirstDay
    ) on user_id
    | extend day_index = datetime_diff('day', event_day, cohort_day) * -1 // ou: toint((event_day - cohort_day) / 1d)
    | where day_index >= 0 and day_index <= 30 // limitar ventana, ex: 30 dias
    | summarize users_active = dcount(user_id) by cohort_day, day_index;

EventsWithCohort

Paso 4: Calcular tamaño de la cohorte y tasa de retención por día

Ahora calculamos el número total de usuarios en la cohorte (day_index == 0) y luego el porcentaje que volvió en cada day_index. Un enfoque sencillo es obtener CohortSize y hacer un join; otra es pivotar para construir una matriz cohorte x day_index, útil para heatmaps. Verifique siempre que retention_pct en day_index 0 sea 100% (o cerca, si usó aprox_count_distinct).

// Tamaño de la cohorte (día 0)
let CohortSize =
    EventsWithCohort
    | where day_index == 0
    | project cohort_day, cohort_users = users_active;

// Retención porcentual por cohorte y day_index
EventsWithCohort
| join kind=inner (CohortSize) on cohort_day
| extend retention_pct = todouble(users_active) / todouble(cohort_users) * 100.0
| order by cohort_day, day_index

Paso 5: Optimizar para Real-Time (ventanas incrementales y estado)

Para Real-Time Analytics, evite recomputar todo en cada nuevo mensaje. Use ventanas incrementales (tumbling o sliding) y mantenga un estado con agregados por (cohort_day, day_index). En soluciones como Azure Stream Analytics o jobs Kusto con update policies, procese por micro-batches (ej.: 5s–1min) y actualice tablas agregadas. Si tiene 10k cohortes activas y 30 días de ventana, tendrá hasta 300k combinaciones de estado—diseñe memoria y TTL adecuados.

// Pseudocódigo para actualización incremental (conceptual)
// 1) Ingerir nuevo lote de eventos
// 2) Calcular event_day y juntar con tabla FirstDay incremental
// 3) Actualizar agregación agreg_table (cohort_day, day_index) con nuevos user_ids únicos
// 4) Recalcular retention_pct solo para cohorts afectadas

Consejos prácticos: use deduplicación por (user_id, event_id) con TTL para evitar conteos inflados; cuando el volumen es muy alto, considere approx_dcount para users_active (error aceptable de 0.5%). Para latencia muy baja, mantenga un store de estado (ej.: Cosmos DB, KV store) que almacene el primer día por user_id y pequeñas agregaciones por cohorte que se incrementan en streaming.

Verificar el resultado

Valide que cada cohort_day tiene un cohort_users (day_index = 0) y que retention_pct es 100% en day_index 0. Pruebe con datos controlados: por ejemplo, cree 1.000 usuarios con eventos en el día 0; simule que 400 vuelven en el día 1 y 180 en el día 7. Se espera obtener retention_pct day1 = 40.0% y day7 = 18.0%. Verifique también contra duplicados: si un usuario genera 3 eventos en el día 1, solo debe contarse una vez (unique user).

Conclusión

Este proceso permite calcular tasas de retención en Real-Time Analytics, mostrando cohortes y retención por day_index para monitorización de producto. Siguientes pasos prácticos: ampliar la ventana a 90 días si necesita visibilidad a largo plazo, segmentar por propiedades (país, versión, canal) y crear visualizaciones en Power BI (heatmap + líneas de tendencia). Recuerde: deduplicación y elección entre conteo exacto y aproximado son decisiones clave para equilibrar coste, precisión y latencia. ¿Quiere experimentar segmentando por canal de adquisición en un ejemplo controlado de 1.000 usuarios para ver el impacto en las tasas de retención?