Scegliere il formato giusto per gli identificatori univoci della propria applicazione è una decisione che influisce sulle prestazioni del database, sulla scalabilità e sull'esperienza dello sviluppatore. Con UUID v7 ora standard ufficiale (RFC 9562, pubblicato nel 2024), il panorama della generazione di ID è cambiato significativamente. Questa guida confronta le quattro opzioni più popolari.
Tabella di confronto rapido
| Caratteristica | UUID v4 | UUID v7 | ULID | NanoID |
|---|---|---|---|---|
| Dimensione (byte) | 16 | 16 | 16 | Configurable (default 21 chars) |
| Lunghezza stringa | 36 chars | 36 chars | 26 chars | 21 chars (default) |
| Ordinato nel tempo | No | Yes (ms precision) | Yes (ms precision) | No |
| Standard | RFC 9562 | RFC 9562 | Community spec | Community spec |
| Compatibile con indici DB | Poor | Excellent | Excellent | Poor |
| Resistenza alle collisioni | 122 random bits | 74 random bits + timestamp | 80 random bits + timestamp | Configurable |
| Sicuro per URL | Yes (with encoding) | Yes (with encoding) | Yes (native) | Yes (native) |
| Supporto linguaggi | Universal | Growing rapidly | Good | Excellent (JS/TS) |
UUID v4: Lo standard consolidato
UUID v4 è stata la scelta predefinita per oltre un decennio. Genera identificatori a 128 bit utilizzando 122 bit di casualità, producendo il formato familiare xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx.
Punti di forza:
- Supporto universale delle librerie in ogni linguaggio di programmazione
- Nessun coordinamento necessario — genera ovunque, in qualsiasi momento
- Semplice e ben compreso
Punti deboli:
- La distribuzione casuale causa frammentazione dell'indice B-tree nei database
- Nessuna informazione temporale — impossibile ordinare per ordine di creazione
- Su larga scala (milioni di righe), le prestazioni di inserimento si degradano significativamente
// JavaScript
crypto.randomUUID();
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"Prova il nostro strumento Generatore UUID →
UUID v7: Il nuovo standard (RFC 9562)
UUID v7, finalizzato nella RFC 9562 (2024), è progettato specificamente per l'uso come chiavi di database. Combina un timestamp Unix a 48 bit (precisione al millisecondo) con 74 bit di casualità, producendo UUID ordinati nel tempo completamente compatibili con l'infrastruttura UUID esistente.
Punti di forza:
- Ordinato nel tempo — ordina naturalmente per data di creazione
- Eccellenti prestazioni di inserimento nel database (nessuna frammentazione dell'indice)
- Compatibile con tutte le colonne e gli strumenti UUID esistenti
- Supporto nativo in PostgreSQL 17+
Punti deboli:
- Meno bit casuali (74 vs 122) — comunque astronomicamente resistente alle collisioni
- Il timestamp è incorporato — rivela l'ora approssimativa di creazione
- Il supporto delle librerie è ancora in crescita (ma rapidamente)
// Node.js (uuid library v9+)
import { v7 as uuidv7 } from 'uuid';
uuidv7();
// → "018e4f5c-6a7b-7000-8000-1234abcd5678"
// ^^^^^^^^^^^^^^^^ timestamp portionULID: Ordinabile lessicograficamente
ULID (Universally Unique Lexicographically Sortable Identifier) precede UUID v7 e condivide un design simile: timestamp a 48 bit + 80 bit di casualità. La differenza chiave è la codifica: Crockford Base32, che produce stringhe compatte di 26 caratteri come 01ARZ3NDEKTSV4RRFFQ69G5FAV.
Punti di forza:
- Rappresentazione compatta in stringa (26 caratteri vs 36 di UUID)
- Monotonia integrata — gli ID generati nello stesso millisecondo sono comunque ordinati
- Ordinabile lessicograficamente come stringa (nessun confronto speciale necessario)
- Insensibile alle maiuscole e sicuro per URL
Punti deboli:
- Non è uno standard RFC — solo specifica della community
- Non compatibile con le colonne UUID senza conversione
- Meno supporto di librerie rispetto a UUID
// JavaScript
import { ulid } from 'ulid';
ulid();
// → "01ARZ3NDEKTSV4RRFFQ69G5FAV"NanoID: Compatto e personalizzabile
NanoID adotta un approccio diverso: invece di un formato fisso, genera stringhe casuali compatte e sicure per URL con un alfabeto e una lunghezza configurabili. Il valore predefinito è di 21 caratteri usando A-Za-z0-9_-.
Punti di forza:
- Molto compatto (21 caratteri predefiniti, personalizzabile)
- Sicuro per URL di default
- Alfabeto e lunghezza personalizzabili
- Libreria minuscola (~130 byte gzippati) — perfetta per il frontend
- Crittograficamente robusto (usa crypto.getRandomValues)
Punti deboli:
- Nessun ordinamento temporale — stessi problemi di frammentazione B-tree di UUID v4
- Nessuna specifica standard
- Non compatibile con l'infrastruttura UUID
// JavaScript
import { nanoid } from 'nanoid';
nanoid();
// → "V1StGXR8_Z5jdHi6B-myT"Guida alla decisione: Quale scegliere?
Usa UUID v7 quando:
- Stai costruendo una nuova applicazione con un database relazionale
- Hai bisogno di ID ordinati nel tempo per un'indicizzazione efficiente
- Il tuo sistema si aspetta il formato UUID standard (PostgreSQL, MySQL, ecc.)
- Vuoi il miglior equilibrio tra compatibilità e prestazioni
Usa UUID v4 quando:
- Lavori con sistemi che supportano solo UUID v4
- Hai bisogno della massima casualità senza perdita di timestamp
- La scala del database è da piccola a media (< 1M righe)
Usa ULID quando:
- Hai bisogno di rappresentazioni stringa più brevi
- Lavori con sistemi che ordinano le stringhe lessicograficamente
- La monotonia all'interno dello stesso millisecondo è importante
- Non hai bisogno della compatibilità con le colonne UUID
Usa NanoID quando:
- Generi ID nel browser o nel frontend
- La dimensione del bundle conta (NanoID è 130 byte)
- Hai bisogno di identificatori brevi e compatibili con URL
- Stai costruendo accorciatori di URL, codici di invito o token di sessione
Benchmark delle prestazioni: Inserimenti nel database
La differenza più significativa tra questi formati è la prestazione di inserimento nel database. Gli ID ordinati nel tempo (UUID v7, ULID) mantengono inserimenti B-tree sequenziali, mentre gli ID casuali (UUID v4, NanoID) causano divisioni casuali delle pagine:
| Formato ID | 1M inserimenti (PostgreSQL) | Dimensione indice | Modello di inserimento |
|---|---|---|---|
| Auto-incremento | ~12s (baseline) | 21 MB | Sequential |
| UUID v7 | ~15s (+25%) | 56 MB | Nearly sequential |
| ULID | ~15s (+25%) | 56 MB | Nearly sequential |
| UUID v4 | ~28s (+133%) | 56 MB | Random |
| NanoID (21 chars) | ~30s (+150%) | 62 MB | Random |
I dati del benchmark sono approssimativi e variano in base all'hardware, alla versione del database e alla struttura delle tabelle. La differenza relativa è coerente in tutti gli ambienti.
Percorso di migrazione: UUID v4 a UUID v7
Se stai considerando la migrazione da UUID v4 a UUID v7, la buona notizia è che condividono lo stesso formato a 128 bit e la stessa rappresentazione stringa. Nella maggior parte dei database, puoi iniziare a generare valori UUID v7 per le nuove righe mentre i valori UUID v4 esistenti rimangono validi:
-- PostgreSQL 17+
CREATE TABLE users (
id UUID DEFAULT gen_random_uuid_v7() PRIMARY KEY,
name TEXT NOT NULL
);
-- Older PostgreSQL with uuid-ossp or pgcrypto
-- Use application-level UUID v7 generationDomande frequenti
Dovrei migrare da UUID v4 a UUID v7?
Se la tua applicazione utilizza UUID come chiavi primarie del database e riscontri frammentazione dell'indice o inserimenti lenti su larga scala, la migrazione a UUID v7 vale la pena. Per applicazioni di dimensioni piccole-medie, UUID v4 funziona bene.
NanoID è sicuro per le chiavi primarie del database?
NanoID è crittograficamente sicuro e ha una lunghezza configurabile, ma manca di ordinamento temporale. Per le chiavi primarie del database dove le prestazioni di inserimento contano, UUID v7 o ULID sono scelte migliori. NanoID eccelle nelle applicazioni frontend e negli accorciatori di URL.
Qual è la differenza tra UUID v7 e ULID?
Entrambi sono identificatori univoci ordinati nel tempo. UUID v7 segue la RFC 9562 ed è compatibile con l'infrastruttura UUID esistente (128 bit, formato standard). ULID usa la codifica Crockford Base32 (26 caratteri) e ha una monotonia integrata all'interno dello stesso millisecondo. UUID v7 è migliore per sistemi che si aspettano il formato UUID; ULID è più compatto come stringa.