Elegir un formato de ID: UUID, ULID, Snowflake o autoincremental
Casi todo sistema necesita dar IDs únicos a las cosas, y la elección tiene consecuencias que afloran mucho después — en el rendimiento de la base de datos, en si los IDs filtran información y en lo fácil que distintos servicios pueden generarlos sin colisionar. Esta guía compara los formatos comunes y te da una forma de elegir con intención, no por costumbre.
Enteros autoincrementales
El ID clásico de base de datos: 1, 2, 3, etc., repartidos por la base de datos. Son diminutos, rápidos de indexar y están ordenados naturalmente por creación. Para una sola base de datos suele ser todo lo que necesitas.
Sus debilidades aparecen en los bordes. Solo la base de datos central puede acuñarlos, así que servicios independientes o clientes sin conexión no pueden generar IDs por adelantado. Además filtran información: un competidor puede leer tu número de factura para estimar cuántos pedidos tienes, y los IDs secuenciales en una URL invitan a adivinar registros vecinos.
UUID versión 4 (aleatorio)
Un UUID v4 son 122 bits aleatorios, escritos normalmente como 36 caracteres. Cualquiera, en cualquier lugar, puede generar uno sin coordinación y con una probabilidad de colisión prácticamente nula, lo que los hace ideales para sistemas distribuidos, claves amigables con fusiones e identificadores públicos que no deberían ser adivinables.
El coste es el tamaño y el orden. Son mucho más grandes que un entero y, al ser totalmente aleatorios, no están ordenados por tiempo — insertar claves aleatorias en un índice B-tree típico dispersa las escrituras y puede perjudicar el rendimiento de la base de datos a gran escala. Tampoco llevan información incrustada, lo que a veces es una ventaja y a veces una limitación.
IDs ordenados por tiempo: UUID v7, ULID y Snowflake
Una familia más nueva soluciona el problema del orden poniendo una marca de tiempo en los bits iniciales, de modo que los IDs generados después se ordenan tras los anteriores sin dejar de ser únicos globalmente. UUID v7 hace esto dentro del formato estándar de UUID. ULID hace lo mismo en una codificación compacta de 26 caracteres, amigable con URLs e insensible a mayúsculas. Los Snowflake (popularizados por Twitter) empaquetan una marca de tiempo, un ID de máquina y un contador por milisegundo en un entero de 64 bits.
El orden temporal te da inserciones amigables con el índice y ordenación cronológica gratis, sin una autoridad central. El compromiso es que ahora la hora de creación es visible en el ID — normalmente inofensivo, ocasionalmente algo que preferirías no exponer.
Qué afecta realmente la elección
Cuatro propiedades se mueven juntas al elegir un formato, y conviene sopesarlas explícitamente.
- Coordinación: ¿puede cualquier nodo generar IDs solo (UUID/ULID/Snowflake) o solo una base de datos central (autoincremental)?
- Orden: ¿se pueden ordenar los IDs por hora de creación (autoincremental, v7, ULID, Snowflake) o no (UUID v4)?
- Tamaño y coste de índice: los enteros son los más pequeños; los UUID aleatorios, los más grandes y menos amigables con el índice.
- Filtración de información: los enteros secuenciales revelan volumen e invitan a la enumeración; los UUID aleatorios no revelan nada; los IDs ordenados por tiempo revelan la marca de tiempo.
Un valor por defecto razonable
Si tienes una sola base de datos y no expones los IDs públicamente, los enteros autoincrementales son simples y eficientes. Si los IDs son públicos, o los generan muchos servicios, o se usan como slugs de URL, recurre a un UUID — v7 o ULID cuando los quieras aproximadamente ordenados por tiempo para la eficiencia de la base de datos, v4 cuando quieras específicamente que no revelen nada en absoluto.
Elijas lo que elijas, sé consistente dentro de un sistema y evita mezclar formatos para el mismo tipo de entidad. La peor estrategia de IDs suele ser la que se elige por accidente.