> uuidv7 generator <
// Uporządkowane czasowo, sortowalne UUID-y (RFC 9562, 2024) — 48-bitowy znacznik czasu Unix w ms + 74 losowe bity, generowane lokalnie
// DEKODUJ / SPRAWDŹ UUIDV7
Wklej dowolny UUID poniżej, aby wyodrębnić jego osadzony znacznik czasu, wersję i wariant. Działa z v7 i informuje, jeśli dane wejściowe są inną wersją UUID.
UUIDv7 zgodny ze specyfikacją
Implementuje uporządkowany czasowo format UUID z RFC 9562 (maj 2024): 48-bitowy znacznik czasu Unix w milisekundach, 4-bitowa wersja 7, 12-bitowe rand_a, 2-bitowy wariant, 62-bitowe rand_b. Zweryfikowany względem wektorów testowych specyfikacji.
Chronologiczny porządek sortowania
Sortuj numerycznie lub leksykograficznie, a otrzymasz kolejność wstawiania — idealne dla kluczy głównych w drzewach B, indeksów szeregów czasowych i korelacji logów. Koniec z losowymi podziałami stron v4 czy pofragmentowanymi indeksami.
Monotoniczność w tej samej milisekundzie
Gdy kilka UUID-ów trafia w jedną milisekundę, część losowa jest ściśle inkrementowana, aby wynik pozostał posortowany w obrębie tej ms. Wyłącz dla zwykłej Metody 1 z RFC 9562 (wypełnienie losowe), jeśli wolisz.
Sprawdź dowolny UUIDv7
Wklej UUID v7, a dekoder wyodrębni osadzony znacznik czasu (ms + ISO 8601), bity wersji, bity wariantu oraz pola rand_a / rand_b. Przydatne do debugowania, archeologii logów i ścieżek audytu.
// O UUIDV7
Jak działa UUIDv7:
UUIDv7 to 128-bitowy identyfikator zbudowany jako unix_ts_ms (48) | ver (4) | rand_a (12) | var (2) | rand_b (62). Pierwsze 48 bitów to bieżący znacznik czasu Unix w milisekundach, big-endian, co sprawia, że UUID rośnie monotonicznie w czasie. Kolejne 4 bity kodują wersję (binarnie 0111 = dziesiętnie 7), więc trzecia grupa oddzielona myślnikami zawsze zaczyna się cyfrą 7. rand_a to 12 losowych bitów używanych do rozdzielczości sub-milisekundowej lub jako dodatkowa entropia. 2-bitowe pole wariantu jest ustalone na 10 (więc pierwszy znak czwartej grupy to zawsze 8, 9, a lub b). Pozostałe 62 bity (rand_b) pochodzą z crypto.getRandomValues() przy każdym generowaniu. Całkowita entropia na UUID wynosi 74 losowe bity, co jest odporne na kolizje przy każdej realistycznej szybkości generowania.
Przykład:
018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55 (ts=2024-05-08T15:00:00.000Z)
Standardy i odniesienia:
- >RFC 9562 — Universally Unique IDentifiers (UUIDs), maj 2024 (zastępuje RFC 4122, definiuje v6/v7/v8)
- >RFC 4122 — pierwotna specyfikacja UUID z 2005 roku (nadal miarodajna dla v1-v5)
- >Web Crypto API (W3C) —
crypto.getRandomValues()CSPRNG używany dla 74 losowych bitów - >Zachowanie
gen_random_uuid()w PostgreSQL (domyślnie v4, v7 w rozszerzeniach pgcrypto / forkach) - >draft-peabody-dispatch-new-uuid-format — pierwotna propozycja v6/v7/v8, która stała się RFC 9562
Dlaczego warto używać UUIDv7:
- >Klucze główne bazy danych z lokalnością wstawiania — strony pozostają upakowane, indeksy nie fragmentują się
- >Zastępuje parę sekwencja + UUID: jedna kolumna, sortowalna ORAZ globalnie unikalna
- >Zastępuje klucze główne v4 w tabelach o intensywnym zapisie, rozwiązując problem podziału stron przy losowym wstawianiu
- >Identyfikatory korelacji logów, które sortują się według czasu utworzenia bez osobnej kolumny znacznika czasu
- >Systemy rozproszone, w których wielu zapisujących potrzebuje uporządkowanych identyfikatorów bez koordynatora
- >Event sourcing / logi tylko do dopisywania, gdzie porządek chronologiczny jest naturalnym indeksem
- >Klucze S3 / pamięci obiektowej, gdzie sortowanie prefiksów odpowiada kolejności wstawiania
- >Zastępuje Snowflake / KSUID / ULID tam, gdzie preferowany jest standardowy format
Powiązane narzędzia:
- >Generator UUID — generuje v4 (losowy) i v1 (znacznik czasu), gdy nie potrzebujesz porządku sortowania v7
- >Generator GUID — ten sam identyfikator pod nazewnictwem Microsoft
- >Konwerter znaczników czasu — konwertuje osadzone ms Unix z powrotem na czas lokalny / ISO 8601
- >Konwerter Epoch — sprawdź 48-bitową część znacznika czasu w dowolnej strefie czasowej
- >Generator haseł — kryptograficznie losowe tokeny, gdy sortowalność nie jest wymagana
// PRZYKŁADOWE WYNIKI
Pojedynczy UUIDv7 wygenerowany teraz
count=1, format=standard, timestamp=current
output:
018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55
Masowa partia z monotonicznością w tej samej milisekundzie
count=5, format=standard, monotonic=on
output:
018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a56 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a57 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a58 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a59
Niestandardowy historyczny znacznik czasu — uzupełnianie migracji
count=1, timestamp=custom, value=1577836800000 (2020-01-01)
output:
016f5e66-e800-7c9a-b403-2f1d4a7c91ee
Kompaktowy format dla adresów URL / nazw plików
count=1, format=no-hyphens
output:
018f5c2e90c07a4fb6ee8dfe3c2b0a55
Zdekodowany UUIDv7 — sprawdź osadzone pola
input = 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55
output:
ts_ms = 1715180400000 ISO = 2024-05-08T15:00:00.000Z ver = 7 var = 10 (RFC 4122) rand_a = 0xa4f rand_b = 0x36ee8dfe3c2b0a55
// ZAIMPLEMENTUJ SAMODZIELNIE
Większość języków ma albo pomocnika w bibliotece standardowej, albo jednoplikową implementację UUIDv7, odkąd RFC 9562 pojawił się w 2024 roku. Poniżej znajdują się kanoniczne przepisy, które możesz wstawić do swojej bazy kodu — w JS przeglądarki, Node.js, Go, Pythonie i PostgreSQL.
UUIDv7 w czystym JS przeglądarki/Node — układ RFC 9562
function uuidv7() {
const ts = BigInt(Date.now());
const rand = new Uint8Array(10);
crypto.getRandomValues(rand);
const b = new Uint8Array(16);
b[0] = Number((ts >> 40n) & 0xFFn);
b[1] = Number((ts >> 32n) & 0xFFn);
b[2] = Number((ts >> 24n) & 0xFFn);
b[3] = Number((ts >> 16n) & 0xFFn);
b[4] = Number((ts >> 8n) & 0xFFn);
b[5] = Number( ts & 0xFFn);
b[6] = (rand[0] & 0x0F) | 0x70; // version = 7
b[7] = rand[1];
b[8] = (rand[2] & 0x3F) | 0x80; // variant = RFC 4122
for (let i = 9; i < 16; i++) b[i] = rand[i - 6];
const h = Array.from(b, x => x.toString(16).padStart(2,'0')).join('');
return `${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20)}`;
}
// usage:
const id = uuidv7();
console.log(id); // -> '018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55'
// generate a batch and verify chronological sort:
const batch = Array.from({ length: 5 }, uuidv7);
batch.sort(); // sorts by creation time without a separate timestamp
Node.js v26.1.0+ — wbudowany crypto.randomUUIDv7()
import { randomUUIDv7 } from 'node:crypto';
// Added in Node.js v26.1.0 (2026-05-07).
// Returns an RFC 9562 version 7 UUID. The first 48 bits encode a
// millisecond Unix timestamp; the rest is CSPRNG output.
const id = randomUUIDv7();
// -> '018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55'
// The CSPRNG output is cached for performance: Node generates enough
// entropy upfront for the next ~128 UUIDs. Pass disableEntropyCache: true
// when you need each call to draw fresh randomness, e.g. directly after
// a fork() or in tight high-security loops.
const freshId = randomUUIDv7({ disableEntropyCache: true });
// IMPORTANT: per the Node docs, "the embedded timestamp relies on a
// non-monotonic clock and is not guaranteed to be strictly increasing."
// If two UUIDs land in the same millisecond OR the system clock steps
// backwards, the IDs may not sort in creation order. Use a userland
// monotonic-v7 library (e.g. uuidv7 on npm) when strict ordering matters.
Go — google/uuid v1.6+ dostarcza UUIDv7 natywnie
package main
import (
"fmt"
"github.com/google/uuid"
)
func newID() uuid.UUID {
id, err := uuid.NewV7()
if err != nil {
panic(err)
}
return id
}
func main() {
id := newID()
fmt.Println(id.String()) // 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55
fmt.Println(id.Time()) // embedded creation timestamp
}
Python 3.13+ — uuid.uuid7() z biblioteki standardowej
import uuid
# Python 3.13 added uuid7() and uuid8() to the standard library.
uid = uuid.uuid7()
print(uid) # 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55
print(uid.version) # 7
# For older Python use the 'uuid7' or 'uuid-utils' PyPI packages, or:
# from uuid_extensions import uuid7
PostgreSQL 18+ — natywna funkcja uuidv7()
-- PG 18 ships uuidv7() natively. Use it as a primary key default:
CREATE TABLE events (
id uuid PRIMARY KEY DEFAULT uuidv7(),
body jsonb,
ts timestamptz NOT NULL DEFAULT now()
);
-- For older Postgres, install the pg_uuidv7 extension or generate client-side.
-- Migration tip: keep INDEX on (id) only — v7 already sorts chronologically,
-- so a separate (created_at) index is usually redundant.
// CZĘSTE PUŁAPKI
> UUIDv7 ujawnia czas utworzenia — nie używaj go do nieprzejrzystych tokenów
Pierwsze 48 bitów każdego v7 to znacznik czasu Unix w milisekundach. Każdy, kto widzi UUID, może odczytać, kiedy rekord został utworzony, tempo wydawania identyfikatorów oraz (przy wielu próbkach) oszacować zegar serwera. To w porządku dla wewnętrznych kluczy głównych bazy danych i identyfikatorów logów, ale dla adresów URL resetowania hasła, linków udostępniania, identyfikatorów sesji lub kodów zaproszeń użyj zamiast tego UUIDv4 lub losowego ciągu wygenerowanego przez CSPRNG.
> Cofnięcie zegara łamie monotoniczność
Jeśli zegar systemowy cofnie się (krok NTP, migracja VM, sekunda przestępna), naiwnie generowane UUID-y v7 mogą tworzyć wartości sortujące się przed wcześniej wydanymi identyfikatorami. RFC 9562 §6.2 zaleca Metodę 2 (monotoniczny losowy): śledź ostatnio wygenerowany UUID i gdy znacznik czasu nie postępuje, inkrementuj zamiast tego część losową. Przełącznik Monotoniczny tego narzędzia robi dokładnie to.
> v7 nie jest bezpośrednim zamiennikiem v4 w kontekstach wrażliwych na bezpieczeństwo
Losowo wyglądające identyfikatory (v4) są często przez pomyłkę używane jako tokeny bearer: „jeśli znasz UUID, możesz odczytać wiersz”. v7 ma tylko 74 losowe bity i przewidywalny prefiks znacznika czasu, co nadal jest odporne na kolizje, ale zapewnia znacznie mniejszą nieprzewidywalność niż 122 losowe bity v4. Jeśli coś jest traktowane jako uprawnienie, wygeneruj osobny token kryptograficzny zamiast ponownie używać klucza głównego v7.
> Porównanie ciągów działa tylko w formie z małymi literami i myślnikami
Sortowanie chronologiczne v7 opiera się na porównaniu leksykograficznym kanonicznego 36-znakowego ciągu z małymi literami — lub na porównaniu bajt po bajcie bazowej 16-bajtowej wartości. Mieszanie wielkich i małych liter, usuwanie myślników w trakcie lub przechowywanie niektórych wierszy w nawiasach {...}, a innych bez, wszystko to wytworzy porządek sortowania, który nie odpowiada już czasowi utworzenia. Wybierz jedną formę kanoniczną na kolumnę i wymuś ją ograniczeniem CHECK.
> 48-bitowy znacznik czasu przekręca się w roku 10889
2^48 milisekund to około 8925 lat po epoce Unix — pole znacznika czasu przepełnia się 2 sierpnia 10889 UTC. Jeśli Twój kod zakłada, że osadzony znacznik czasu mieści się w rozsądnym zakresie, ustaw górną granicę na 281 474 976 710 655 ms (maksimum, jakie może pomieścić 48-bitowa liczba całkowita bez znaku) zamiast wpisywać na sztywno rok z bliskiej przyszłości, który za stulecie będzie błędny.
>> najczęściej zadawane pytania
P: Czym jest UUIDv7?
O: UUIDv7 to 128-bitowy identyfikator zdefiniowany w RFC 9562 (maj 2024), który łączy 48-bitowy znacznik czasu Unix w milisekundach z 74 bitami losowości oraz standardowymi bitami wersji + wariantu. Rezultatem jest globalnie unikalny identyfikator, który również sortuje się chronologicznie według czasu utworzenia — najlepsze z obu światów. Został zaprojektowany specjalnie po to, by rozwiązać problem indeksów bazy danych powodowany przez losowe klucze główne UUIDv4, gdzie każde wstawienie trafia na inną stronę drzewa B i powoduje ogromne wzmocnienie zapisu.
P: Czym UUIDv7 różni się od UUIDv4?
O: UUIDv4 jest w pełni losowy (122 losowe bity) i nie ma struktury poza polami wersji + wariantu. Dwa v4 wygenerowane w odstępie mikrosekundy sortują się do zupełnie różnych pozycji, co jest świetne dla nieprzewidywalności, ale okropne dla indeksów drzew B. UUIDv7 umieszcza 48-bitowy znacznik czasu Unix w milisekundach na początku, więc v7 wygenerowane blisko siebie w czasie sortują się także blisko w pamięci. Kompromis: v7 ujawnia czas utworzenia i ma tylko 74 losowe bity zamiast 122 — nadal odporny na kolizje, ale nieodpowiedni jako tajny token.
P: Czy powinienem migrować z UUIDv4 na UUIDv7?
O: Dla wewnętrznych kluczy głównych bazy danych w tabelach o intensywnym zapisie — tak, niemal zawsze. Fragmentacja indeksów powodowana przez v4 może przyćmić koszt samych zapytań, zwłaszcza w PostgreSQL lub MySQL z klastrowanymi indeksami InnoDB. Dla tokenów wystawianych użytkownikom, osadzanych w adresach URL lub traktowanych jako uprawnienia („jeśli znasz UUID, możesz uzyskać dostęp do zasobu”), zachowaj v4 lub użyj osobnego losowego tokenu — v7 ujawnia czas utworzenia. Powszechnym wzorcem są klucze główne v7 do wewnętrznych złączeń plus osobny losowy slug dla publicznego adresu URL.
P: Czy UUIDv7 to to samo co ULID, KSUID lub Snowflake?
O: Koncepcyjnie podobne — wszystkie cztery to identyfikatory uporządkowane czasowo — ale układy bitów i kodowania się różnią. ULID używa Crockford base32 i innego układu milisekund. KSUID koduje 32-bitowy znacznik czasu + 128-bitowy ładunek jako 27 znaków base62. Snowflake to 64-bitowy identyfikator specyficzny dla Twittera z identyfikatorami workerów. UUIDv7 to odpowiednik standardowy IETF, zakodowany w kanonicznej formie szesnastkowej 8-4-4-4-12, więc każda biblioteka UUID, typ UUID bazy danych oraz sterownik JDBC/ODBC już go rozumie. Jeśli zaczynasz od zera w 2025+, preferuj v7 — to standard.
P: Ile UUIDv7 mogę wygenerować na milisekundę przed kolizjami?
O: W obrębie pojedynczej milisekundy tylko 74 losowe bity (12 w rand_a + 62 w rand_b) zapewniają unikalność. Zgodnie z granicą kolizji urodzinowej możesz wygenerować około 2^37 ≈ 137 miliardów v7 w tej samej ms przed 50% szansą na kolizję — praktycznie nieograniczona ilość dla każdego realistycznego systemu. Między milisekundami sam znacznik czasu rozróżnia, więc globalne ryzyko kolizji w całym okresie życia systemu jest pomijalne. Przy włączonym przełączniku Monotoniczny kolizje w obrębie milisekundy są zerowe z konstrukcji (część losowa jest inkrementowana).
P: Czy mogę wyodrębnić znacznik czasu z UUIDv7?
O: Tak — znacznik czasu to pierwsze 48 bitów, czyli pierwsze 12 znaków szesnastkowych po usunięciu myślników. Połącz pierwsze trzy grupy oddzielone myślnikami (8 + 4 = 12 hex digits), zinterpretuj jako liczbę szesnastkową i otrzymasz znacznik czasu Unix w milisekundach. Użyj dekodera powyżej, aby zrobić to interaktywnie, lub w kodzie: parseInt(uuid.replace(/-/g,'').slice(0,12), 16). Wynikiem jest milisekundowy moment wygenerowania UUID, dokładny zgodnie z zegarem systemowym w tym czasie.
P: Jak wygląda cyfra wersji w UUIDv7?
O: Trzecia grupa oddzielona myślnikami zawsze zaczyna się cyfrą 7. Na przykład: 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55. Czwarta grupa zawsze zaczyna się od 8, 9, a lub b — to cztery możliwe wartości, gdy dwa najwyższe bity to 10 (wariant RFC 4122). Jeśli cyfra wersji nie jest 7, UUID jest inną wersją (zwykle 4 dla losowego lub 1 dla opartego na czasie v1) i nie sortuje się chronologicznie.
P: Czy PostgreSQL / MySQL obsługują UUIDv7 natywnie?
O: PostgreSQL 18 (wydany we wrześniu 2025) dostarcza uuidv7() jako funkcję wbudowaną. Wcześniejsze wersje wymagają rozszerzenia pg_uuidv7 lub generowania po stronie klienta. MySQL 8.x nie ma natywnego v7; użyj pomocnika UUID_TO_BIN(uuid, 1) (który zamienia bajty znacznika czasu dla porządku sortowania) tylko dla v1 — dla v7 generuj po stronie klienta. SQL Server, Oracle i SQLite oczekują generowania v7 po stronie klienta. Większość ORM-ów (Hibernate, Entity Framework, Sequelize, Prisma, SQLAlchemy) obsługuje teraz v7 natywnie lub poprzez wtyczkę.
P: Czy opcja monotoniczna jest zgodna z RFC 9562?
O: Tak. RFC 9562 §6.2 wyraźnie opisuje trzy metody zapewnienia porządku w obrębie milisekundy: (1) wypełnienie losowe, (2) monotoniczny losowy — inkrementacja licznika, gdy znacznik czasu nie postępuje, (3) precyzja znacznika czasu sub-milisekundowa. Pole wyboru Monotoniczny w tym narzędziu implementuje metodę 2: gdy dwa UUID-y dzielą ten sam 48-bitowy znacznik czasu, część losowa drugiego jest ustawiana na previous_random + 1 zamiast być losowana od nowa. Gwarantuje to ścisły porządek przy generowaniu wsadowym, pozostając w pełni zgodnym ze specyfikacją.
P: Czy moje dane są gdzieś wysyłane?
O: Nie. Całe generowanie, dekodowanie, sortowanie, kopiowanie i pobieranie UUIDv7 odbywa się w całości w Twojej przeglądarce jako czysty JavaScript. Strona nigdy nie wykonuje żądania sieciowego, gdy klikniesz GENERUJ, DEKODUJ, KOPIUJ lub POBIERZ — możesz to zweryfikować za pomocą karty Sieć w narzędziach deweloperskich przeglądarki. Nie logujemy znaczników czasu, niestandardowych ziaren, wygenerowanych UUID-ów ani zdekodowanych wyników. Sama strona to statyczny HTML serwowany z CDN, więc żadne dane wejściowe nigdy nie docierają do naszej infrastruktury. To sprawia, że narzędzie jest bezpieczne dla produkcyjnych identyfikatorów bazy danych, wewnętrznych logów lub innych danych, których wolałbyś nie przepuszczać przez serwer zewnętrzny.
P: Czy mogę używać UUIDv7 w Javie / .NET / Rust?
O: Tak. Java ma com.fasterxml.uuid:java-uuid-generator 5.0+, a JDK 21 ma to poprzez pomocniki bibliotek. .NET 9 dostarcza Guid.CreateVersion7() w BCL. Rust używa Uuid::now_v7() z crate'a uuid za flagą funkcji v7. Większość innych ekosystemów (Elixir, Ruby, PHP, Swift, Kotlin) również ma dobrze utrzymane pakiety — wyszukaj „uuidv7” lub „uuid v7” w rejestrze pakietów danego języka. Format wire jest identyczny we wszystkich, więc v7 wygenerowany w Go może zostać sparsowany i mieć wyodrębniony znacznik czasu przez JavaScript bez żadnej transformacji.
P: Czy Node.js ma wbudowany generator UUIDv7?
O: Tak — od wersji Node.js v26.1.0 (wydanej 2026-05-07) biblioteka standardowa udostępnia crypto.randomUUIDv7([options]). Zaimportuj to jako import { randomUUIDv7 } from 'node:crypto' i wywołaj bez argumentów, aby uzyskać ciąg UUID v7 zgodny z RFC 9562. Jedyną obsługiwaną opcją jest disableEntropyCache (wartość logiczna, domyślnie false); domyślnie Node buforuje z wyprzedzeniem wystarczająco dużo danych losowych, by wygenerować kolejne ~128 UUID-ów, co jest tą samą optymalizacją, której używa crypto.randomUUID(). Ważne zastrzeżenie z oficjalnej dokumentacji: „osadzony znacznik czasu opiera się na niemonotonicznym zegarze i nie ma gwarancji, że będzie ściśle rosnący”. Innymi słowy, dwa UUID-y wygenerowane w tej samej milisekundzie lub jakiekolwiek UUID-y utworzone na przestrzeni kroku NTP / cofnięcia zegara VM mogą nie sortować się w kolejności utworzenia. Jeśli potrzebujesz ścisłej monotoniczności w obrębie milisekundy, użyj implementacji userland zgodnej z RFC 9562 §6.2 Metoda 2 (pakiet npm uuidv7 lub to narzędzie z włączonym przełącznikiem Monotoniczny).
P: Jak efektywnie przechowywać UUIDv7 w bazie danych?
O: Przechowuj go jako 16-bajtowy typ binarny zamiast 36-znakowego ciągu — oszczędzasz 20 bajtów na wiersz, zmniejszasz rozmiar indeksu o połowę i zyskujesz szybszą ścieżkę porównania. Użyj typu uuid PostgreSQL, MySQL BINARY(16), SQL Server uniqueidentifier lub SQLite BLOB. Dodaj ograniczenie CHECK, że nibble wersji równa się 7, jeśli chcesz to wymusić. Przy v7 wiersze naturalnie grupują się według czasu utworzenia, więc indeks pokrywający na (uuid_pk) zwykle wystarcza — nie potrzebujesz osobnego indeksu (created_at) dla zapytań chronologicznych.