UUIDv7: el ID que promete tres cosas y solo cumple una

UUIDv7: el ID que promete tres cosas y solo cumple una

Escucha este artículo en audio (1:49 min, resumen del artículo original)

📻 Versión en audio: si prefieres escuchar en vez de leer, el resumen del artículo está justo aquí arriba.

UUIDv7: el ID que promete tres cosas y solo cumple una

Casi todo sistema moderno migró a UUID v7. Se lo ganó a medias: el valor ya trae la fecha adentro, se ordena más o menos bien y se ve impredecible. Tres beneficios por el precio de uno. Esta semana revisé el estándar con ojo crítico y la conclusión es incómoda: de esas tres promesas, la única garantizada en todas las versiones es que los IDs no se repiten. Ni el orden, ni la fecha, ni la privacidad.

Lo destapó bien claro Robert Alexander, consultor DevSecOps, al contrastar UUIDv7 con su propio estándar, el RFC 9562, y con implementaciones reales. El hallazgo central: la única propiedad que sostiene UUIDv7 de punta a punta es la unicidad, o sea la resistencia a colisiones. Todo lo demás depende de cuál implementación te tocó y de qué le pasa al reloj de tu servidor.

El timestamp que adelanta el futuro

El propio RFC deja la puerta abierta de par en par: la implementación puede alterar el timestamp, y no hay obligación de que ese valor pegue con la hora real. ¿Por qué se permite? Por rendimiento: si el contador de resolución fina se llena (el mínimo recomendado es de 12 bits, unos 4.096 IDs por milisegundo por nodo), la salida elegante es incrementar el timestamp y seguir generando.

El caso feo es el reloj que salta hacia atrás. Alexander lo probó con el generador que viene en la biblioteca estándar de Python: la máquina se retrocede una hora y el generador se queda ciclando, porque se niega a emitir un ID con hora menor a la del ID anterior y va adelantando su timestamp interno de por vida. Con carga sobre un ID por milisegundo, la diferencia entre la hora del ID y la hora real crece sin tope. El issue está abierto en CPython y la respuesta de los mantenedores es deslumbrante: es consistente con el RFC, consistente con otras implementaciones, y no hay mucho que hacer en un sistema así construido. Traducido: cada quien ajusta su versión como quiere, y tú cargas con el resultado.

«Monotónico» solo si sabes qué hora es, y no la sabes

El otro mito es el orden. Entre nodos, un orden estricto por timestamps es imposible por diseño, problema que se arrastra desde los trabajos de Lamport en los años setenta sobre relojes físicos: sin una hora común suficientemente precisa, no puedes ordenar eventos con valores de tiempo. Ni siquiera una sola máquina te salva: hay implementaciones que usan timestamp de milisegundos sin contador y generan IDs fuera de orden dentro de un simple ciclo for. Y ninguno de los generadores que revisó Alexander persiste el último timestamp usado, así que un reinicio del proceso tras un salto de reloj vuelve a desordenar la fila.

Que lo diga quien administra una flota de servidores con relojes que nunca coinciden del todo: confiar en el ID para ordenar eventos críticos es pedir problemas. Para eso están las columnas de fecha.

El detalle que casi nadie menciona

El timestamp viaja dentro del ID. Toda URL que compartas con un UUIDv7 filtra cuándo se creó ese objeto con precisión de milisegundos: la página que no muestra la fecha de registro de un perfil la está filtrando igual por su identificador. Y más grave: un v7 no es una sopa de azar como el v4, su estructura da margen para adivinar IDs cercanos, justo el patrón que habilita un IDOR contra recursos enumerados.

Qué haría yo

Nada de arrancar UUIDv7 en pánico: el orden aproximado sigue siendo oro para la localidad de los índices, y la mayoría de los sistemas no sufre por esto. Pero cuídate de la sobreventa: trátalo como un orden aproximado y nada más. La fecha de creación en su columna aparte. La fecha embebida, trátala como metadata filtrable, no como dato confiable ni como secreto. Y si tu modelo de amenaza incluye usuarios curioseando URLs, no uses el orden del número para inferir nada sensible. Unicidad: promesa en piedra. Todo lo demás: código de la implementación abierto al lado del contrato.

Me apoyé en el análisis de UUIDv7 doesn’t have the properties you think it does, de Robert Alexander (alexsci.com).

Fuente de inspiración: UUIDv7 doesn’t have the properties you think it does – Built on Shards of Silicon

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *