Skip to content
SP StackPractices
beginner Por Mathias Paulenko

Generacion de UUID: v4, v7 y Comparacion con ULID

Compara UUID v4, v7, ULID y nanoid para generar identificadores unicos con diferentes tradeoffs en aleatoriedad, ordenamiento, rendimiento y localidad de indices de base de datos

Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.

Generacion de UUID: v4, v7 y Comparacion con ULID

Elige la estrategia de identificador unico correcta para tu aplicacion comparando UUID v4 (random), v7 (time-sortable), ULID (lexicographically sortable) y nanoid (compact URL-safe). Esta recipe cubre generacion, implicaciones de indices de base de datos, probabilidad de colision y consideraciones de migracion.

Cuando Usar Esto

  • Las primary keys de base de datos deben ser globalmente unicas en sistemas distribuidos
  • El ordenamiento de identificadores afecta el rendimiento de queries y fragmentacion de indices
  • Se necesitan identificadores cortos y URL-safe para recursos public-facing

Solucion

1. UUID v4 (Random)

// ids/uuid4.ts
import { v4 as uuidv4 } from 'uuid';

const id = uuidv4(); // 'f47ac10b-58cc-4372-a567-0e02b2c3d479'

// Caracteristicas
// - Completamente random (122 bits de aleatoriedad)
// - No sortable por tiempo
// - Causa fragmentacion de indice en B-trees
// - Formato standard con hyphens

2. UUID v7 (Time-Sortable)

// ids/uuid7.ts
import { v7 as uuidv7 } from 'uuid';

const id = uuidv7(); // '018f3bda-7c58-7e8a-8b5e-4f3e8c9d2a1b'

// Caracteristicas
// - Primeros 48 bits = Unix timestamp en milisegundos
// - Restantes 74 bits = random
// - Sortable por tiempo de creacion
// - Mejor localidad de indice que v4
// - Standard RFC draft (estable para produccion)

3. ULID (Lexicographically Sortable)

// ids/ulid.ts
import { ulid } from 'ulid';

const id = ulid(); // '01HV8J3K2M4N5P6Q7R8S9T0UV'

// Caracteristicas
// - 26 caracteres, Crockford's base32
// - Primeros 10 chars = timestamp (sortable)
// - Ultimos 16 chars = aleatoriedad
// - Lexicographically sortable como string
// - Sin hyphens, URL-safe

4. NanoID (Compacto y Rapido)

// ids/nanoid.ts
import { nanoid } from 'nanoid';

const id = nanoid();       // default 21 chars
const short = nanoid(10);  // longitud configurable

// Caracteristicas
// - 21 chars por defecto (similar resistencia de colision a UUID v4)
// - Alfabeto custom soportado
// - Generacion rapida (~50% mas rapido que UUID)
// - URL-safe por defecto (sin hyphens)

5. Matriz de Comparacion

// ids/comparison.ts
const comparison = {
  uuidv4: {
    length: 36,
    sortable: false,
    indexLocality: 'poor',
    standard: 'RFC 4122',
    collisionRisk: 'negligible (2^122)',
  },
  uuidv7: {
    length: 36,
    sortable: true,
    indexLocality: 'good',
    standard: 'RFC draft',
    collisionRisk: 'negligible (2^74)',
  },
  ulid: {
    length: 26,
    sortable: true,
    indexLocality: 'good',
    standard: 'Community',
    collisionRisk: 'negligible (2^80)',
  },
  nanoid: {
    length: 21,
    sortable: false,
    indexLocality: 'poor',
    standard: 'Community',
    collisionRisk: 'negligible (2^126)',
  },
};

6. PostgreSQL con UUID v7

-- Habilitar extension UUID
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Tabla con primary key UUID v7
CREATE TABLE events (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  name TEXT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Para UUIDs sortables, generar en la aplicacion e insertar
INSERT INTO events (id, name) VALUES ('018f3bda-7c58-7e8a-8b5e-4f3e8c9d2a1b', 'signup');

Como Funciona

  • UUID v4 usa aleatoriedad para unicidad pero dispersa inserts de indice
  • UUID v7 embebe un prefijo de timestamp, haciendo los inserts aproximadamente secuenciales
  • ULID usa codificacion base32 para identificadores mas cortos aun sortable
  • NanoID prioriza velocidad y compacidad con longitud configurable

Consideraciones de Produccion

  • Usa UUID v7 para aplicaciones nuevas que necesiten keys time-sortable
  • Manten UUID v4 para sistemas existentes a menos que la migracion este justificada
  • Usa ULID cuando la longitud del identificador y el ordenamiento lexicografico importen
  • Usa nanoid para tokens de corta vida, short URLs o cuando el tamano sea critico

Errores Comunes

  • Generar UUIDs en la base de datos en lugar de la application layer
  • Usar v4 en sistemas de alto insert sin monitorear fragmentacion de indice
  • No manejar la rara pero posible colision de UUID en sistemas distribuidos

FAQ

P: Deberia usar enteros auto-incrementales en su lugar? R: Usa enteros para sistemas single-node donde la coordinacion es trivial. Usa UUIDs para sistemas distribuidos o cuando los identificadores no deben revelar informacion de secuencia.

P: Es UUID v7 oficialmente estandarizado? R: Esta en estado RFC draft y ampliamente considerado estable. Las principales bases de datos y librerias lo soportan.