UUID v7-generator: waarom deze 36‑tekenige ID’s tijdgesorteerd en cryptografisch willekeurig zijn
Een UUID v7 begint met een 48‑bits Unix‑millisecondetijdstempel, gevolgd door 80 bits aan sterke willekeurige data. Het resultaat is een 36‑teken‑string (128 bits) die eruitziet als 018f3a6e‑b7c8‑7a3b‑8000‑d4e5f6a7b8c9. De eerste twaalf tekens coderen de tijd in hexadecimaal, wat betekent dat de ID’s van nature chronologisch gesorteerd zijn. Anders dan UUID v4, waarvan de volledig willekeurige lay‑out de B‑boom‑indexen van databases versnippert, plaatst v7 nieuwe entries dicht bij elkaar in de index – mits ze in een ander milliseconde zijn gegenereerd. De generator op deze pagina produceert lokaal, in de browser, tussen 1 en 100 van deze ID’s tegelijk. Je kunt de uitvoer in hoofdletters zetten, de streepjes weglaten, en elke ID afzonderlijk of allemaal tegelijk kopiëren. Wijzigen van een optie (aantal, hoofdletters, streepjes) triggert direct een nieuwe generatie.
De interne structuur van UUID v7 (RFC 9562)
UUID v7 is gestandaardiseerd in RFC 9562. De 128 bits zijn als volgt opgebouwd:
- 48 bits: Unix‑millisecondetijdstempel (geheel getal, big‑endian). Dit is het aantal milliseconden sinds 1 januari 1970 UTC.
- 4 bits: versie‑indicator (
0111voor v7). - 12 bits: variant‑ en reservebits (gestart met
10voor de RFC‑variant, gevolgd door 10 bits willekeur). - 62 bits: cryptografisch willekeurig (geen vast patroon).
In de 36‑teken‑string (met streepjes) worden de tijdstempel‑bits de eerste 8 hexadecimale karakters, een streepje, dan 4 karakters (waarvan de eerste de versie bevat), nog een streepje, dan 4 karakters (variant + begin willekeur), streepje, 4 karakters (willekeur), streepje, en tot slot 12 karakters (willekeur). Voorbeeld met tijdstempel 018f3a6e:
018f3a6e‑b7c8‑7a3b‑8000‑d4e5f6a7b8c9
tijdstempel versie variant willekeur
De tijdstempel is in milliseconden, niet in seconden of nanoseconden. Dat betekent dat UUID’s die in dezelfde milliseconde worden gegenereerd, dezelfde eerste 48 bits delen. De volgorde binnen die milliseconde is niet gegarandeerd: de resterende bits zijn willekeurig, niet sequentieel. Dit is een bewuste ontwerpkeuze om parallelle generatie zonder coördinatie mogelijk te maken – precies wat gedistribueerde systemen nodig hebben.
Waarom tijdgesorteerde ID’s de database‑index redden
UUID v4 is volledig willekeurig. Als je een tabel met een UUID v4 als primaire sleutel hebt, en je voegt een rij toe, dan landt de nieuwe UUID ergens in het midden van de B‑boom. Dat dwingt de database om pagina’s te splitsen, herschikken en opnieuw te balanceren. Bij hoge schrijfvolumes leidt dit tot indexfragmentatie, meer I/O, en lagere insert‑throughput. De klassieke oplossing is om een auto‑increment integer te gebruiken, maar die is voorspelbaar en schaalt slecht in gedistribueerde omgevingen.
UUID v7 lost dit grotendeels op. Omdat de eerste 48 bits de creatietijd zijn, worden nieuwe ID’s in oplopende volgorde toegevoegd aan het einde van de index – zolang er geen tijdreis optreedt. De database kan de nieuwe bladpagina’s sequentieel schrijven, wat de cache‑efficiëntie verbetert en het aantal page splits drastisch vermindert. Het enige nadeel: ID’s uit dezelfde milliseconde worden nog steeds willekeurig geplaatst, maar dat is een fractie van het totale volume. In de praktijk levert UUID v7 een aanzienlijke verbetering van de insert‑prestaties ten opzichte van v4.
Een kanttekening: strikte ordening binnen één milliseconde is niet mogelijk zonder een centraal coördinatiepunt of een monotoon oplopende teller (die ook privacyrisico’s geeft). UUID v7 kiest voor schaalbaarheid en onvoorspelbaarheid boven absolute sorteergarantie.
UUID v7 versus ULID, UUID v4 en NanoID
| Eigenschap | UUID v7 | UUID v4 | ULID | NanoID |
|---|---|---|---|---|
| Tijdgebonden | Ja (48‑bit ms) | Nee | Ja (48‑bit ms) | Nee (optioneel) |
| Tijdsvolgorde | Chronologisch, geen garantie binnen ms | Geen | Chronologisch, geen garantie binnen ms | Alleen bij eigen implementatie |
| Lengte | 36 tekens (met streepjes) | 36 tekens | 26 tekens (Crockford) | 21 tekens (standaard) |
| Strikte leesbaarheid | Hexadecimaal | Hexadecimaal | Base32 (geen leesbare tijd) | url‑veilig |
| Cryptografisch willekeurig | Ja (62‑74 bits, afhankelijk van variant) | Ja (122 bits) | Nee (pseudo‑random) | Ja (configureerbaar) |
| Standaard | RFC 9562 | RFC 4122 | Informeel | Informeel |
Het grote voordeel van UUID v7 boven ULID is dat het een officiële RFC is, breed ondersteund in bibliotheken, en dat de 36‑teken‑string compatibel is met bestaande UUID‑kolommen in databases. ULID is korter (26 tekens) en gebruikt een andere codering, maar mist dezelfde standaardisatie. NanoID is nog korter, maar heeft geen ingebouwde tijdcomponent; je kunt die zelf toevoegen, maar dan ben je afhankelijk van een eigen implementatie.
Hyphen‑gebruik en hoofdlettergevoeligheid: wat elke ontwikkelaar moet weten
UUID v7 wordt standaard weergegeven in kleine letters met streepjes: 550e8400‑e29b‑41d4‑a716‑446655440000. De streepjes zijn onderdeel van de RFC‑representatie, maar niet van de binaire vorm. Dat betekent:
- Met streepjes: 36 tekens, leesbaar, invoer voor de meeste UUID‑parsers.
- Zonder streepjes: 32 hexadecimale tekens, compacter, maar niet zonder conversie te gebruiken in kolommen die een
uuidtype verwachten (afhankelijk van de DBMS). PostgreSQL accepteertgen_random_uuid()die streepjes teruggeeft; MySQL en SQL Server zijn flexibeler. - Hoofdletters: Geen invloed op parsering – hoofdletters en kleine letters worden in hex gelijk behandeld. Sommige systemen eisen echter kleine letters (RFC‑conform). Andere systemen, zoals bepaalde logging‑frameworks, geven de voorkeur aan hoofdletters voor visuele consistentie.
De generator laat je beide toggles naar wens instellen. Vergeet niet dat als je de streepjes weghaalt, de string niet meer voldoet aan de formele UUID‑syntax. Als je later met een bibliotheek zoals uuid in Node.js of java.util.UUID werkt, moet je mogelijk de streepjes opnieuw toevoegen.
Lokaal genereren: privacy en prestaties
Alle UUID’s worden gegenereerd in de browser, met crypto.getRandomValues() (of de Web Crypto API). Er wordt geen data naar de server gestuurd. Dit heeft twee belangrijke gevolgen:
- Privacy: De tijdstempel van jouw apparaat wordt niet gedeeld. Zelfs als je 100 ID’s genereert, blijft alles lokaal.
- Snelheid: De generatie is vrijwel instant, ongeacht het aantal. De browser gebruikt de ingebouwde cryptografische bron, die veilig genoeg is voor productiedoeleinden.
Omdat de tijdstempel van het apparaat wordt gebruikt (de Unix‑milliseconds van Date.now()), kan er een kleine afwijking zijn tussen verschillende machines. Voor toepassingen die absolute tijdsynchronisatie vereisen (bijvoorbeeld bij forensische logging), moet je een gedeelde klokbron gebruiken. Maar voor de meeste toepassingen – primaire sleutels, event‑ID’s, message‑ID’s – is de lokale tijd voldoende.
Veelgestelde vragen (FAQ)
Waarom is UUID v7 niet strikt geordend wanneer ID’s in dezelfde milliseconde worden aangemaakt?
De tijdstempel is 48 bits met millisecondeprecisie. Voor ID’s binnen één milliseconde zijn de tijdbits identiek; de resterende bits zijn willekeurig. Strikt sequentieel maken binnen één ms zou een centrale teller vereisen, wat schaalbaarheid en onvoorspelbaarheid ondermijnt.
Kan ik UUID v7 gebruiken als primaire sleutel in een relationele database?
Ja. De meeste moderne databases ondersteunen UUID als type (PostgreSQL, MySQL 8+, SQL Server, SQLite met extensies). UUID v7 geeft betere indexprestaties dan v4, maar is nog steeds langzamer dan een integer. Overweeg of de voordelen van onvoorspelbaarheid en tijdssortering opwegen tegen de overhead.
Zijn UUID v7‑ID’s cryptografisch veilig voor beveiligingstokens?
De random bits zijn gegenereerd met een cryptografisch veilige generator. Een aanvaller kan de tijdstempel schatten, maar kan de resterende 62‑74 bits niet raden zonder opzettelijke zwakte. Voor sessietokens of reset‑links is v7 veilig, mits de bron van willekeur goed is (zoals in de browser).
Wat gebeurt er als ik het maximum van 100 ID’s overschrijd?
De generator staat maximaal 100 in één keer toe. Wil je er meer, genereer dan meerdere keren. Dit voorkomt dat het browsergedeelte overbelast raakt, al is dat in de praktijk geen probleem; het is een bewuste gebruikersinterface‑limiet.
Hebben de streepjes invloed op de sorteereigenschappen?
Nee. De streepjes zijn alleen representatie; het onderliggende binaire patroon blijft ongewijzigd. Je kunt dus met of zonder streepjes sorteren op dezelfde hexadecimale string, zolang je consistent bent. Sommige systemen parseren de string echter anders zonder streepjes.
Waarom wordt er geen vaste volgorde gegarandeerd binnen één milliseconde?
Dat is een ontwerpkeuze van RFC 9562. Door de overige bits volledig willekeurig te houden, kunnen onafhankelijke generatoren (verschillende threads, processen, machines) ID’s maken zonder te coördineren. Een sequentiële teller zou een shared lock vereisen, precies wat UUID v7 juist wil vermijden.