RePlaya: reproducción de sesiones de navegador autoalojada sobre streams de S2

Fuentes: RePlaya: self-hosted browser session replay backed by S2 streams
Imagen generada por IA con el prompt: Minimalist dark UI illustration of a session replay dashboard with a timeline scrubber, soft purple accents, clean tech editorial style
Imagen generada con IA

RePlaya es una herramienta de código abierto y autoalojada para grabar y reproducir sesiones de navegador que utiliza streams de S2 como única capa de almacenamiento. Cada sesión se captura como un único stream S2 de tipo append-only, lo que elimina la necesidad de bases de datos, buses de mensajes, object stores o índices de búsqueda separados que suelen requerir los backends de replay convencionales. Como los streams de S2 pueden leerse en tiempo real mientras se escriben, RePlaya puede reproducir sesiones en directo mientras el visitante aún está en la página, además de reproducir sesiones ya finalizadas.

El proyecto se apoya en rrweb para la captura de eventos en el navegador. Basta con añadir un pequeño fragmento de JavaScript al sitio para iniciar la grabación; los eventos rrweb se anexan al final del stream de la sesión a través de la Producer API de S2, que aplica batching con backpressure y confirma cada lote una vez durable. Los eventos rrweb de gran tamaño se fragmentan en varios registros S2 y se reconstruyen al leerlos. Los streams usan el modo de timestamping client-require, de forma que el tiempo de captura rrweb se preserva en el timestamp S2 de cada registro y se recupera como línea de tiempo de scrub.

Para ejecutar RePlaya se necesitan un token de acceso de S2 y un basin. La configuración se introduce en .env.local con variables para el token, el basin, el prefijo de stream y el puerto. El basin se crea en el primer uso con los valores por defecto de RePlaya. El panel de control muestra una health pill con el basin y los endpoints S2 efectivos. Los desarrolladores pueden apuntar RePlaya a S2 Cloud o a un despliegue autoalojado de s2-lite fijando explícitamente los endpoints de cuenta y basin.

La instalación de dependencias y el arranque del servidor de desarrollo se realizan con pnpm; la API corre en el puerto 8787 y el panel Vite en el 5173. Una página /recorder-test permite generar grabaciones de prueba sin instrumentar otra aplicación. Para producción se puede compilar y servir todo desde Express en un único puerto.

El grabador enmascara por defecto los valores de inputs, selects y textareas (maskAllInputs de rrweb), de modo que las pulsaciones nunca llegan al servidor. El enmascaramiento puede desactivarse por página para herramientas internas. Las zonas sensibles del DOM se pueden envolver con la clase replaya-block para omitirlas, o con replaya-ignore para ignorar los cambios de un subárbol. El navegador nunca recibe el token de S2; todas las lecturas y escrituras pasan por el servidor de RePlaya.

Frente a un backend de replay típico —que suele necesitar bus de mensajes, almacén analítico, base de datos relacional, object store e índice de búsqueda—, RePlaya se reduce a un servidor Node y S2. El live tail funciona sobre el mismo stream que almacena la grabación. En producción, las rutas del colector se exponen públicamente, mientras que el panel y las APIs de lectura permanecen privadas tras una capa de acceso. El proyecto exige NODE_ENV=production, REPLAYA_PROJECT_KEY, REPLAYA_APPEND_TOKEN_SECRET y REPLAYA_ALLOWED_CAPTURE_ORIGINS para activar la autenticación de ingesta y las restricciones por origen.