Skip to content
Powrót do bloga
Poradniki

Czym jest UUID? Przewodnik po formacie, wersjach i zastosowaniach

UUID od podstaw: 128-bitowa struktura, format hex, jak wewnętrznie działają wersje v1/v3/v4/v5/v7, matematyka kolizji, praktyczne zastosowania i przykłady kodu.

13 min czytania

Czym jest UUID? 128-bitowa struktura, wersje i praktyczne zastosowania

Za każdym razem, gdy rejestrujesz się w jakiejś usłudze, dla twojego konta tworzony jest unikalny identyfikator. Każde żądanie API niesie ze sobą trace ID. Każdy wiersz w rozproszonej bazie danych potrzebuje klucza głównego, który nie zderzy się z kluczami generowanymi na innych maszynach. Rozwiązanie stojące za tym wszystkim? UUID — Universally Unique Identifier.

Ten przewodnik wyjaśnia, czym są UUID, jak są zbudowane, co każda wersja robi pod maską oraz kiedy ich używać (a kiedy unikać).

UUID w pigułce

UUID to 128-bitowy (16-bajtowy) identyfikator zaprojektowany tak, aby był globalnie unikalny bez konieczności korzystania z centralnego rejestru. Zapisuje się go jako 32 cyfry szesnastkowe w kanonicznym formacie 8-4-4-4-12:

550e8400-e29b-41d4-a716-446655440000
|------| |--| |--| |--| |----------|
 8 hex   4    4    4      12 hex

To 32 znaki hex + 4 myślniki = łącznie 36 znaków. Myślniki są czysto kosmetyczne — nie niosą żadnych danych.

Najważniejsze fakty:

  • 128 bitów = 2¹²⁸ ≈ 3,4 × 10³⁸ możliwych wartości
  • Standaryzowany przez RFC 9562 (maj 2024, zastępuje RFC 4122)
  • W ekosystemach Microsoftu nazywany również GUID (Globally Unique Identifier) — ten sam format, inna nazwa
  • Wspierany natywnie przez PostgreSQL (typ uuid), MySQL (BINARY(16) lub CHAR(36)) oraz praktycznie każdy język programowania

Anatomia UUID

Każdy UUID koduje dwa pola metadanych w stałych pozycjach bitowych, niezależnie od wersji:

550e8400-e29b-41d4-a716-446655440000
                  ^  ^
                  |  |
          Version-┘  └-Variant

Pole wersji (bity 48–51)

  1. cyfra hex (pierwsza cyfra trzeciej grupy) identyfikuje wersję UUID:
Cyfra hexWersjaMetoda
1v1Timestamp + adres MAC
3v3Hash MD5 z namespace + nazwa
4v4Kryptograficznie losowy
5v5Hash SHA-1 z namespace + nazwa
6v6Przeporządkowany timestamp (RFC 9562)
7v7Unix timestamp + losowość (RFC 9562)
8v8Niestandardowy / zależny od implementacji

Pole wariantu (bity 64–65)

  1. cyfra hex (pierwsza cyfra czwartej grupy) identyfikuje wariant. Dla UUID zgodnych z RFC 4122/9562 pierwsze bity to 10, co oznacza, że ta cyfra hex zawsze przyjmuje wartość 8, 9, a lub b.

Przykładowy rozkład

550e8400-e29b-41d4-a716-446655440000
              ↑         ↑
              4 → v4    a → RFC 4122 variant

This is a UUID v4 (random), RFC 4122/9562 variant.

Wersje UUID — wyjaśnienie

UUID v1: timestamp + adres MAC

UUID v1 był pierwotnym projektem. Koduje:

  • 60-bitowy timestamp — odstępy 100-nanosekundowe od 15 października 1582 roku (reforma kalendarza gregoriańskiego)
  • 14-bitową sekwencję zegara — licznik monotoniczności zapobiegający duplikatom przy cofnięciu zegara
  • 48-bitowy node — zwykle adres MAC maszyny
|        Timestamp         | Ver |  Clk  |Var|    Node (MAC)     |
| 60 bits                  | 4b  | 14b   |2b | 48 bits           |

Problemy:

  • Ujawnia czas wygenerowania oraz tożsamość sprzętu (ryzyko prywatności)
  • Adresy MAC można sfałszować, co podważa unikalność
  • Epoka roku 1582 jest myląca i wymaga konwersji

Werdykt: wycofany przez RFC 9562. W identyfikatorach opartych na czasie używaj v7.

UUID v3: oparty na nazwie z MD5 (deterministyczny)

UUID v3 oblicza hash z namespace UUID oraz łańcucha nazwy za pomocą MD5. Te same dane wejściowe zawsze produkują ten sam UUID.

import uuid
# namespace = DNS, name = "example.com"
print(uuid.uuid3(uuid.NAMESPACE_DNS, "example.com"))
# → "9073926b-929f-31c2-abc9-fad77ae3e8eb"  (always this value)

Zdefiniowane są cztery standardowe namespace’y:

  • 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

Werdykt: funkcjonalny, ale lepiej wybrać v5 — SHA-1 jest silniejszy niż MD5.

UUID v4: losowy — najpopularniejszy

UUID v4 wypełnia 122 bity kryptograficznie bezpiecznymi danymi losowymi (pozostałe 6 bitów jest zarezerwowane na pola wersji i wariantu).

|           Random          | Ver |    Random     |Var|    Random       |
| 48 bits                   | 4b  | 12 bits       |2b | 62 bits         |

Przy 2¹²² ≈ 5,3 × 10³⁶ możliwych wartościach prawdopodobieństwo kolizji jest astronomicznie niskie. Aby osiągnąć 50% szansę na choć jedną kolizję, potrzeba około 2,71 × 10¹⁸ UUID — czyli 2,71 tryliona (10¹⁸ w polskiej długiej skali = angielski quintillion; uwaga: angielski „trillion” 10¹² to po polsku „bilion”, nie „trylion”).

// Every modern browser and Node.js supports this
const id = crypto.randomUUID();
console.log(id); // → "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"

Mocne strony: prostota, prywatność, uniwersalne wsparcie, brak potrzeby koordynacji.

Słaba strona: losowy rozkład powoduje fragmentację indeksów B-tree, gdy v4 jest używany jako klucz główny w bazie danych. Dla zastosowań intensywnie korzystających z bazy danych warto rozważyć v7.

UUID v5: oparty na nazwie z SHA-1 (deterministyczny)

Identyczny jak v3, ale używa SHA-1 zamiast MD5. Te same dane wejściowe zawsze produkują ten sam UUID.

import uuid
print(uuid.uuid5(uuid.NAMESPACE_DNS, "example.com"))
# → "cfbff0d1-9375-5685-968c-48ce8b15ae17"  (always this value)

Zastosowania:

  • Generowanie stabilnych ID na podstawie URL-i lub nazw DNS
  • Klucze do magazynów typu content-addressable
  • Powtarzalne fixture’y testowe

Ważne: v3 i v5 NIE są przeznaczone do celów bezpieczeństwa. Są deterministyczne — każdy, kto zna namespace i nazwę, może odtworzyć UUID.

UUID v7: Unix timestamp + losowość (rekomendowany dla nowych projektów)

UUID v7 to najnowsza wersja, wprowadzona w RFC 9562 (maj 2024). Koduje:

  • 48-bitowy Unix timestamp w milisekundach — monotonicznie rosnący
  • 74 bity kryptograficznej losowości
|    Unix timestamp (ms)    | Ver |  rand_a  |Var|     rand_b       |
| 48 bits                   | 4b  | 12 bits  |2b | 62 bits          |

Oznacza to, że UUID v7 są naturalnie sortowane według czasu utworzenia — nowsze UUID są zawsze leksykograficznie większe od starszych. Ta właściwość czyni je idealnymi jako klucze główne w bazie danych, gdzie indeksy B-tree pozostają sekwencyjne, zamiast losowo się fragmentować.

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)

Dlaczego to ma znaczenie dla baz danych: sekwencyjna natura v7 redukuje liczbę podziałów stron indeksu nawet o 90% w porównaniu do v4, co przekłada się na szybsze inserty, mniejsze indeksy i lepszą wydajność cache.

UUID a GUID — czym się różnią?

Funkcjonalnie niczym. GUID (Globally Unique Identifier) to nazwa stosowana przez Microsoft na UUID, używana w Windows, .NET, COM oraz SQL Server. Format jest identyczny: 128 bitów, hex w układzie 8-4-4-4-12.

Jedyna różnica kosmetyczna: narzędzia Microsoftu czasami wyświetlają GUID-y wielkimi literami i w nawiasach klamrowych:

UUID: 550e8400-e29b-41d4-a716-446655440000
GUID: {550E8400-E29B-41D4-A716-446655440000}

Jeżeli ktoś pyta o „różnicę między UUID a GUID”, odpowiedź brzmi: branding.

Specjalne wartości UUID

RFC 9562 definiuje dwa specjalne UUID:

NazwaWartośćCel
Nil UUID00000000-0000-0000-0000-000000000000Reprezentuje brak wartości (jak null)
Max UUIDffffffff-ffff-ffff-ffff-ffffffffffffZnacznik granicy lub wartość wartownik

Nigdy nie używaj ich jako rzeczywistych identyfikatorów — z definicji nie są unikalne.

Prawdopodobieństwo kolizji: problem urodzin

„Problem urodzin” pozwala obliczyć, ile UUID trzeba wygenerować, zanim kolizja stanie się prawdopodobna. Dla UUID v4 (122 losowe bity):

Wygenerowane UUIDPrawdopodobieństwo kolizji
1 milion~10⁻²² (praktycznie niemożliwe)
1 miliard~10⁻¹⁶ (nadal zaniedbywalne)
2,71 × 10¹⁸50% (granica „urodzinowa”)

Dla porównania: gdyby generować 1 miliard UUID na sekundę, osiągnięcie 50% szansy na pojedynczą kolizję zajęłoby 86 lat. W praktyce awarie sprzętu, błędy w oprogramowaniu i promieniowanie kosmiczne są bardziej prawdopodobnymi przyczynami duplikatu niż matematyka UUID v4.

Wzór: p(n) ≈ n² / (2 × 2¹²²)

Jak walidować UUID

Poprawny UUID pasuje do tego wzorca regex (bez rozróżniania wielkości liter):

^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

Sprawdza on:

  1. Format hex 8-4-4-4-12
  2. Cyfra wersji w zakresie 1–7 (pozycja 15)
  3. Nibble wariantu zaczyna się od 8, 9, a lub b (pozycja 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

Generowanie UUID w różnych językach

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();

Najczęstsze zastosowania

Klucze główne w bazach danych

UUID pozwalają generować ID gdziekolwiek — w aplikacji, na kliencie, na brzegu sieci — bez zaglądania do bazy danych. Umożliwia to architektury offline-first i upraszcza systemy rozproszone. Dla najlepszej wydajności indeksu używaj v7, a jeśli kolejność nie ma znaczenia — v4.

Śledzenie żądań API

Każdemu żądaniu API przypisuj UUID w punkcie wejścia (gateway, load balancer). Przekazuj je do wszystkich usług w dół przepływu w nagłówku takim jak X-Request-ID. Dzięki temu korelowanie logów między mikrousługami staje się trywialne.

Klucze idempotencji

API używają UUID jako kluczy idempotencji, aby ponownie wysłane żądania nie tworzyły duplikatów zasobów. Klient generuje UUID przed pierwszą próbą i wysyła ten sam UUID przy ponowieniach.

Identyfikatory sesji

UUID zapewniają wystarczającą unikalność, aby zapobiec kolizjom sesji w dużych bazach użytkowników. W odróżnieniu od liczb auto-increment nie da się ich enumerować — atakujący nie odgadnie poprawnych ID sesji przez zwiększanie liczby.

Magazyny content-addressable

UUID v5 generuje deterministyczne ID na podstawie zawartości. Dla tego samego wejścia zawsze otrzymasz ten sam UUID — przydatne przy deduplikacji, cache’owaniu i powtarzalnych buildach.

Kwestie bezpieczeństwa

UUID NIE są tokenami bezpieczeństwa

UUID są zaprojektowane pod kątem unikalności, a nie tajności. Kluczowe problemy:

  • UUID v1 ujawnia timestamp generacji oraz adres MAC
  • UUID v4 ma 122 losowe bity, ale przewidywalną strukturę (bity wersji i wariantu są stałe)
  • UUID v3/v5 są deterministyczne — każdy, kto zna namespace i nazwę, może odtworzyć UUID

Do tokenów bezpieczeństwa, kluczy API lub sekretów sesyjnych używaj dedykowanego CSPRNG z 128+ bitami czystej losowości:

// 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 ujawnia czas utworzenia

Pierwsze 48 bitów UUID v7 koduje timestamp utworzenia w milisekundach. Każdy, kto otrzyma UUID v7, może odczytać moment jego powstania:

const hex = "01906b5e-4a3e-7234-8f56-b8c12d4e5678".replace(/-/g, "").slice(0, 12);
new Date(parseInt(hex, 16));
// → 2024-07-01T12:34:56.000Z

Jeśli czas utworzenia jest informacją wrażliwą, używaj v4.

Nie używaj UUID do zapobiegania enumeracji

Choć UUID trudniej zgadnąć niż sekwencyjne liczby całkowite, nie powinny być jedynym mechanizmem kontroli dostępu. Zawsze egzekwuj kontrole autoryzacji — nie polegaj na nieprzejrzystości URL.

Często zadawane pytania

Dlaczego w UUID są myślniki?

Myślniki w formacie 8-4-4-4-12 służą wyłącznie czytelności dla człowieka. Nie niosą żadnych danych i są ignorowane podczas parsowania. Niektóre systemy przechowują UUID bez myślników (32 znaki hex), co jest równie poprawne.

Czy dwa UUID mogą być takie same?

Teoretycznie tak, praktycznie nie. Dla UUID v4 ze 122 losowymi bitami prawdopodobieństwo wygenerowania dwóch identycznych UUID wynosi w przybliżeniu 1 na 5,3 × 10³⁶ dla dowolnej pary. Przy realnych tempach generowania jest bardziej prawdopodobne, że trafi cię piorun w trakcie wygranej w lotto, niż że napotkasz kolizję UUID.

Czy UUID są sekwencyjne?

Tylko niektóre wersje. UUID v1, v6 i v7 zawierają timestamp i sortują się chronologicznie. UUID v4 jest całkowicie losowy, bez żadnej kolejności. UUID v3 i v5 są deterministyczne, ale nie uporządkowane.

Ile miejsca zajmuje UUID?

  • Binarnie: 16 bajtów (128 bitów) — najbardziej wydajna forma przechowywania
  • String (z myślnikami): 36 bajtów (ASCII)
  • String (bez myślników): 32 bajty (ASCII)

Większość baz danych przechowuje UUID wewnętrznie w formacie binarnym. Natywny typ uuid w PostgreSQL zajmuje dokładnie 16 bajtów.

UUID czy auto-increment dla kluczy głównych?

Auto-increment jest prostszy w aplikacjach z jedną bazą danych (mniejszy, szybszy, sekwencyjny). UUID jest lepszy w systemach rozproszonych (generowanie wszędzie, brak koordynacji, bezpieczne łączenie). Jeśli wybierasz UUID, preferuj v7 dla najlepszej wydajności bazy danych.

Czym jest RFC 9562?

RFC 9562, opublikowany w maju 2024 roku, to najnowszy standard UUID. Zastępuje RFC 4122 i formalnie wprowadza wersje UUID 6, 7 oraz 8. Wycofuje v1 na rzecz v6/v7 oraz definiuje wartości nil i max UUID. Jeżeli implementujesz generowanie lub walidację UUID, RFC 9562 jest miarodajnym źródłem.

Czy mogę używać UUID w różnych językach programowania?

Tak. Format UUID (128-bitowy, hex 8-4-4-4-12) jest niezależny od języka. UUID wygenerowany w JavaScripcie zostanie poprawnie odczytany w Pythonie, Go, Javie czy dowolnym innym języku ze wsparciem dla UUID. Ta interoperacyjność to jedna z największych zalet UUID.


Generuj, dekoduj i waliduj UUID natychmiast w naszym narzędziu Generator UUID — wspiera v1, v4, v5 i v7 z generowaniem wsadowym, w 100% w przeglądarce.

Wybierasz między wersjami UUID dla swojego kolejnego projektu? Praktyczny przewodnik wyboru z benchmarkami baz danych i przykładami kodu — porównanie UUID v4 vs v7 vs ULID vs Snowflake — pojawi się wkrótce.

Powiązane artykuły

Zobacz wszystkie artykuły