Skip to content
Terug naar blog
Tutorials

UUID v4 vs v7 vs ULID vs Snowflake: ID-gids (2026)

UUID v4, v7, ULID, Snowflake ID en NanoID vergeleken op database-prestaties, sorteerbaarheid, opslaggrootte en ecosysteemondersteuning met codevoorbeelden.

15 min leestijd

Nieuw met UUID’s? Begin met onze Wat is een UUID? Volledige gids voor de basis van UUID-formaat, versies en toepassingen.

UUID v4 vs v7 vs ULID vs Snowflake: de juiste ID kiezen voor je database in 2026

Het verkeerde ID-schema kiezen kan je duur komen te staan. Willekeurige UUID v4 als primary key op een tabel met 100 miljoen rijen veroorzaakt tot 10 keer meer index-page-splits dan sequentiële ID’s. Snowflake ID’s vereisen een centraal worker-register dat een single point of failure wordt. ULID leek het perfecte compromis — tot UUID v7 als IETF-standaard verscheen.

Deze gids biedt een beslisschema, harde prestatiecijfers en codevoorbeelden waarmee je de juiste identifier voor je systeem kiest.

Snelle beslisboom

Jouw eisBeste keuzeWaarom
Database primary key (nieuw project)UUID v7Tijd-geordend, standaard uuid-kolomtype, beste indexprestaties
Algemene unieke ID (geen ordening nodig)UUID v4Universele ondersteuning, geen configuratie, 122 bits willekeur
Deterministische ID uit bekende invoerUUID v5Dezelfde namespace + naam produceert altijd dezelfde UUID
Gedistribueerd systeem met hoge doorvoer (>100K ID’s/sec/node)Snowflake ID64-bit integer, monotoon binnen een worker, ingebouwde BIGINT-opslag
Korte URL-veilige token of client-side IDNanoID21 tekens, URL-veilig alfabet, aanpasbare lengte
Bestaand systeem dat al ULID gebruiktULIDBehouden — functioneel equivalent aan UUID v7, migratie is de moeite niet waard

UUID-versies in detail

UUID v1: tijd + MAC-adres (afgeschreven)

UUID v1 encodeert een 60-bits timestamp en het 48-bits MAC-adres van de machine. Het was de originele “sorteerbare UUID”, maar heeft twee fatale gebreken: het lekt hardware-identiteit en gebruikt een niet-standaard timestamp-epoch (15 oktober 1582). RFC 9562 schrijft v1 formeel af ten gunste van v6/v7. Gebruik v1 niet in nieuwe projecten.

UUID v4: pure willekeur

UUID v4 vult 122 van zijn 128 bits met cryptografisch veilige willekeurige data. Het is de meest gebruikte versie — simpel, privé en universeel ondersteund.

Sterke punten:

  • Geen configuratie, geen coördinatie nodig
  • Volledig anoniem — geen timestamp of hardware-info gelekt
  • Ondersteund door elke database, taal en framework

Zwakte:

  • Willekeurige distributie veroorzaakt B-tree-indexfragmentatie. Op schrijf-intensieve tabellen met miljoenen rijen kunnen v4 primary keys de insert-prestaties met 2 tot 10 keer degraderen vergeleken met sequentiële ID’s, door overmatige page-splits.
// Generate UUID v4 — built-in in all modern browsers and Node.js
const id = crypto.randomUUID();
// → "550e8400-e29b-41d4-a716-446655440000"

UUID v5: deterministische hash

UUID v5 berekent een hash van een namespace-UUID en een naam-string met SHA-1 om een deterministische UUID te produceren. Dezelfde invoer levert altijd dezelfde uitvoer op.

Toepassingen: stabiele ID’s genereren uit URL’s, DNS-namen of elke reproduceerbare invoer. Verkies v5 boven v3 (dat het zwakkere MD5 gebruikt).

import uuid

# Same inputs → same UUID, every time
id = uuid.uuid5(uuid.NAMESPACE_DNS, "example.com")
# → "cfbff0d1-9375-5685-968c-48ce8b15ae17"

UUID v7: tijd-geordend willekeurig (aanbevolen)

UUID v7 (RFC 9562, mei 2024) bevat een 48-bits Unix-timestamp in milliseconden in de meest significante bits, gevolgd door 74 bits cryptografische willekeur.

Waarom v7 de nieuwe standaard is voor database-keys:

  • Sequentiële inserts: nieuwe UUID’s zijn altijd groter dan voorgaande (binnen milliseconde-precisie), dus B-tree inserts voegen altijd toe aan het einde van de index
  • Tot 90% minder page-splits vergeleken met v4 bij schrijf-intensieve workloads
  • Natuurlijke chronologische sortering zonder extra created_at-kolom
  • Standaard uuid-kolomtype — geen schema-wijzigingen nodig bij migratie vanaf v4
  • 74 bits willekeur — voldoende voor vrijwel alle toepassingen (v4 heeft 122 bits)

Afweging: de aanmaak-timestamp zit in de ID verwerkt. Als je ondoorzichtige ID’s nodig hebt die de aanmaaktijd niet onthullen, houd je dan bij v4.

// UUID v7 generation (Node.js 20+)
import { v7 as uuidv7 } from "uuid";
const id = uuidv7();
// → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"
// Older IDs always sort before newer ones

PostgreSQL- en MySQL-prestaties: v4 vs v7

Benchmarks op een PostgreSQL 16-tabel met 50 miljoen rijen (B-tree primary key):

MetriekUUID v4UUID v7Verbetering
Insert-doorvoer (rijen/sec)12.40028.6002,3x sneller
Indexgrootte na 50M rijen4,2 GB2,8 GB33% kleiner
Page-splits tijdens bulk-insert1,2M84K93% minder
Sequentiële scan na insert320 ms180 ms44% sneller

In MySQL/InnoDB is de impact nog dramatischer, omdat de primary key samenvalt met de clustered index — willekeurige v4-UUID’s forceren constante page-reorganisatie, terwijl v7 zich gedraagt als een auto-increment.

Alternatieve ID-schema’s

ULID — de pre-v7 kampioen

ULID (Universally Unique Lexicographically Sortable Identifier) werd in 2016 gecreëerd om het sorteerprobleem van UUID v4 op te lossen. Het encodeert een 48-bits milliseconde-timestamp gevolgd door 80 bits willekeur in een 26-tekens Crockford Base32-string.

01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp          Randomness
  48 bits            80 bits

ULID vs UUID v7 — moet je overstappen?

AspectULIDUUID v7
SorteerbaarJaJa
String-lengte26 tekens36 tekens
Opslag16 bytes16 bytes
StandaardCommunity-specIETF RFC 9562
Ingebouwd DB-typeNee (CHAR(26) of BYTEA)Ja (uuid)
Taalondersteuningnpm, PyPI, crates.ioIngebouwd in de meeste standaardbibliotheken

Conclusie: begin je nieuw, kies dan UUID v7 — het heeft dezelfde sorteerbaarheid met veel betere ecosysteemondersteuning en ingebouwde database-types. Gebruik je al ULID, dan is er geen dringende reden om te migreren; de twee zijn functioneel equivalent.

Snowflake ID — gedistribueerde systemen met hoge doorvoer

Snowflake ID (gemaakt door Twitter in 2010) past in 64 bits:

0 | 41 bits timestamp | 10 bits worker ID | 12 bits sequence
  • 41-bits timestamp: milliseconden sinds een aangepaste epoch (~69 jaar bereik)
  • 10-bits worker-ID: ondersteunt 1.024 unieke workers
  • 12-bits sequentie: tot 4.096 ID’s per milliseconde per worker

Sterke punten:

  • 8 bytes — half zo groot als UUID/ULID, past in een BIGINT-kolom
  • Monotoon binnen een worker — gegarandeerde ordening per node
  • ~4,1 miljoen ID’s/sec theoretische doorvoer per worker
  • Leesbaar voor mensen als gewone integer

Zwakke punten:

  • Vereist centrale coördinatie — worker-ID’s moeten worden toegewezen en beheerd (doorgaans via ZooKeeper, etcd of een configuratieservice)
  • Gevoelig voor klok-afwijking — als systeemklokken uit de pas lopen, kunnen ID’s botsen of achteruit springen
  • Aangepaste epoch — elke implementatie kiest een eigen epoch, wat interoperabiliteit tussen systemen bemoeilijkt
  • Geen standaard — tientallen incompatibele varianten (Twitter, Discord, Instagram, enz.)
// Snowflake ID generation (using sony/sonyflake)
package main

import (
    "fmt"
    "github.com/sony/sonyflake"
)

func main() {
    sf := sonyflake.NewSonyflake(sonyflake.Settings{})
    id, _ := sf.NextID()
    fmt.Println(id) // → 175928847299543040
}

Kies Snowflake wanneer: je systeem genereert >100K ID’s/sec, je hebt compacte 64-bits integers nodig en je hebt al infrastructuur voor worker-ID-toewijzing (bijvoorbeeld Kubernetes pod-ordinals).

NanoID — compacte URL-veilige ID’s

NanoID genereert korte (standaard 21 tekens), URL-veilige identifiers met het alfabet A-Za-z0-9_-. Het gebruikt crypto.getRandomValues() voor beveiliging.

import { nanoid } from "nanoid";
const id = nanoid();    // → "V1StGXR8_Z5jdHi6B-myT"
const short = nanoid(10); // → "IRFa-VaY2b"

Het beste voor: korte URL’s, frontend-componentsleutels, uitnodigingscodes, bestandsnamen — overal waar stringlengte ertoe doet en je geen ordening op databaseniveau of interoperabiliteit tussen systemen nodig hebt.

Niet geschikt voor: database primary keys (geen ingebouwd DB-type, geen sorteerbaarheid, geen timestamp).

CUID2 — collision-bestendig op schaal

CUID2 genereert ID’s met variabele lengte, ontworpen voor horizontale schaling. Het combineert een teller, timestamp, fingerprint en willekeur.

Niche-gebruik: systemen die collision-bestendigheid nodig hebben over veel onafhankelijke generators zonder coördinatie. In de praktijk vult UUID v7 deze behoefte in met betere standaardisatie.

Uitgebreide vergelijkingstabel

EigenschapUUID v4UUID v7ULIDSnowflakeNanoID
Lengte36 tekens36 tekens26 tekens15-20 cijfers21 tekens (standaard)
Opslag16 bytes16 bytes16 bytes8 bytes~21 bytes
SorteerbaarNeeJa (tijd)Ja (tijd)Ja (tijd)Nee
TimestampNee48-bit ms48-bit ms41-bit msNee
Willekeur122 bits74 bits80 bits12-bit seq~126 bits
StandaardRFC 9562RFC 9562CommunityProprietaryCommunity
Ingebouwd DB-typeuuiduuidNeeBIGINTNee
CoördinatieGeenGeenGeenWorker-registerGeen
URL-veiligNee (streepjes)Nee (streepjes)JaJa (integer)Ja
Collision bij 1M ID’s~10⁻²²~10⁻¹⁸~10⁻²⁰Nul (monotoon)~10⁻²¹

Codevoorbeelden: elk ID-type genereren

JavaScript / TypeScript

import { v4 as uuidv4, v7 as uuidv7 } from "uuid";
import { ulid } from "ulid";
import { nanoid } from "nanoid";

// UUID v4
console.log(uuidv4());
// → "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"

// UUID v7
console.log(uuidv7());
// → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"

// ULID
console.log(ulid());
// → "01ARZ3NDEKTSV4RRFFQ69G5FAV"

// NanoID
console.log(nanoid());
// → "V1StGXR8_Z5jdHi6B-myT"

Python

import uuid
from ulid import ULID
from nanoid import generate

# UUID v4
print(uuid.uuid4())
# → "a8098c1a-f86e-11da-bd1a-00112444be1e"

# UUID v7 (Python 3.14+ planned, or use uuid7 package)
from uuid_extensions import uuid7
print(uuid7())
# → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"

# ULID
print(ULID())
# → "01ARZ3NDEKTSV4RRFFQ69G5FAV"

# NanoID
print(generate(size=21))
# → "V1StGXR8_Z5jdHi6B-myT"

Go

package main

import (
    "fmt"

    "github.com/google/uuid"     // UUID v4 & v7
    "github.com/oklog/ulid/v2"   // ULID
    gonanoid "github.com/matoous/go-nanoid/v2" // NanoID
)

func main() {
    // UUID v4
    fmt.Println(uuid.New())
    // → "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"

    // UUID v7
    fmt.Println(uuid.Must(uuid.NewV7()))
    // → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"

    // ULID
    fmt.Println(ulid.Make())
    // → "01ARZ3NDEKTSV4RRFFQ69G5FAV"

    // NanoID
    id, _ := gonanoid.New()
    fmt.Println(id)
    // → "V1StGXR8_Z5jdHi6B-myT"
}

Migreren van UUID v4 naar v7

Als je systeem al UUID v4 primary keys gebruikt en je de prestatievoordelen van v7 wilt, dan is er goed nieuws: v4 en v7 delen hetzelfde 128-bits formaat en worden opgeslagen in hetzelfde uuid kolomtype. Geen schema-migratie nodig.

Migratiestrategie

  1. Nieuwe records gebruiken v7, oude records houden v4. Beide bestaan naast elkaar in dezelfde kolom. Queries en joins werken identiek.
  2. Update je ID-generatiecode — vervang uuidv4() door uuidv7() in je applicatielaag.
  3. Herschrijf bestaande v4-ID’s NIET. Dat zou foreign keys, externe referenties en gecachte URL’s breken.
  4. Monitor indexprestaties. Naarmate de v4/v7-verhouding naar v7 verschuift, neemt de indexfragmentatie geleidelijk af.

Compatibiliteitscontrole

-- Both v4 and v7 coexist in the same uuid column
SELECT id, version FROM (
  SELECT id,
    CASE get_byte(id::bytea, 6) >> 4
      WHEN 4 THEN 'v4'
      WHEN 7 THEN 'v7'
      ELSE 'other'
    END AS version
  FROM your_table
) t
GROUP BY version;

Veelgestelde vragen

Moet ik UUID v7 of auto-increment integers gebruiken?

Auto-increment integers zijn eenvoudiger en kleiner (4 tot 8 bytes versus 16 bytes), maar vereisen een gecentraliseerde sequentie — alleen de database kan ze genereren. UUID v7 kan overal worden gegenereerd (client, edge, microservice) zonder een omweg via een server. Gebruik auto-increment voor eenvoudige single-database apps; gebruik UUID v7 voor gedistribueerde systemen, multi-tenant architecturen of wanneer je client-side ID-generatie nodig hebt.

Is 74 bits willekeur van UUID v7 genoeg?

Ja. 74 willekeurige bits geven 2⁷⁴ ≈ 1,9 × 10²² mogelijke waarden per milliseconde. Zelfs bij het genereren van 1 miljoen ID’s per milliseconde is de collision-kans ongeveer 10⁻¹⁰ — ruim onder elke praktische grens. De 122 willekeurige bits van UUID v4 zijn voor de meeste toepassingen overkill.

Kan ik de timestamp uit een UUID v7 halen?

Ja. De eerste 48 bits encoderen een Unix-timestamp in milliseconden:

function extractTimestamp(uuidv7) {
  const hex = uuidv7.replace(/-/g, "").slice(0, 12);
  const ms = parseInt(hex, 16);
  return new Date(ms);
}

extractTimestamp("01906b5e-4a3e-7234-8f56-b8c12d4e5678");
// → 2024-07-01T12:34:56.000Z

Dit is een feature, geen bug — maar als je ondoorzichtige ID’s nodig hebt, gebruik dan v4.

Ondersteunt PostgreSQL 18 UUID v7 ingebouwd?

PostgreSQL 18 (uitgebracht in 2025) voegt een ingebouwde uuidv7()-functie toe, waardoor extensies als pgcrypto of pg_uuidv7 niet meer nodig zijn. MySQL heeft nog geen ingebouwde v7-generatie — genereer die in je applicatielaag.

Waarom niet gewoon ULID gebruiken?

ULID bestond al voor UUID v7 en lost hetzelfde probleem op. Nu v7 een IETF-standaard is (RFC 9562) heeft het belangrijke voordelen: ingebouwd uuid-database-type (16 bytes, efficiënt geïndexeerd), bredere taal- en framework-ondersteuning en formele standaardisatie. Gebruik je al ULID, dan werkt het prima — geen noodzaak om te migreren. Voor nieuwe projecten verdient UUID v7 de voorkeur.

Wanneer is Snowflake ID de betere keuze?

Wanneer je compacte 64-bits ID’s nodig hebt bij extreme doorvoer (>100K ID’s/sec per node) en je al infrastructuur hebt voor worker-ID-toewijzing. De 8-byte BIGINT-opslag van Snowflake is half zo groot als UUID, wat telt bij miljarden rijen. De afweging is operationele complexiteit: je moet worker-ID-toewijzing beheren en klok-afwijking afhandelen.


Nu meteen UUID’s genereren? Probeer onze UUID-generator — ondersteunt v1, v4, v5 en v7 met batchgeneratie en decodering, 100% in je browser.

Gerelateerde artikelen

Alle artikelen bekijken