Buat identifier
Bandingkan sequence database, UUID, ObjectId, dan ID bergaya Snowflake, termasuk caveat clock dan urutannya.
Pertanyaan
Dari mana ID unik berasal, dan apa yang kamu korbankan di tiap pilihan?
Setelah baca ini, kamu bisa memilih skema identifier untuk sebuah tabel, menyebut risiko tabrakan, urutan, dan clock, serta menjelaskan dampaknya ke indeks dan keamanan.
Prasyarat dan contoh
Kamu paham primary key dan indeks B-tree (M04), serta kenapa penulis konkuren butuh koordinasi (M05.03).
Layanan pesanan awalnya satu database dengan id BIGSERIAL. Lalu tim memecahnya jadi tiga
layanan yang masing-masing membuat pesanan, dan pesanan perlu ID sebelum disimpan (untuk log dan
retry). Sequence satu database nggak lagi bisa dipanggil dari mana saja tanpa satu titik
koordinasi.
Mekanisme
Sequence database. Penghitung yang naik terus: 1, 2, 3, ... Kecil (8 byte), terurut, murah di
indeks. Biayanya: satu titik koordinasi, dan ID mudah ditebak. Pengguna yang melihat /pesanan/1042
bisa mencoba /pesanan/1043. Sequence juga punya celah: transaksi yang rollback tetap
menghabiskan nomor, jadi jangan menjadikannya nomor faktur tanpa celah.
UUID v4. 128 bit acak, 122 bit benar-benar acak. Dibuat di mana saja tanpa koordinasi. Peluang tabrakan: dengan 1 miliar ID, sekitar 10^-19 untuk satu pasangan, jadi nggak realistis. Biayanya: 16 byte, dan acak total. Sisipan jatuh ke halaman B-tree yang tersebar, sehingga cache buffer kurang efektif dan halaman sering terbelah.
UUID v7 dan ULID. Awalan timestamp milidetik, sisanya acak. Terurut kasar menurut waktu, jadi sisipan menumpuk di ujung kanan indeks, mirip sequence. Tetap bisa dibuat tanpa koordinasi.
ObjectId (MongoDB). 12 byte: 4 byte timestamp detik, 5 byte nilai acak per proses, 3 byte counter. Terurut kasar per detik, cukup unik tanpa koordinasi.
ID bergaya Snowflake. 64 bit: sekitar 41 bit timestamp milidetik, 10 bit id mesin, 12 bit
nomor urut. Satu mesin bisa membuat 4.096 ID per milidetik, sekitar 4 juta per detik. Muat di
BIGINT, terurut kasar, dan padat. Syaratnya: setiap mesin harus punya id mesin yang unik
(butuh pengaturan atau registri), dan clock harus bisa dipercaya.
"Terurut" itu kasar. Di semua skema berbasis waktu, urutan ID hanya mendekati urutan kejadian. Dua mesin dengan clock berbeda 50 ms bisa menerbitkan ID yang urutannya terbalik dari urutan kejadian sebenarnya. Jangan memakai ID sebagai bukti "A terjadi sebelum B" (M08.04).
Perbandingan:
| Skema | Ukuran | Koordinasi | Urutan | Catatan | | --- | --- | --- | --- | --- | | Sequence | 8 B | ya | ketat per sequence | mudah ditebak, ada celah | | UUID v4 | 16 B | tidak | acak | indeks tersebar | | UUID v7 / ULID | 16 B | tidak | kasar | bocorkan waktu pembuatan | | ObjectId | 12 B | tidak | kasar per detik | bocorkan waktu pembuatan | | Snowflake | 8 B | id mesin | kasar | tergantung clock |
Keamanan. ID berurutan membocorkan volume dan memudahkan enumerasi. ID acak mempersulit tebakan tapi bukan pengganti otorisasi. Setiap akses tetap harus memeriksa izin.
Saat rancangan ini gagal
- UUID v4 sebagai primary key tabel besar. Pada tabel ratusan juta baris dengan sisipan tinggi, indeks tersebar menambah I/O dan ukuran. Ukur sebelum memutuskan, tapi waspadai.
- Id mesin Snowflake bentrok. Dua instance dengan id mesin sama menerbitkan ID kembar pada milidetik yang sama. Penetapan id lewat konfigurasi manual rawan salah saat autoscaling.
- Memakai ID sebagai cap waktu atau urutan bisnis. Urutan antar mesin nggak dijamin.
- Mengandalkan ID sebagai rahasia. Tautan "tersembunyi" dengan UUID tetap bocor lewat log dan referrer.
- Nomor faktur dari sequence. Celah akibat rollback melanggar aturan "tanpa celah" yang diminta akuntansi di beberapa negara. Pakai tabel penomoran dengan kunci, bukan sequence.
Latihan
Platform tiket membuat pesanan di tiga layanan, tiap layanan punya 2 sampai 20 instance dengan autoscaling. Target 5.000 pesanan/detik. Tabel pesanan memakai indeks B-tree pada primary key. Pengguna melihat ID di URL. Tim menimbang UUID v4, Snowflake, dan sequence.
Pilih satu dan jelaskan.
Lihat pembahasan
Pilih UUID v7 (atau ULID) sebagai primary key, dan tetap lakukan otorisasi tiap akses.
Alasannya:
- Tanpa koordinasi. Tiga layanan dengan instance yang naik turun bisa membuat ID sendiri. Sequence menjadikan satu database titik panggil wajib. Snowflake butuh id mesin unik per instance, rumit dengan autoscaling.
- Indeks. 5.000 sisipan/detik pada UUID v4 tersebar ke seluruh B-tree. v7 menumpuk di ujung indeks karena awalan waktu, jadi perilaku sisipannya mirip sequence.
- Tebakan di URL. Bagian acak 74 bit mempersulit enumerasi. Tapi otorisasi per pesanan tetap wajib.
Harga yang dibayar: 16 byte, bukan 8, dan urutan hanya kasar. Jangan memakai ID untuk menentukan
mana yang lebih dulu. Kalau butuh urutan bisnis, simpan kolom dibuat_pada dan, bila perlu, nomor
urut per pelanggan.
Snowflake masuk akal kalau ukuran 8 byte sangat penting dan kamu sudah punya layanan penetapan id mesin dan pemantauan clock.
Terkait
- M05.03 Koordinasikan perubahan konkuren menjelaskan koordinasi yang dihindari ID terdistribusi.
- M04 membahas indeks B-tree dan dampak urutan sisipan.
- M07 menyinggung ID sebagai partition key dan risiko hot spot pada ID berurutan.
- M08.04 membahas kenapa timestamp saja tidak membuktikan sebab-akibat.
Catatan
- Asumsi: ID dibuat di aplikasi atau layanan, disimpan di database relasional.
- Angka tabrakan UUID v4 memakai pendekatan birthday bound, dengan asumsi generator acak kriptografis yang benar.
- Yang nggak dibahas: ID yang ramah manusia (kode pendek), enkripsi ID, dan format UUID v8.
- Terakhir ditinjau: 26 Oktober 2026.