Toda respuesta que da una plataforma de juego lleva un tiempo dentro. Una apuesta se aceptó en un instante, una sesión empezó en otro, una ronda se liquidó después, una ventana de bono se cerró, un mercado se suspendió, un bote acumuló, el día de un informe terminó, se escribió una línea de registro. Ninguno de esos tiempos es decoración: cada uno es una afirmación que el operador puede tener que defender algún día — ante un jugador con una reclamación, ante un auditor con una pregunta, ante una revisión de incidente que reconstruye lo ocurrido, o ante una conciliación que no cuadra.
El tiempo es además la única dependencia que una plataforma nunca deja de usar. Se lee en cada petición en lugar de invocarse de vez en cuando, no tiene endpoint de salud por defecto, y cuando está mal la plataforma no se detiene: sigue sirviendo, en silencio, con marcas de tiempo que ya no significan lo que suponen los registros que las rodean. Por eso el tiempo merece el mismo trato que un libro mayor: una sola fuente de verdad, una representación explícita, límites declarados y pruebas que reproduzcan el fallo.

Las cuatro partes de una afirmación temporal
“14:03:07” todavía no es una afirmación que alguien pueda comprobar. Una afirmación temporal defendible tiene cuatro partes, y una plataforma que deje cualquiera de ellas implícita acabará discrepando de sus propios informes.
| Parte | La pregunta que responde | Dónde falla cuando no está escrita |
|---|---|---|
| El reloj | Qué máquina, sincronizada con qué, dentro de qué tolerancia | Dos servicios ordenan los mismos eventos de forma distinta |
| La representación | Instante con desplazamiento, o hora local sin zona | Un tiempo guardado no puede situarse en una línea temporal después |
| La regla | Qué calendario, qué límite, inclusivo o exclusivo | Un corte aplicado de una forma en la API y de otra en el informe |
| La evidencia | Qué se registró, quién lo registró, cuánto se conserva | Una reclamación se resuelve con un registro que no muestra el desplazamiento |
El resto del artículo sigue esas cuatro partes en orden, porque los errores se acumulan: una fuente de reloj no escrita vuelve ambigua la representación, una representación ambigua vuelve indemostrable el límite, y un límite indemostrable convierte una conciliación rutinaria en una discusión.
Nombrar un reloj en el que la plataforma confíe
El Protocolo de Tiempo de Red es la respuesta habitual, y el RFC 5905 describe para qué sirve: NTP “se usa ampliamente para sincronizar los relojes de las computadoras en Internet”, y la versión 4 “incluye mejoras fundamentales en los algoritmos de mitigación y disciplina que extienden la precisión potencial a decenas de microsegundos con estaciones de trabajo modernas y redes locales rápidas”. Conviene leer esa frase con cuidado antes de citarla internamente: es una afirmación sobre la precisión que el protocolo puede alcanzar en condiciones favorables, no una promesa sobre una máquina virtual en un hipervisor cargado, detrás de un enlace saturado, con un demonio que lleva un mes consultando el mismo servidor.
De ahí se derivan cuatro reglas prácticas.
- Más de una fuente y un respaldo con nombre. Un único servidor de referencia es un punto único de fallo para algo de lo que depende cada petición. Una configuración de plataforma debería parecerse a un pequeño conjunto de fuentes, y esa configuración debería poder revisarse en el repositorio en lugar de haberse escrito una vez en un host en ejecución.
- Autenticar la fuente cuando la exposición lo justifique. El RFC 8915 especifica Network Time Security, que usa “Transport Layer Security (TLS) y cifrado autenticado con datos asociados (AEAD) para proporcionar seguridad criptográfica al modo cliente-servidor del Protocolo de Tiempo de Red (NTP)”. Chrony lo expone como la opción
ntsde una directivaserver, y su documentación advierte que, cuando la autenticación está activada, conviene desactivar las fuentes no autenticadas que de otro modo podrían usarse para influir en el reloj. - Dar el salto al arrancar y ajustar después por barrido. La directiva
makestepde chrony “fuerza a chronyd a dar un salto en el reloj del sistema si el ajuste es mayor que un valor umbral, pero solo si no hubo más actualizaciones de reloj desde que se inició chronyd que el límite indicado”. Su propia recomendación es que “en la mayoría de los sistemas es deseable dar el salto del reloj del sistema solo al arrancar, antes de iniciar programas que dependen de que el tiempo avance de forma monótona hacia adelante”. Una plataforma que da saltos a su reloj en operación normal ha decidido que un segundo puede repetirse o perderse mientras está funcionando. - Monitorizar la fuente de tiempo como una dependencia. Desviación y deriva por host, con alerta en un umbral más estrecho que el límite más fino que la plataforma declara, y tratado como motivo para retirar un host de las escrituras sensibles al tiempo en lugar de como un gráfico que alguien mirará después. Un host cuyo reloj está fuera de tolerancia no está “bien, solo un poco adelantado”: es un host que escribirá un registro que no coincide con el registro de al lado.
Guardar el instante, no la impresión
Una marca de tiempo es un instante con una relación declarada con el Tiempo Universal Coordinado. El RFC 3339, el formato de fecha y hora de Internet, es explícito en que sus valores expresan un desplazamiento respecto de UTC, y define una convención que conviene conocer: si se conoce la hora UTC pero no el desplazamiento local, el desplazamiento -00:00 significa exactamente eso y “difiere semánticamente de un desplazamiento Z o +00:00, que implican que UTC es el punto de referencia preferido para la hora indicada”. El mismo documento señala la propiedad que hace que valga la pena esa disciplina: si los valores comparten desplazamiento y precisión, se ordenan como texto en orden temporal.
El modo de fallo es el hábito contrario: guardar lo que mostraba la pantalla. Una hora local sin zona es irrecuperable una vez se pierde el desplazamiento. La documentación de PostgreSQL describe la mecánica sin adornos: si no se indica zona horaria en la entrada, se “asume que está en la zona indicada por el parámetro TimeZone del sistema”, y en cualquiera de los dos casos “el valor se almacena internamente como UTC y la zona indicada o asumida originalmente no se conserva”. La base de datos hace lo correcto con el instante y descarta el contexto humano, lo que significa que una regla que mencionaba una zona local tiene que reconstruirse a partir de otra cosa. También significa que la configuración de un servidor puede cambiar en silencio cómo se lee una marca de tiempo sin zona.
El RFC 9557, publicado en 2024, existe precisamente para esa brecha: extiende el RFC 3339 “para representar información adicional, incluida una zona horaria”, justamente porque las aplicaciones tratan “cada instante con un nombre de zona horaria asociado para tener en cuenta eventos como los cambios de horario de verano”. Se adopte o no ese formato, la regla que codifica es la que hay que seguir: guardar el instante y conservar el nombre de la zona junto a él cuando una regla se refería a una hora local, en lugar de un desplazamiento fijo calculado al escribirla.
Medir con un reloj que no se puede reajustar
En la mayoría de los hosts viven dos relojes, y la documentación de Go expone la distinción mejor que muchas especificaciones: “Los sistemas operativos proporcionan tanto un ‘reloj de pared’, sujeto a cambios por la sincronización del reloj, como un ‘reloj monótono’, que no lo está. La regla general es que el reloj de pared sirve para decir la hora y el reloj monótono para medir el tiempo”.
Esa división tiene una consecuencia operativa. Todo lo que mide un intervalo —un tiempo de espera, un retroceso de reintento, una ventana de limitación de tasa, una muestra de latencia, una cuenta atrás de sesión, un arrendamiento de bloqueo— debe regirse por una fuente monótona, o una corrección del reloj se convierte en un fallo: un salto hacia adelante expira trabajo que aún tenía tiempo, un salto hacia atrás hace que una duración transcurrida sea negativa. Todo lo que registra un hecho —aceptación, liquidación, acumulación— debe usar el reloj de pared, porque un instante tiene que ser comparable con otras máquinas.
Los dos también divergen al serializar, que es donde suele llegar el error a producción. La lectura monótona “no tiene significado fuera del proceso actual”, así que los codificadores de Go la omiten, y cada constructor de análisis crea un tiempo sin ella. Una duración guardada como diferencia de marcas de tiempo sobrevive por tanto a un reinicio del proceso como aritmética de reloj de pared, con el error que el reloj haya acumulado. Si el intervalo importa a través de un reinicio, conviene guardarlo como un instante límite en lugar de recalcularlo desde una hora de inicio.
Los navegadores trazan la misma línea: la especificación High Resolution Time del W3C define una fuente de tiempo con resolución sub-milisegundo “de modo que no está sujeta a la deriva ni a los ajustes del reloj del sistema”. Una telemetría del lado del cliente que mide duraciones con un reloj de pared está midiendo el reloj del dispositivo del jugador, no el de la plataforma.
Hay una trampa que ninguna disciplina del lado de la plataforma arregla, y merece figurar en las notas de aceptación en lugar de descubrirse en producción: en algunos sistemas el reloj monótono se detiene mientras la máquina está suspendida, así que una duración medida a través de una suspensión puede reportar menos tiempo del que realmente pasó.
Decidir qué hace un segundo intercalar en tu libro mayor
El Tiempo Universal Coordinado no es un simple recuento de segundos. NIST explica el motivo: los segundos intercalares se insertan para mantener UTC “dentro de ±0,9 s de la escala astronómica UT1”, la diferencia actual entre UTC y el Tiempo Atómico Internacional es de 37 segundos, y la secuencia de eventos en un segundo intercalar positivo va de 23h 59m 59s a 23h 59m 60s y luego a 00h 00m 00s. El apéndice del RFC 3339 recuerda que la decisión corresponde al IERS, que “un segundo intercalar ocurre simultáneamente en todas las zonas horarias” y que la inserción se representa como YYYY-MM-DDT23:59:60Z.
Muy poco de una pila típica modela eso. La documentación de Go dice que sus “cálculos de calendario siempre asumen un calendario gregoriano, sin segundos intercalares”; la mayoría de las bases de datos y bibliotecas de fechas adoptan la misma postura, lo cual es razonable: un sexagésimo segundo que existe dos veces por década no es algo que un libro mayor de apuestas quiera representar. La consecuencia es que la flota tiene que elegir una política, y hay dos vigentes:
- Salto. El reloj se atrasa o se retiene durante el segundo extra del salto. El orden a través de ese segundo deja de ser monótono: dos procesos distintos pueden marcar el mismo segundo dos veces, o saltarse uno. Algunos subsistemas lo manejan repitiendo el último segundo del día.
- Difuminado. El segundo extra se reparte en una ventana, de modo que no haya un salto único. El servicio público de NTP de Google describe que lo hace “desde 2008, en lugar de aplicar segundos intercalares a nuestros servidores mediante saltos de reloj”, recomienda un “difuminado lineal de 24 horas desde el mediodía hasta el mediodía UTC” y declara el costo con honestidad: “el tiempo difuminado se desvía brevemente de UTC durante el periodo de difuminado, pero se realinea después de 24 horas”.
Ese costo importa para el orden. Durante una ventana de difuminado, un reloj difuminado y otro que no lo está difieren hasta aproximadamente un segundo, así que dos servicios con políticas distintas pueden ordenar de forma diferente el mismo par de eventos. Las reglas prácticas son cortas: dejar escrito qué política sigue la flota, mantener todas las marcas de tiempo en el mismo formato en cualquier caso, asegurarse de que todo lo que compara horas de dos fuentes comparta política o tolere un segundo de desacuerdo, y mantener actualizada la información de segundos intercalares del demonio de tiempo: la directiva leapsectz de chrony lee la base de datos de zonas horarias del sistema para saber cuándo ocurrirá el próximo segundo intercalar, y su documentación señala que, cuando se anuncia uno, “la zona horaria debe actualizarse al menos 12 horas antes del segundo intercalar”, sin necesidad de reiniciar el demonio.
Los cortes son una regla escrita, no un redondeo
Todo producto regulado tiene cortes: el instante en que cierra un mercado, termina un periodo de bono, expira una sesión, se cierra una ventana de retiro, se declara terminado un día de informe. Un corte que solo existe como una comparación en algún lugar del código no es una regla; es una coincidencia que se mantiene hasta que alguien escriba el siguiente servicio.
Un corte declarado tiene cuatro propiedades, y deberían estar escritas donde puedan leerlas el equipo de producto, el de plataforma y quien redacta el informe.
- Qué reloj. El tiempo sincronizado de la propia plataforma, nunca una marca de tiempo enviada por el cliente. Una regla que acepta el reloj del dispositivo es una regla que el dispositivo puede mover.
- El límite, exactamente. Al segundo, al milisegundo o al tic del trabajo programado, y con borde inclusivo o exclusivo. Un intervalo semiabierto como
[apertura, cierre)es una decisión que la API, la interfaz y el informe pueden implementar de forma idéntica; “cierra a medianoche” no lo es. - Qué ocurre con el trabajo en vuelo. Una petición que llega antes del corte y termina después necesita un desenlace definido. En las apuestas, el punto de compromiso es el instante en que la plataforma la aceptó, y la guía de arquitectura de aceptación de apuestas deportivas explica por qué ese punto tiene que ser el autoritativo y no el momento en que el jugador pulsó un botón.
- Qué se le dice al jugador. Un corte que la interfaz presenta de forma distinta a como lo aplica la plataforma genera contactos de soporte, no disputas sobre milisegundos.
La expiración de sesión merece su propia línea, porque es un corte que mezcla ambos relojes. Una cuenta atrás que solo tiene que sobrevivir dentro de un proceso —un aviso de inactividad, una ventana de limitación de tasa— debería correr sobre un límite monótono, para que una corrección del reloj no pueda terminar una sesión antes de tiempo ni alargarla. Una expiración que debe sobrevivir a un reinicio, a un despliegue o a que un balanceador mueva al jugador a otro nodo tiene que guardarse como un instante con su desplazamiento, y su regla debe decir qué ocurre cuando el reloj se corrige mientras hay sesiones abiertas.
El calendario son datos, y los datos cambian
Una regla de negocio expresada en hora local no es estable, porque la hora local la define un dato que la plataforma no controla. Dos transiciones al año hacen que una hora local declarada sea ambigua o imposible: una hora que ocurre dos veces y una hora que no ocurre en absoluto. Una regla que dice “la promoción termina a las 02:00 locales” necesita una respuesta para la noche en que las 02:00 nunca llegan.
La base de datos de zonas horarias se actualiza con regularidad a medida que los gobiernos cambian sus reglas, lo que tiene una consecuencia para todo lo fechado en el futuro: el mismo texto de regla rinde un instante distinto después de una actualización. Por eso un corte con fecha futura debería guardarse como regla —nombre de zona más hora local— y evaluarse con la versión de datos vigente, y toda ejecución programada debería registrar la versión de datos que usó. Un instante calculado y congelado con un año de antelación es una promesa sobre la legislación.
Las bases de datos añaden una dependencia silenciosa más. PostgreSQL convierte entre timestamp without time zone y timestamp with time zone asumiendo que el valor “debe tomarse o darse como hora local de timezone”, y advierte que la conversión normalmente asume el TimeZone de la sesión. Una consulta que parece correcta cambia de significado con un ajuste de conexión. El remedio es poco glamuroso y eficaz: nombrar la zona explícitamente en la consulta y mantener los instantes guardados sin ambigüedad, para que el ajuste de sesión no tenga nada que reinterpretar.
Dónde termina el día de un informe es una decisión
Los informes diarios y mensuales tienen un límite que es una decisión de producto disfrazada de cuestión técnica. Un día UTC, un día local del regulador y un día de negocio del operador son tres tramos distintos con tres duraciones distintas en una transición horaria —23 o 25 horas en lugar de 24—, y el límite elegido cambia qué apuestas, depósitos o bonos caen en cada periodo.
Hay que elegir uno, dejarlo escrito y publicarlo junto a las cifras. Esa sola línea resuelve la mayoría de los descuadres antes de que se conviertan en incidencias: la guía de conciliación de monederos ya fija la conciliación contra el reloj del proveedor y los límites del libro mayor, y un informe cuyo límite de día está documentado puede compararse con el estado de cuenta de un proveedor en lugar de discutirse con él.
Probar los fallos de tiempo que puedes reproducir
Los defectos de tiempo son invisibles en una suite de pruebas que lee el reloj del sistema, porque el reloj del sistema es justamente lo que está bajo sospecha. El primer requisito es por tanto estructural: el tiempo entra en el código como una dependencia inyectada y las pruebas la proporcionan. Después, los siguientes fallos son todos reproducibles, y cada uno tiene un comportamiento esperado definido en lugar de una esperanza.
| Fallo | Qué pone a prueba | Qué debería hacer la plataforma |
|---|---|---|
| Reloj adelantado durante una sesión abierta | Expiración, ventanas de tasa, retroceso de reintentos | El trabajo en vuelo no se cancela en silencio ni se cuenta dos veces |
| Reloj atrasado | Orden de registros, duraciones “transcurridas”, ventanas de deduplicación | Sin duraciones negativas, sin ventana repetida, orden aún explicable |
| Desviación entre dos servicios | Orden de eventos reconstruido por un trabajo | El orden viene de un registro, no de comparar los relojes de dos hosts |
| Fuente de tiempo inalcanzable | Arranque y régimen permanente | El comportamiento está definido, registrado y alertado, sin deriva silenciosa |
| Día de transición horaria | Trabajos programados, reglas en hora local | Una regla que nombra una zona se resuelve de forma consistente, ni dos veces ni nunca |
| Segundo intercalar, con cualquiera de las políticas | Orden de toda la flota | La flota acuerda su política y tolera el desacuerdo que implica |
| Suspensión o migración | Intervalos monótonos | El trabajo expirado no resucita; un arrendamiento no se retiene dos veces |
Dos de esas pruebas necesitan algo más que una prueba unitaria. El comportamiento de la plataforma cuando su fuente de tiempo es inalcanzable pertenece al entorno de no producción que puede volverse erróneo a propósito, y cualquier prueba que mida duración durante una ejecución larga tiene que declarar con qué reloj midió: la guía de pruebas de carga y resistencia cubre la misma disciplina aplicada a la evidencia de capacidad, donde una medición de reloj de pared que se desvía invalida la ejecución que describe. Cuando una revisión de incidente reconstruye una cronología, el plan de respuesta a incidentes depende de un orden registrado correctamente antes del incidente, y la guía de evidencia de auditoría es donde corresponden las expectativas sobre desplazamiento y fuente.
Convertirlo en evidencia de aceptación
Un comprador, un auditor o un nuevo equipo de plataforma deberían poder responder preguntas sobre el tiempo a partir de documentos y no de entrevistas. El paquete es lo bastante pequeño para armarlo en una tarde y lo bastante concreto para ser probado:
- La lista de fuentes de reloj, el método de autenticación, la tolerancia y cómo se monitorizan y alertan la desviación y la deriva.
- El formato del instante, la regla de desplazamiento y dónde se conserva el nombre de la zona y por qué.
- El registro de cortes: cada límite, su precisión, su borde inclusivo o exclusivo, el reloj que lo decide y el servicio que lo aplica.
- La regla de calendario para cada comportamiento programado, con la versión de los datos de zonas horarias registrada en cada ejecución.
- La política de segundos intercalares y el razonamiento que aceptó su costo.
- Las pruebas de fallo anteriores, con resultados, un responsable y una fecha.
- El límite del día de informe, publicado junto a los informes que gobierna.
La razón para dedicar esa tarde es que el tiempo es la única dependencia que nunca puede estar caída. No se puede desactivar con una bandera, no tiene ventana de mantenimiento, y una plataforma que no ha decidido qué significan sus marcas de tiempo descubrirá la decisión durante la reclamación que las necesitaba. El trabajo de ingeniería de una plataforma de juego —la disciplina de desarrollo de plataforma de especificar el comportamiento antes de construirlo— se aplica aquí igual que en cualquier otro sitio: las reglas son baratas de escribir mientras el sistema está tranquilo.
Preguntas que hace un comprador de plataforma
¿No se encarga el sistema operativo del reloj?
Mantiene el reloj aproximadamente correcto, y eso es un trabajo más estrecho de lo que parece. El sistema operativo no elige el formato de las marcas de tiempo, no decide qué significa un corte en su borde, no conserva la zona a la que se refería una regla y no registra qué política siguió la flota durante un segundo intercalar. Esas son decisiones de producto y de plataforma, y son la parte por la que preguntará una revisión.
¿Basta con guardar las marcas de tiempo en UTC?
Guardar en UTC es lo correcto por defecto y es solo la mitad de la regla. Un instante con desplazamiento es inequívoco; el contexto que lo rodea no es automático. Si una regla mencionaba una hora local, el nombre de la zona tiene que conservarse en algún lugar para poder evaluarla tras una actualización de los datos de zonas horarias, y el límite —qué reloj, qué precisión, inclusivo o exclusivo— todavía hay que declararlo.
¿Qué precisión necesita realmente el reloj de una plataforma?
Más estrecha que el límite más fino que la plataforma declara, y no más. Si el cierre de un mercado se declara al segundo, la incertidumbre de la flota tiene que quedar cómodamente dentro de un segundo; una tolerancia más laxa que el límite significa que ese límite se aplica de forma distinta en hosts distintos, que es como dos jugadores del mismo segundo obtienen respuestas diferentes. La forma correcta de fijar el número es derivarlo de la regla más estrecha y luego monitorizar contra él.
¿De verdad importan los segundos intercalares a una plataforma de casino?
No a las matemáticas del juego, y sí a la evidencia. La mayoría de las bibliotecas de fechas y bases de datos no modelan un sexagésimo segundo, lo cual es una decisión de ingeniería defendible. Lo que importa es que la decisión esté escrita y sea consistente, para que un avance de segundo intercalar —o una flota que sigue una política en una región y otra en otra— no deje dos registros del mismo evento discrepando en un segundo sin ningún documento que explique por qué.








































