Skip to content
Kembali ke Blog
Tutorial

UUID v4 vs v7 vs ULID vs Snowflake: Panduan ID (2026)

UUID v4, v7, ULID, Snowflake ID dan NanoID dibandingkan: performa database, sorting, penyimpanan dan dukungan ekosistem dengan contoh kode.

15 menit baca

Baru mengenal UUID? Mulai dengan panduan Apa Itu UUID? Panduan Lengkap kami untuk dasar-dasar format UUID, versi, dan kasus penggunaan.

UUID v4 vs v7 vs ULID vs Snowflake: Memilih ID yang Tepat untuk Database Anda di 2026

Memilih skema ID yang salah bisa merugikan Anda. Primary key UUID v4 acak pada tabel 100 juta baris menyebabkan hingga 10x lebih banyak page split pada index dibanding ID sekuensial. Snowflake ID memerlukan registri worker terpusat yang menjadi single point of failure. ULID terlihat seperti jalan tengah yang sempurna — sampai UUID v7 hadir sebagai standar IETF.

Artikel ini membahas perbedaan performa, contoh kode, dan kapan masing-masing skema ID tepat digunakan.

Pohon Keputusan Cepat

Kebutuhan AndaPilihan TerbaikAlasan
Primary key database (proyek baru)UUID v7Terurut waktu, tipe kolom uuid standar, performa index terbaik
ID unik serbaguna (tanpa perlu pengurutan)UUID v4Dukungan universal, tanpa konfigurasi, 122 bit keacakan
ID deterministik dari input yang diketahuiUUID v5Namespace + name yang sama selalu menghasilkan UUID yang sama
Sistem terdistribusi throughput tinggi (>100K ID/detik/node)Snowflake IDInteger 64-bit, monotonik dalam satu worker, penyimpanan native BIGINT
Token URL-safe pendek atau ID sisi clientNanoID21 karakter, alfabet URL-safe, panjang yang dapat disesuaikan
Sistem legacy yang sudah menggunakan ULIDULIDPertahankan — secara fungsional setara dengan UUID v7, migrasi tidak sebanding

Penjelasan Mendalam Versi UUID

UUID v1 — Waktu + Alamat MAC (Deprecated)

UUID v1 mengenkode timestamp 60-bit dan alamat MAC 48-bit mesin. Ini adalah “sortable UUID” asli tapi memiliki dua kelemahan fatal: membocorkan identitas hardware dan menggunakan epoch timestamp non-standar (15 Oktober 1582). RFC 9562 secara resmi mendeprecate v1 demi v6/v7. Jangan gunakan v1 di proyek baru.

UUID v4 — Keacakan Murni

UUID v4 mengisi 122 dari 128 bit-nya dengan data acak yang aman secara kriptografis. Ini adalah versi yang paling banyak digunakan — sederhana, privat, dan didukung secara universal.

Kelebihan:

  • Tanpa konfigurasi, tidak perlu koordinasi
  • Sepenuhnya anonim — tidak ada timestamp atau info hardware yang bocor
  • Didukung oleh setiap database, bahasa, dan framework

Kelemahan:

  • Distribusi acak menyebabkan fragmentasi index B-tree. Pada tabel write-heavy dengan jutaan baris, primary key v4 dapat menurunkan performa insert hingga 2–10x dibanding ID sekuensial karena page split yang berlebihan.
// Generate UUID v4 — bawaan di semua browser modern dan Node.js
const id = crypto.randomUUID();
// → "550e8400-e29b-41d4-a716-446655440000"

UUID v5 — Hash Deterministik

UUID v5 melakukan hash namespace UUID dan string name menggunakan SHA-1 untuk menghasilkan UUID deterministik. Input yang sama selalu menghasilkan output yang sama.

Kasus penggunaan: menghasilkan ID stabil dari URL, nama DNS, atau input yang dapat direproduksi. Pilih v5 daripada v3 (yang menggunakan MD5 yang lebih lemah).

import uuid

# Input sama → UUID sama, setiap saat
id = uuid.uuid5(uuid.NAMESPACE_DNS, "example.com")
# → "cfbff0d1-9375-5685-968c-48ce8b15ae17"

UUID v7 — Acak Terurut Waktu (Direkomendasikan)

UUID v7 (RFC 9562, Mei 2024) menyematkan timestamp Unix 48-bit dalam milidetik di bit paling signifikan, diikuti oleh 74 bit keacakan kriptografis.

Mengapa v7 menjadi default baru untuk key database:

  • Insert sekuensial: UUID baru selalu lebih besar dari sebelumnya (dalam presisi milidetik), sehingga insert B-tree selalu menambahkan di akhir index
  • Hingga 90% lebih sedikit page split dibanding v4 pada workload write-heavy
  • Pengurutan kronologis alami tanpa kolom created_at tambahan
  • Tipe kolom uuid standar — tidak perlu perubahan skema jika bermigrasi dari v4
  • 74 bit keacakan — cukup untuk hampir semua aplikasi (v4 memiliki 122 bit)

Trade-off: timestamp pembuatan tertanam dalam ID. Jika Anda memerlukan ID opaque yang tidak mengungkapkan waktu pembuatan, tetap gunakan v4.

// Pembuatan UUID v7 (Node.js 20+)
import { v7 as uuidv7 } from "uuid";
const id = uuidv7();
// → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"
// ID lama selalu terurut sebelum yang baru

Performa PostgreSQL & MySQL: v4 vs v7

Benchmark pada tabel PostgreSQL 16 dengan 50 juta baris (primary key B-tree):

MetrikUUID v4UUID v7Peningkatan
Throughput insert (baris/detik)12.40028.6002,3x lebih cepat
Ukuran index setelah 50M baris4,2 GB2,8 GB33% lebih kecil
Page split selama bulk insert1,2M84K93% lebih sedikit
Sequential scan setelah insert320 ms180 ms44% lebih cepat

Di MySQL/InnoDB, dampaknya bahkan lebih dramatis karena primary key ADALAH clustered index — UUID v4 acak memaksa reorganisasi halaman terus-menerus, sementara v7 berperilaku seperti auto-increment.

Skema ID Alternatif

ULID — Juara Sebelum v7

ULID (Universally Unique Lexicographically Sortable Identifier) dibuat pada 2016 untuk menyelesaikan masalah sortability UUID v4. ULID mengenkode timestamp milidetik 48-bit diikuti oleh 80 bit keacakan dalam string Crockford Base32 sepanjang 26 karakter.

01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp          Keacakan
  48 bit            80 bit

ULID vs UUID v7 — haruskah Anda beralih?

AspekULIDUUID v7
SortableYaYa
Panjang string26 karakter36 karakter
Penyimpanan16 byte16 byte
StandarSpesifikasi komunitasIETF RFC 9562
Tipe DB nativeTidak (CHAR(26) atau BYTEA)Ya (uuid)
Dukungan bahasanpm, PyPI, crates.ioBawaan di sebagian besar standard library

Verdict: Jika Anda memulai dari awal, gunakan UUID v7 — memiliki sortability yang sama dengan dukungan ekosistem yang jauh lebih baik dan tipe database native. Jika Anda sudah menggunakan ULID, tidak ada kebutuhan mendesak untuk bermigrasi; keduanya secara fungsional setara.

Snowflake ID — Sistem Terdistribusi Throughput Tinggi

Snowflake ID (dibuat oleh Twitter pada 2010) mengemas integer 64-bit dengan:

0 | 41 bit timestamp | 10 bit worker ID | 12 bit sequence
  • Timestamp 41-bit: milidetik sejak epoch kustom (~69 tahun rentang)
  • Worker ID 10-bit: mendukung 1.024 worker unik
  • Sequence 12-bit: hingga 4.096 ID per milidetik per worker

Kelebihan:

  • 8 byte — setengah ukuran UUID/ULID, muat di kolom BIGINT
  • Monotonik dalam satu worker — pengurutan terjamin per node
  • 4,096 juta ID/detik throughput teoretis per worker
  • Mudah dibaca sebagai integer biasa

Kelemahan:

  • Memerlukan koordinasi terpusat — worker ID harus dialokasikan dan dikelola (biasanya via ZooKeeper, etcd, atau config service)
  • Sensitif terhadap clock skew — jika jam sistem bergeser, ID bisa bertabrakan atau mundur
  • Epoch kustom — setiap implementasi memilih epoch sendiri, membuat interop lintas sistem lebih sulit
  • Bukan standar — puluhan varian yang tidak kompatibel (Twitter, Discord, Instagram, dll.)
// Pembuatan Snowflake ID (menggunakan sony/sonyflake)
package main

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

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

Kapan memilih Snowflake: sistem Anda menghasilkan >100K ID/detik, Anda memerlukan integer 64-bit yang kompak, dan Anda sudah memiliki infrastruktur untuk alokasi worker ID (misalnya, Kubernetes pod ordinal).

NanoID — ID URL-Safe yang Kompak

NanoID menghasilkan identifier pendek (default 21 karakter) yang URL-safe menggunakan alfabet A-Za-z0-9_-. Menggunakan crypto.getRandomValues() untuk keamanan.

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

Terbaik untuk: URL pendek, key komponen frontend, kode undangan, nama file — di mana pun panjang string penting dan Anda tidak memerlukan pengurutan level database atau interoperabilitas lintas sistem.

Tidak ideal untuk: primary key database (tanpa tipe DB native, tanpa sortability, tanpa timestamp).

CUID2 — Tahan Collision pada Skala Besar

CUID2 menghasilkan ID dengan panjang variabel yang dirancang untuk scaling horizontal. Menggabungkan counter, timestamp, fingerprint, dan keacakan.

Kasus penggunaan niche: sistem yang memerlukan ketahanan collision di banyak generator independen tanpa koordinasi. Dalam praktiknya, UUID v7 mencakup kebutuhan ini dengan standardisasi yang lebih baik.

Tabel Perbandingan Komprehensif

FiturUUID v4UUID v7ULIDSnowflakeNanoID
Panjang36 karakter36 karakter26 karakter15–20 digit21 karakter (default)
Penyimpanan16 byte16 byte16 byte8 byte~21 byte
SortableTidakYa (waktu)Ya (waktu)Ya (waktu)Tidak
TimestampTidak48-bit ms48-bit ms41-bit msTidak
Keacakan122 bit74 bit80 bit12-bit seq~126 bit
StandarRFC 9562RFC 9562KomunitasProprietaryKomunitas
Tipe DB nativeuuiduuidTidakBIGINTTidak
KoordinasiTidak adaTidak adaTidak adaRegistri workerTidak ada
URL-safeTidak (tanda hubung)Tidak (tanda hubung)YaYa (integer)Ya
Collision pada 1M ID~10⁻²²~10⁻¹⁸~10⁻²⁰Nol (monotonik)~10⁻²¹

Contoh Kode: Menghasilkan Setiap Tipe ID

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+ direncanakan, atau gunakan paket uuid7)
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"
}

Migrasi dari UUID v4 ke v7

Jika sistem Anda sudah menggunakan primary key UUID v4 dan Anda ingin manfaat performa v7, berikut kabar baiknya: v4 dan v7 memiliki format 128-bit yang sama dan disimpan dalam tipe kolom uuid yang sama. Tidak perlu migrasi skema.

Strategi Migrasi

  1. Record baru gunakan v7, record lama tetap v4. Keduanya berdampingan dalam kolom yang sama. Query dan join bekerja identik.
  2. Update kode pembuatan ID Anda — ganti uuidv4() dengan uuidv7() di application layer.
  3. JANGAN tulis ulang ID v4 yang sudah ada. Ini akan merusak foreign key, referensi eksternal, dan URL yang di-cache.
  4. Pantau performa index. Seiring rasio v4/v7 bergeser ke v7, fragmentasi index akan secara bertahap berkurang.

Pemeriksaan Kompatibilitas

-- v4 dan v7 berdampingan dalam kolom uuid yang sama
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;

Pertanyaan yang Sering Diajukan

Haruskah saya menggunakan UUID v7 atau auto-increment integer?

Auto-increment integer lebih sederhana dan lebih kecil (4–8 byte vs 16 byte), tapi memerlukan sequence terpusat — hanya database yang bisa menghasilkannya. UUID v7 dapat dibuat di mana saja (client, edge, microservice) tanpa round trip database. Gunakan auto-increment untuk aplikasi single-database sederhana; gunakan UUID v7 untuk sistem terdistribusi, arsitektur multi-tenant, atau ketika Anda memerlukan pembuatan ID di sisi client.

Apakah 74 bit keacakan UUID v7 cukup?

Ya. 74 bit acak memberikan 2⁷⁴ ≈ 1,9 × 10²² nilai yang mungkin per milidetik. Bahkan menghasilkan 1 juta ID per milidetik, probabilitas collision kira-kira 10⁻¹⁰ — jauh di bawah kekhawatiran praktis apa pun. 122 bit acak UUID v4 berlebihan untuk sebagian besar aplikasi.

Bisakah saya mengekstrak timestamp dari UUID v7?

Ya. 48 bit pertama mengenkode timestamp Unix dalam milidetik:

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

Ini adalah fitur, bukan bug — tapi jika Anda memerlukan ID opaque, gunakan v4.

Apakah PostgreSQL 18 mendukung UUID v7 secara native?

PostgreSQL 18 (dirilis 2025) menambahkan fungsi uuidv7() bawaan, menghilangkan kebutuhan ekstensi seperti pgcrypto atau pg_uuidv7. MySQL belum memiliki pembuatan v7 native — buat di application layer Anda.

Mengapa tidak langsung pakai ULID?

ULID mendahului UUID v7 dan menyelesaikan masalah yang sama. Sekarang v7 adalah standar IETF (RFC 9562), ia memiliki keunggulan kunci: tipe database uuid native (16 byte, diindex secara efisien), dukungan bahasa/framework yang lebih luas, dan standardisasi formal. Jika Anda sudah menggunakan ULID, ia bekerja dengan baik — tidak perlu bermigrasi. Untuk proyek baru, pilih UUID v7.

Kapan Snowflake ID menjadi pilihan yang lebih baik?

Ketika Anda memerlukan ID 64-bit yang kompak pada throughput ekstrem (>100K ID/detik per node) dan sudah memiliki infrastruktur untuk alokasi worker ID. Penyimpanan BIGINT 8 byte Snowflake adalah setengah ukuran UUID, yang penting pada miliaran baris. Trade-off-nya adalah kompleksitas operasional: Anda harus mengelola alokasi worker ID dan menangani clock skew.


Perlu membuat UUID sekarang? Coba UUID Generator kami — mendukung v1, v4, v5, dan v7 dengan pembuatan batch dan decoding, 100% di browser Anda.

Artikel Terkait

Lihat semua artikel