> uuidv7 generator <
// Упорядоченные по времени, сортируемые UUID (RFC 9562, 2024) — 48-битная метка времени Unix в мс + 74 случайных бита, генерируются локально
// ДЕКОДИРОВАТЬ / ПРОВЕРИТЬ UUIDV7
Вставьте любой UUID ниже, чтобы извлечь встроенную метку времени, версию и вариант. Работает с v7 и сообщает, если на входе другая версия UUID.
UUIDv7, соответствующий спецификации
Реализует упорядоченный по времени формат UUID из RFC 9562 (май 2024): 48-битная метка времени Unix в миллисекундах, 4-битная версия 7, 12-битный rand_a, 2-битный вариант, 62-битный rand_b. Проверено по тестовым векторам спецификации.
Хронологический порядок сортировки
Сортируйте численно или лексикографически — и вы получите порядок вставки, идеально для первичных ключей B-дерева, индексов временных рядов и корреляции логов. Больше никаких случайных разбиений страниц v4 или фрагментированных индексов.
Монотонность в пределах одной миллисекунды
Когда несколько UUID попадают в одну миллисекунду, случайная часть строго инкрементируется, так что вывод остаётся отсортированным в пределах этой мс. Отключите для обычного Метода 1 из RFC 9562 (случайное заполнение), если предпочитаете.
Проверьте любой UUIDv7
Вставьте UUID v7 — и декодер извлечёт встроенную метку времени (мс + ISO 8601), биты версии, биты варианта и поля rand_a / rand_b. Полезно для отладки, археологии логов и аудиторских журналов.
// О UUIDV7
Как работает UUIDv7:
UUIDv7 — это 128-битный идентификатор со структурой unix_ts_ms (48) | ver (4) | rand_a (12) | var (2) | rand_b (62). Первые 48 бит — текущая метка времени Unix в миллисекундах, big-endian, что делает UUID монотонно возрастающим во времени. Следующие 4 бита кодируют версию (двоичное 0111 = десятичное 7), поэтому третья группа, разделённая дефисами, всегда начинается с цифры 7. rand_a — это 12 случайных бит, используемых для субмиллисекундного разрешения или как дополнительная энтропия. 2-битное поле варианта фиксировано как 10 (поэтому первый символ четвёртой группы всегда 8, 9, a или b). Оставшиеся 62 бита (rand_b) берутся из crypto.getRandomValues() при каждой генерации. Общая энтропия на один UUID — 74 случайных бита, что устойчиво к коллизиям при любой реалистичной скорости генерации.
Пример:
018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55 (ts=2024-05-08T15:00:00.000Z)
Стандарты и ссылки:
- >RFC 9562 — Universally Unique IDentifiers (UUIDs), май 2024 (заменяет RFC 4122, определяет v6/v7/v8)
- >RFC 4122 — исходная спецификация UUID 2005 года (по-прежнему авторитетна для v1-v5)
- >Web Crypto API (W3C) —
crypto.getRandomValues()CSPRNG, используемый для 74 случайных бит - >Поведение
gen_random_uuid()в PostgreSQL (по умолчанию v4, v7 в расширениях pgcrypto / форках) - >draft-peabody-dispatch-new-uuid-format — исходное предложение v6/v7/v8, ставшее RFC 9562
Зачем использовать UUIDv7:
- >Первичные ключи базы данных с локальностью вставки — страницы остаются упакованными, индексы не фрагментируются
- >Заменяет пару последовательность + UUID: один столбец, сортируемый И глобально уникальный
- >Заменяет первичные ключи v4 в таблицах с интенсивной записью, решая проблему разбиения страниц при случайной вставке
- >Идентификаторы корреляции логов, сортируемые по времени создания без отдельного столбца метки времени
- >Распределённые системы, где нескольким записывающим узлам нужны упорядоченные идентификаторы без координатора
- >Event sourcing / журналы только для добавления, где хронологический порядок является естественным индексом
- >Ключи S3 / объектного хранилища, где сортировка по префиксу совпадает с порядком вставки
- >Заменяет Snowflake / KSUID / ULID там, где предпочтителен стандартный формат
Связанные инструменты:
- >Генератор UUID — генерирует v4 (случайный) и v1 (по времени), когда не нужен порядок сортировки v7
- >Генератор GUID — тот же идентификатор под наименованием Microsoft
- >Конвертер меток времени — преобразует встроенные мс Unix обратно в локальное время / ISO 8601
- >Конвертер Unix-времени — проверяет 48-битную часть метки времени в любом часовом поясе
- >Генератор паролей — криптографически случайные токены, когда сортируемость не требуется
// ПРИМЕРЫ ВЫВОДА
Один UUIDv7, сгенерированный сейчас
count=1, format=standard, timestamp=current
output:
018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55
Массовая партия с монотонностью в одной миллисекунде
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
Пользовательская историческая метка времени — заполнение при миграции
count=1, timestamp=custom, value=1577836800000 (2020-01-01)
output:
016f5e66-e800-7c9a-b403-2f1d4a7c91ee
Компактный формат для URL / имён файлов
count=1, format=no-hyphens
output:
018f5c2e90c07a4fb6ee8dfe3c2b0a55
Декодированный UUIDv7 — проверка встроенных полей
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
// РЕАЛИЗУЙТЕ САМИ
С момента появления RFC 9562 в 2024 году у большинства языков есть либо помощник в стандартной библиотеке, либо однофайловая реализация UUIDv7. Ниже приведены канонические рецепты, которые можно вставить в вашу кодовую базу — на JS в браузере, Node.js, Go, Python и PostgreSQL.
UUIDv7 на чистом JS в браузере/Node — структура 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+ — встроенный 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+ поставляет UUIDv7 нативно
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() из стандартной библиотеки
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+ — нативная функция 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.
// РАСПРОСТРАНЁННЫЕ ОШИБКИ
> UUIDv7 раскрывает время создания — не используйте его для непрозрачных токенов
Первые 48 бит любого v7 — это метка времени Unix в миллисекундах. Любой, кто видит UUID, может декодировать, когда была создана запись, скорость выдачи идентификаторов и (по нескольким образцам) приблизительно определить часы сервера. Это нормально для внутренних первичных ключей базы данных и идентификаторов логов, но для URL сброса пароля, ссылок для обмена, идентификаторов сессий или кодов приглашений используйте UUIDv4 или случайную строку, сгенерированную CSPRNG.
> Регрессия часов нарушает монотонность
Если системные часы переходят назад (шаг NTP, миграция ВМ, високосная секунда), наивно сгенерированные UUID v7 могут давать значения, сортирующиеся раньше ранее выданных идентификаторов. RFC 9562 §6.2 рекомендует Метод 2 (монотонный случайный): отслеживать последний сгенерированный UUID и, когда метка времени не продвигается, инкрементировать случайную часть. Переключатель Монотонный в этом инструменте делает именно это.
> v7 не является прямой заменой v4 в контекстах, чувствительных к безопасности
Случайно выглядящие идентификаторы (v4) часто по ошибке используются как токены-носители: «если вы знаете UUID, вы можете прочитать строку». У v7 всего 74 случайных бита и предсказуемый префикс метки времени, что по-прежнему устойчиво к коллизиям, но обеспечивает гораздо меньшую непредсказуемость, чем 122 случайных бита v4. Если что-то трактуется как полномочие, сгенерируйте отдельный криптографический токен вместо повторного использования первичного ключа v7.
> Сравнение строк работает только в нижнем регистре с дефисами
Хронологическая сортировка v7 опирается на лексикографическое сравнение канонической 36-символьной строки в нижнем регистре — или на побайтовое сравнение базового 16-байтового значения. Смешивание верхнего и нижнего регистра, удаление дефисов на полпути или хранение одних строк в скобках {...}, а других без них — всё это даёт порядок сортировки, который больше не совпадает со временем создания. Выберите одну каноническую форму для столбца и обеспечьте её ограничением CHECK.
> 48-битная метка времени переполнится в 10889 году
2^48 миллисекунд — это примерно 8925 лет после эпохи Unix; поле метки времени переполнится 02.08.10889 UTC. Если ваш код утверждает, что встроенная метка времени находится в разумном диапазоне, установите верхнюю границу 281 474 976 710 655 мс (максимум, который может вместить 48-битное беззнаковое целое), а не зашивайте близкий будущий год, который через столетие окажется неверным.
>> часто задаваемые вопросы
В: Что такое UUIDv7?
О: UUIDv7 — это 128-битный идентификатор, определённый в RFC 9562 (май 2024), который объединяет 48-битную метку времени Unix в миллисекундах с 74 битами случайности и стандартными битами версии + варианта. Результат — глобально уникальный идентификатор, который также сортируется хронологически по времени создания — лучшее из обоих миров. Он был разработан специально для устранения проблемы с индексами базы данных, вызванной случайными первичными ключами UUIDv4, при которых каждая вставка попадает на другую страницу B-дерева и вызывает значительное усиление записи.
В: Чем UUIDv7 отличается от UUIDv4?
О: UUIDv4 полностью случаен (122 случайных бита) и не имеет структуры, кроме полей версии + варианта. Два v4, сгенерированные с разницей в микросекунду, сортируются в совершенно разные позиции, что отлично для непредсказуемости, но ужасно для индексов B-дерева. UUIDv7 помещает 48-битную метку времени Unix в миллисекундах в начало, поэтому v7, сгенерированные близко по времени, сортируются близко и в хранилище. Компромисс: v7 раскрывает время создания и имеет всего 74 случайных бита вместо 122 — по-прежнему устойчив к коллизиям, но непригоден как секретный токен.
В: Стоит ли мигрировать с UUIDv4 на UUIDv7?
О: Для внутренних первичных ключей базы данных в таблицах с интенсивной записью — да, почти всегда. Фрагментация индексов, вызываемая v4, может превышать стоимость самих запросов, особенно в PostgreSQL или MySQL с кластеризованными индексами InnoDB. Для токенов, которые доступны пользователям, встраиваются в URL или трактуются как полномочия («если вы знаете UUID, вы можете получить доступ к ресурсу»), сохраните v4 или используйте отдельный случайный токен — v7 раскрывает время создания. Распространённый шаблон — первичные ключи v7 для внутренних соединений плюс отдельный случайный slug для публичного URL.
В: UUIDv7 — это то же самое, что ULID, KSUID или Snowflake?
О: Концептуально похожи — все четыре являются упорядоченными по времени идентификаторами — но компоновки битов и кодировки различаются. ULID использует Crockford base32 и другую компоновку миллисекунд. KSUID кодирует 32-битную метку времени + 128-битную нагрузку как 27 символов base62. Snowflake — это 64-битный специфичный для Twitter идентификатор с идентификаторами воркеров. UUIDv7 — это стандартный эквивалент IETF, закодированный в канонической шестнадцатеричной форме 8-4-4-4-12, поэтому любая библиотека UUID, тип UUID базы данных и драйвер JDBC/ODBC уже его понимают. Если вы начинаете с нуля в 2025+, предпочтите v7 — это стандарт.
В: Сколько UUIDv7 я могу сгенерировать за миллисекунду до коллизий?
О: В пределах одной миллисекунды уникальность обеспечивают только 74 случайных бита (12 в rand_a + 62 в rand_b). По границе коллизии «дней рождения» вы можете сгенерировать примерно 2^37 ≈ 137 миллиардов v7 в одной мс до 50% вероятности коллизии — практически неограниченно для любой реалистичной системы. Между миллисекундами различает сама метка времени, поэтому глобальный риск коллизии за весь срок службы системы пренебрежимо мал. При включённом переключателе Монотонный внутримиллисекундные коллизии равны нулю по построению (случайная часть инкрементируется).
В: Можно ли извлечь метку времени из UUIDv7?
О: Да — метка времени это первые 48 бит, то есть первые 12 шестнадцатеричных символов с удалёнными дефисами. Соедините первые три группы, разделённые дефисами (8 + 4 = 12 hex digits), интерпретируйте как шестнадцатеричное целое — и вы получите метку времени Unix в миллисекундах. Используйте декодер выше, чтобы сделать это интерактивно, или в коде: parseInt(uuid.replace(/-/g,'').slice(0,12), 16). Результат — миллисекундный момент генерации UUID, точный по системным часам в то время.
В: Как выглядит цифра версии в UUIDv7?
О: Третья группа, разделённая дефисами, всегда начинается с цифры 7. Например: 018f5c2e-90c0-7a4f-b6ee-8dfe3c2b0a55. Четвёртая группа всегда начинается с 8, 9, a или b — это четыре возможных значения, когда два старших бита равны 10 (вариант RFC 4122). Если цифра версии не 7, UUID относится к другой версии (обычно 4 для случайного или 1 для основанного на времени v1) и не сортируется хронологически.
В: Поддерживают ли PostgreSQL / MySQL UUIDv7 нативно?
О: PostgreSQL 18 (выпущен в сентябре 2025) поставляет uuidv7() как встроенную функцию. Более ранним версиям нужно расширение pg_uuidv7 или генерация на стороне клиента. У MySQL 8.x нет нативного v7; используйте помощник UUID_TO_BIN(uuid, 1) (который меняет байты метки времени местами для порядка сортировки) только для v1 — для v7 генерируйте на стороне клиента. SQL Server, Oracle и SQLite ожидают генерацию v7 на стороне клиента. Большинство ORM (Hibernate, Entity Framework, Sequelize, Prisma, SQLAlchemy) теперь поддерживают v7 либо нативно, либо через плагин.
В: Соответствует ли монотонный режим RFC 9562?
О: Да. RFC 9562 §6.2 явно описывает три метода обеспечения внутримиллисекундного порядка: (1) случайное заполнение, (2) монотонный случайный — инкрементировать счётчик, когда метка времени не продвигается, (3) субмиллисекундная точность метки времени. Флажок Монотонный в этом инструменте реализует метод 2: когда два UUID имеют одну и ту же 48-битную метку времени, случайная часть второго устанавливается в previous_random + 1 вместо нового розыгрыша. Это гарантирует строгий порядок при пакетной генерации, оставаясь полностью соответствующим спецификации.
В: Отправляются ли мои данные куда-либо?
О: Нет. Вся генерация, декодирование, сортировка, копирование и скачивание UUIDv7 происходят полностью в вашем браузере как чистый JavaScript. Страница никогда не делает сетевой запрос, когда вы нажимаете СГЕНЕРИРОВАТЬ, ДЕКОДИРОВАТЬ, КОПИРОВАТЬ или СКАЧАТЬ — вы можете проверить это во вкладке «Сеть» инструментов разработчика браузера. Мы не логируем метки времени, пользовательские сиды, сгенерированные UUID или декодированный вывод. Сама страница — это статический HTML, обслуживаемый из CDN, поэтому никакой ввод не достигает нашей инфраструктуры. Это делает инструмент безопасным для использования с производственными идентификаторами базы данных, внутренними логами или любыми другими данными, которые вы предпочли бы не пропускать через сторонний сервер.
В: Можно ли использовать UUIDv7 в Java / .NET / Rust?
О: Да. В Java есть com.fasterxml.uuid:java-uuid-generator 5.0+, а JDK 21 имеет это через помощники библиотек. .NET 9 поставляет Guid.CreateVersion7() в BCL. Rust использует Uuid::now_v7() из крейта uuid за флагом функции v7. У большинства других экосистем (Elixir, Ruby, PHP, Swift, Kotlin) тоже есть хорошо поддерживаемые пакеты — ищите «uuidv7» или «uuid v7» в реестре пакетов языка. Формат передачи идентичен у всех, поэтому v7, сгенерированный в Go, может быть разобран, а его метка времени извлечена в JavaScript без какого-либо преобразования.
В: Есть ли в Node.js встроенный генератор UUIDv7?
О: Да — начиная с Node.js v26.1.0 (выпущен 07.05.2026), стандартная библиотека предоставляет crypto.randomUUIDv7([options]). Импортируйте его как import { randomUUIDv7 } from 'node:crypto' и вызовите без аргументов, чтобы получить строку UUID v7 по RFC 9562. Единственный поддерживаемый параметр — disableEntropyCache (булево, по умолчанию false); по умолчанию Node заранее кеширует достаточно случайных данных для генерации следующих ~128 UUID, что является той же оптимизацией, которую использует crypto.randomUUID(). Важная оговорка из официальной документации: «встроенная метка времени опирается на немонотонные часы и не гарантированно строго возрастает». Иными словами, два UUID, сгенерированные в одной миллисекунде, или любые UUID, созданные в момент шага NTP / сдвига часов ВМ назад, могут не сортироваться в порядке создания. Если вам нужна строгая монотонность в пределах миллисекунды, используйте userland-реализацию, следующую RFC 9562 §6.2 Метод 2 (пакет npm uuidv7 или этот инструмент с включённым переключателем Монотонный).
В: Как эффективно хранить UUIDv7 в базе данных?
О: Храните его как 16-байтовый двоичный тип, а не 36-символьную строку — вы экономите 20 байт на строку, вдвое уменьшаете размер индекса и получаете более быстрый путь сравнения. Используйте тип uuid PostgreSQL, MySQL BINARY(16), SQL Server uniqueidentifier или SQLite BLOB. Добавьте ограничение CHECK, что ниббл версии равен 7, если хотите принудительной проверки. С v7 строки естественным образом кластеризуются по времени создания, поэтому покрывающего индекса по (uuid_pk) обычно достаточно — вам не нужен отдельный индекс (created_at) для хронологических запросов.