UUID uitgelegd: 128-bit structuur, versies en praktische toepassingen
Elke keer dat je je aanmeldt bij een dienst, wordt er een unieke identifier aangemaakt voor je account. Elk API-verzoek draagt een trace-ID. Elke rij in een gedistribueerde database heeft een primaire sleutel nodig die niet botst met sleutels die op andere machines zijn gegenereerd. De oplossing achter dit alles? UUID — Universally Unique Identifier.
Deze gids legt uit wat UUIDs zijn, hoe ze zijn opgebouwd, wat elke versie intern doet en wanneer je ze wel (of niet) moet gebruiken.
UUID in het kort
Een UUID is een 128-bit (16-byte) identifier die ontworpen is om wereldwijd uniek te zijn zonder dat er een centrale autoriteit nodig is. Hij wordt geschreven als 32 hexadecimale cijfers in het canonieke 8-4-4-4-12-formaat:
550e8400-e29b-41d4-a716-446655440000
|------| |--| |--| |--| |----------|
8 hex 4 4 4 12 hex
Dat zijn 32 hex-tekens + 4 koppeltekens = 36 tekens in totaal. De koppeltekens zijn puur decoratief — ze bevatten geen gegevens.
Kernfeiten:
- 128 bits = 2¹²⁸ ≈ 3,4 × 10³⁸ mogelijke waarden
- Gestandaardiseerd door RFC 9562 (mei 2024, vervangt RFC 4122)
- Ook wel GUID (Globally Unique Identifier) genoemd in Microsoft-ecosystemen — hetzelfde formaat, andere naam
- Ingebouwd ondersteund door PostgreSQL (
uuid-type), MySQL (BINARY(16)ofCHAR(36)) en vrijwel elke programmeertaal
Anatomie van een UUID
Elke UUID codeert twee metadatavelden op vaste bitposities, ongeacht de versie:
550e8400-e29b-41d4-a716-446655440000
^ ^
| |
Version-┘ └-Variant
Versieveld (bits 48–51)
Het 13e hex-cijfer (het eerste cijfer van de derde groep) geeft de UUID-versie aan:
| Hex-cijfer | Versie | Methode |
|---|---|---|
1 | v1 | Timestamp + MAC-adres |
3 | v3 | MD5 hash van namespace + naam |
4 | v4 | Cryptografisch willekeurig |
5 | v5 | SHA-1 hash van namespace + naam |
6 | v6 | Geherordende timestamp (RFC 9562) |
7 | v7 | Unix timestamp + willekeurig (RFC 9562) |
8 | v8 | Aangepast / implementatiespecifiek |
Variantveld (bits 64–65)
Het 17e hex-cijfer (het eerste cijfer van de vierde groep) geeft de variant aan. Voor RFC 4122/9562-UUIDs zijn de eerste bits 10, wat betekent dat dit hex-cijfer altijd 8, 9, a of b is.
Voorbeeld uitgesplitst
550e8400-e29b-41d4-a716-446655440000
↑ ↑
4 → v4 a → RFC 4122 variant
This is a UUID v4 (random), RFC 4122/9562 variant.
UUID-versies uitgelegd
Versie 1: Timestamp + MAC-adres
UUID v1 was het oorspronkelijke ontwerp. Het codeert:
- 60-bit timestamp — intervallen van 100 nanoseconden vanaf 15 oktober 1582 (de Gregoriaanse kalenderhervorming)
- 14-bit kloksequentie — monotoniciteitsteller om duplicaten bij een klokterugzetting te voorkomen
- 48-bit node — doorgaans het MAC-adres van de machine
| Timestamp | Ver | Clk |Var| Node (MAC) |
| 60 bits | 4b | 14b |2b | 48 bits |
Problemen:
- Legt het generatiemoment en de hardware-identiteit bloot (privacyrisico)
- MAC-adressen kunnen worden vervalst, wat de uniciteit ondermijnt
- De 1582-epoch is verwarrend en vereist omrekening
Oordeel: Afgeschreven door RFC 9562. Gebruik v7 voor tijdgebaseerde UUIDs.
Versie 3: MD5 naam-gebaseerd (deterministisch)
UUID v3 berekent een hash van een namespace-UUID en een naamstring met MD5. Dezelfde invoer levert altijd dezelfde UUID op.
import uuid
# namespace = DNS, name = "example.com"
print(uuid.uuid3(uuid.NAMESPACE_DNS, "example.com"))
# → "9073926b-929f-31c2-abc9-fad77ae3e8eb" (always this value)
Er zijn vier standaard-namespaces gedefinieerd:
- DNS:
6ba7b810-9dad-11d1-80b4-00c04fd430c8 - URL:
6ba7b811-9dad-11d1-80b4-00c04fd430c8 - OID:
6ba7b812-9dad-11d1-80b4-00c04fd430c8 - X.500:
6ba7b814-9dad-11d1-80b4-00c04fd430c8
Oordeel: Functioneel, maar gebruik liever v5 — SHA-1 is sterker dan MD5.
UUID v4: Willekeurig — de meest gebruikte
UUID v4 vult 122 bits met cryptografisch veilige willekeurige gegevens (de resterende 6 bits zijn gereserveerd voor de versie- en variantvelden).
| Random | Ver | Random |Var| Random |
| 48 bits | 4b | 12 bits |2b | 62 bits |
Met 2¹²² ≈ 5,3 × 10³⁶ mogelijke waarden is de kans op een botsing astronomisch klein. Om een kans van 50% op ten minste één botsing te bereiken, heb je ongeveer 2,71 × 10¹⁸ UUIDs nodig — dat zijn 2,71 triljoen.
// Every modern browser and Node.js supports this
const id = crypto.randomUUID();
console.log(id); // → "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
Sterktes: eenvoudig, privé, universeel ondersteund, geen coördinatie nodig.
Zwakte: willekeurige distributie veroorzaakt B-tree-indexfragmentatie bij gebruik als primaire databasesleutel. Overweeg voor database-intensieve toepassingen v7.
Versie 5: SHA-1 naam-gebaseerd (deterministisch)
Identiek aan v3, maar gebruikt SHA-1 in plaats van MD5. Dezelfde invoer levert altijd dezelfde UUID op.
import uuid
print(uuid.uuid5(uuid.NAMESPACE_DNS, "example.com"))
# → "cfbff0d1-9375-5685-968c-48ce8b15ae17" (always this value)
Toepassingen:
- Stabiele ID’s genereren op basis van URL’s of DNS-namen
- Sleutels voor content-addressable storage
- Reproduceerbare testfixtures
Belangrijk: v3 en v5 zijn NIET bedoeld voor beveiliging. Ze zijn deterministisch — iedereen die de namespace en naam kent, kan de UUID reproduceren.
UUID v7: Unix-timestamp + willekeurig (aanbevolen voor nieuwe projecten)
UUID v7 is de nieuwste versie, geïntroduceerd in RFC 9562 (mei 2024). Het codeert:
- 48-bit Unix timestamp in milliseconden — monotoon toenemend
- 74 bits cryptografische willekeurigheid
| Unix timestamp (ms) | Ver | rand_a |Var| rand_b |
| 48 bits | 4b | 12 bits |2b | 62 bits |
Dit betekent dat v7-UUIDs van nature gesorteerd zijn op aanmaaktijd — nieuwere UUIDs zijn altijd lexicografisch groter dan oudere. Deze eigenschap maakt ze ideaal als primaire databasesleutels, waarbij B-tree-indexen sequentieel blijven in plaats van willekeurig te fragmenteren.
import { v7 as uuidv7 } from "uuid";
const id1 = uuidv7(); // generated at T₁
const id2 = uuidv7(); // generated at T₂ (T₂ > T₁)
console.log(id1 < id2); // → true (lexicographic comparison)
Waarom dit belangrijk is voor databases: de sequentiële eigenschap van v7 vermindert het aantal index-paginascheidingen met wel 90% ten opzichte van v4, wat neerkomt op snellere inserts, kleinere indexen en betere cacheprestaties.
UUID vs. GUID — wat is het verschil?
Er is geen functioneel verschil. GUID (Globally Unique Identifier) is de naam van Microsoft voor UUID, gebruikt in Windows, .NET, COM en SQL Server. Het formaat is identiek: 128 bits, 8-4-4-4-12 hex.
Het enige cosmetische verschil: Microsoft-tools tonen GUIDs soms in hoofdletters met accolades:
UUID: 550e8400-e29b-41d4-a716-446655440000
GUID: {550E8400-E29B-41D4-A716-446655440000}
Als iemand vraagt naar het “verschil tussen UUID en GUID”, is het antwoord: naamgeving.
Speciale UUID-waarden
RFC 9562 definieert twee speciale UUIDs:
| Naam | Waarde | Doel |
|---|---|---|
| Nil UUID | 00000000-0000-0000-0000-000000000000 | Geeft de afwezigheid van een waarde aan (zoals null) |
| Max UUID | ffffffff-ffff-ffff-ffff-ffffffffffff | Grensmarkering of schildwachtwaarde |
Gebruik deze nooit als echte identifiers — ze zijn per definitie niet uniek.
Botsingswaarschijnlijkheid: het verjaardagsprobleem
Het “verjaardagsprobleem” berekent hoeveel UUIDs je nodig hebt voordat een botsing waarschijnlijk wordt. Voor UUID v4 (122 willekeurige bits):
| Gegenereerde UUIDs | Botsingskans |
|---|---|
| 1 miljoen | ~10⁻²² (praktisch onmogelijk) |
| 1 miljard | ~10⁻¹⁶ (nog steeds verwaarloosbaar) |
| 2,71 × 10¹⁸ | 50% (de “verjaardagsgrens”) |
Ter vergelijking: als je 1 miljard UUIDs per seconde zou genereren, duurt het 86 jaar om een kans van 50% op één botsing te bereiken. In de praktijk zijn hardwarestoringen, softwarefouten en kosmische straling allemaal waarschijnlijker als oorzaak van een duplicaat dan de UUID v4-wiskunde.
De formule: p(n) ≈ n² / (2 × 2¹²²)
Zo valideer je een UUID
Een geldige UUID voldoet aan dit regex-patroon (hoofdletterongevoelig):
^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Dit controleert:
- Het 8-4-4-4-12 hex-formaat
- Het versiecijfer is 1–7 (positie 15)
- De variantnibble begint met 8, 9, a of b (positie 20)
function isValidUUID(str) {
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str);
}
isValidUUID("550e8400-e29b-41d4-a716-446655440000"); // → true
isValidUUID("not-a-uuid"); // → false
UUIDs genereren in elke taal
JavaScript / TypeScript
// Browser & Node.js — built-in v4
crypto.randomUUID();
// npm uuid package — supports v1, v3, v4, v5, v7
import { v4, v7 } from "uuid";
v4(); // random
v7(); // time-ordered
Python
import uuid
uuid.uuid4() # random
uuid.uuid5(uuid.NAMESPACE_DNS, "example.com") # deterministic
# uuid.uuid7() planned for Python 3.14+
Go
import "github.com/google/uuid"
uuid.New() // v4 random
uuid.Must(uuid.NewV7()) // v7 time-ordered
Java
import java.util.UUID;
UUID.randomUUID(); // v4 random
// UUID v7: use com.fasterxml.uuid or java.util.UUID in JDK 21+
SQL (PostgreSQL)
-- v4 (PostgreSQL 13+)
SELECT gen_random_uuid();
-- v7 (PostgreSQL 18+)
SELECT uuidv7();
Veelvoorkomende toepassingen
Primaire databasesleutels
UUIDs laten je ID’s overal genereren — in de applicatie, op de client, aan de edge — zonder een omweg via een server. Dit maakt offline-first-architecturen mogelijk en vereenvoudigt gedistribueerde systemen. Gebruik v7 voor de beste indexprestaties, of v4 als volgorde je niet uitmaakt.
API-verzoektracering
Ken een UUID toe aan elk API-verzoek op het ingangspunt (gateway, load balancer). Geef hem door aan alle downstream-diensten in een header zoals X-Request-ID. Dit maakt het eenvoudig om logs over microservices heen te correleren.
Idempotentiesleutels
API’s gebruiken UUIDs als idempotentiesleutels om ervoor te zorgen dat opnieuw verzonden verzoeken geen dubbele resources aanmaken. De client genereert een UUID vóór de eerste poging en stuurt dezelfde UUID bij nieuwe pogingen mee.
Sessie-identifiers
UUIDs bieden voldoende uniciteit om sessiebotsingen over grote gebruikersgroepen te voorkomen. Anders dan auto-increment-integers zijn ze niet enumereerbaar — een aanvaller kan geen geldige sessie-ID’s raden door een getal op te hogen.
Content-addressable storage
UUID v5 genereert deterministische ID’s op basis van inhoud. Bij dezelfde invoer krijg je altijd dezelfde UUID — nuttig voor deduplicatie, caching en reproduceerbare builds.
Beveiligingsoverwegingen
UUIDs zijn GEEN beveiligingstokens
UUIDs zijn ontworpen voor uniciteit, niet voor geheimhouding. Belangrijke aandachtspunten:
- UUID v1 legt de generatietimestamp en het MAC-adres bloot
- UUID v4 heeft 122 willekeurige bits, maar een voorspelbare structuur (versie- en variantbits zijn vast)
- UUID v3/v5 zijn deterministisch — iedereen die de namespace en naam kent, kan de UUID reproduceren
Gebruik voor beveiligingstokens, API-sleutels of sessiegeheimen een speciale CSPRNG met 128+ bits puur willekeurige gegevens:
// For security tokens — NOT a UUID, but fully random
const token = Array.from(crypto.getRandomValues(new Uint8Array(32)))
.map(b => b.toString(16).padStart(2, "0"))
.join("");
UUID v7 legt de aanmaaktijd bloot
De eerste 48 bits van een UUID v7 coderen de aanmaaktimestamp in milliseconden. Iedereen die een v7-UUID ontvangt, kan afleiden wanneer hij is aangemaakt:
const hex = "01906b5e-4a3e-7234-8f56-b8c12d4e5678".replace(/-/g, "").slice(0, 12);
new Date(parseInt(hex, 16));
// → 2024-07-01T12:34:56.000Z
Als de aanmaaktijd gevoelige informatie is, gebruik dan v4.
Gebruik UUIDs niet om enumeratie te voorkomen
Hoewel UUIDs moeilijker te raden zijn dan opeenvolgende integers, mogen ze niet je enige toegangsbeveiligingsmechanisme zijn. Dwing altijd autorisatiecontroles af — vertrouw niet op URL-obscuriteit.
Veelgestelde vragen
Waarom zitten er koppeltekens in UUIDs?
De koppeltekens in het 8-4-4-4-12-formaat zijn puur voor de leesbaarheid voor mensen. Ze bevatten geen gegevens en worden genegeerd bij het inlezen van de UUID. Sommige systemen slaan UUIDs op zonder koppeltekens (32 hex-tekens), wat net zo geldig is.
Kunnen twee UUIDs ooit hetzelfde zijn?
Theoretisch ja, praktisch nee. Voor UUID v4 met 122 willekeurige bits is de kans op het genereren van twee identieke UUIDs ongeveer 1 op 5,3 × 10³⁶ voor een willekeurig paar. Bij generatiesnelheden uit de praktijk is de kans dat je door de bliksem wordt getroffen én de jackpot wint groter dan de kans op een UUID-botsing.
Zijn UUIDs sequentieel?
Alleen sommige versies. UUID v1, v6 en v7 bevatten timestamps en sorteren chronologisch. UUID v4 is volledig willekeurig zonder volgorde. UUID v3 en v5 zijn deterministisch maar niet geordend.
Hoeveel opslagruimte gebruikt een UUID?
- Binair: 16 bytes (128 bits) — de meest efficiënte opslag
- String (met koppeltekens): 36 bytes (ASCII)
- String (zonder koppeltekens): 32 bytes (ASCII)
De meeste databases slaan UUIDs intern op in binair formaat. Het ingebouwde uuid-type van PostgreSQL gebruikt precies 16 bytes.
Moet ik UUID of auto-increment gebruiken voor primaire sleutels?
Auto-increment is eenvoudiger voor toepassingen met één database (kleiner, sneller, sequentieel). UUID is beter voor gedistribueerde systemen (overal genereren, geen coördinatie, merge-veilig). Als je UUIDs gebruikt, kies dan bij voorkeur v7 voor de beste databaseprestaties.
Wat is RFC 9562?
RFC 9562, gepubliceerd in mei 2024, is de nieuwste UUID-standaard. Het vervangt RFC 4122 en introduceert formeel UUID-versies 6, 7 en 8. Het schrijft v1 af ten gunste van v6/v7 en definieert de nil- en max-UUID-waarden. Als je UUID-generatie of -validatie implementeert, is RFC 9562 de gezaghebbende referentie.
Kan ik UUIDs gebruiken in verschillende programmeertalen?
Ja. Het UUID-formaat (128-bit, 8-4-4-4-12 hex) is taalonafhankelijk. Een UUID gegenereerd in JavaScript wordt correct verwerkt in Python, Go, Java of elke andere taal met UUID-ondersteuning. Deze interoperabiliteit is een van de grootste sterke punten van UUID.
Genereer, decodeer en valideer UUIDs direct met onze UUID Generator — ondersteunt v1, v4, v5 en v7 met batchgeneratie, 100% in je browser.
Twijfel je over welke UUID-versie je moet kiezen? De vergelijking van UUID v4, v7, ULID en Snowflake behandelt databasebenchmarks en codevoorbeelden als praktische keuzegids.