Key Overloading di DynamoDB
Datang dari SQL, sebuah kolom berarti satu hal selamanya: orders.created_at
selalu sebuah tanggal, users.email selalu sebuah email. Key overloading
membuang itu. Anda memberi partition dan sort key nama generik — pk, sk — dan
membiarkan setiap tipe item menuangkan makna berbeda ke dalamnya. Satu tabel,
banyak entitas, satu bentuk.
Apa itu key overloading di DynamoDB?
Key overloading adalah menyimpan banyak tipe entitas dalam satu tabel di bawah nama key generik seperti pk/sk, dengan mengenkode tipenya pada nilai key (USER#u_3001, INVOICE#2026-0014). Nama atribut tetap netral sehingga pengguna, invoice, dan event berbagi satu partition; nilainya yang membawa tipe, dan prefix sort-key memungkinkan satu Query mengiris setiap entitas lewat begins_with.
- Nama key generik, nilai bertipe. Beri nama key Anda
pk/skdan taruh tipe entitas di nilainya:pk = "TENANT#acme",sk = "USER#u_3001". Namanya bodoh; nilainya membawa tipenya. - Itulah yang membuat single-table design bekerja. Tanpa overloading, sebuah
tabel bersama hanyalah laci sampah. Dengannya, setiap entitas duduk di sebuah
partition yang bisa Anda
Query. begins_withadalah hasilnya. Sebuah prefix tipe pada sort key membiarkan satuQuerymenarik seluruh entitas, atau satu potongnya, tanpaScandan tanpa filter.- Biayanya: keterbacaan. Sebuah dump
pk/skmentah tidak memberi tahu Anda apa pun. Anda butuh viewer yang men-decode prefix-nya, atau Anda akan menyipitkan mata pada string.
Mengapa nama generik mengalahkan nama asli
DynamoDB punya persis dua atribut key per tabel, dan sebuah Query hanya bisa
menargetkan satu partition key. Jadi jika Anda menamai key Anda userId, hanya
item user yang bisa tinggal di tabel itu dengan rapi — segala yang lain harus
memalsukan sebuah userId atau pindah ke tabelnya sendiri.
Overloading menyiasati itu. Sebuah nama netral seperti pk tidak berkomitmen ke
entitas mana pun, jadi sebuah user, sebuah invoice, dan sebuah audit event semua
bisa berbagi atribut key yang sama dan tabel yang sama. Nilainya, bukan nama
atributnya, yang mengatakan apa item itu.
Ini adalah langkah yang mengubah single-table design dari teori menjadi sesuatu yang bisa Anda query betulan. Tabel bersama adalah wadahnya; overloading adalah yang membuat entitas berbeda hidup berdampingan di dalamnya.
Contoh multi-tenant
Misalkan Anda menjalankan sebuah produk billing SaaS. Setiap tenant punya member, invoice, dan jejak audit. Alih-alih tiga tabel, taruh semuanya dalam satu dan overload key-nya:
| pk | sk | attributes |
|---|---|---|
| TENANT#acme | META | name="Acme Inc", plan="team" |
| TENANT#acme | USER#u_3001 | email, role="admin" |
| TENANT#acme | USER#u_3002 | email, role="member" |
| TENANT#acme | INVOICE#2026-0014 | amount_cents, status="paid" |
| TENANT#acme | INVOICE#2026-0015 | amount_cents, status="open" |
| TENANT#acme | EVENT#2026-06-23T09:12Z | actor="u_3001", action="invite" |
Setiap baris berbagi pk = "TENANT#acme", jadi mereka membentuk satu item
collection — semua ko-lokasi, semua terjangkau dalam satu pembacaan partition.
Prefix sort-key mengerjakan kerja sesungguhnya. Ia mengelompokkan entitas sekaligus mengurutkannya.
Query collection yang ter-overload
Karena tipe-nya tinggal di prefix sort-key, begins_with mengiris partition
berdasarkan entitas tanpa men-scan apa pun:
Query pk = "TENANT#acme" -- seluruh tenant, setiap tipe
Query pk = "TENANT#acme" AND begins_with(sk, "USER#") -- hanya member
Query pk = "TENANT#acme" AND begins_with(sk, "INVOICE#") -- hanya invoice
Anda hanya membayar untuk item yang dicocokkan kondisi, bukan seluruh partition —
kebalikan dari sebuah Scan yang difilter, di mana Anda
membayar untuk membaca baris yang lalu Anda buang. AWS menyebut ini sebuah
condition key; ia berjalan pada key sebelum data apa pun meninggalkan
partition.
Jika Anda membangun kondisi begins_with itu dengan tangan, buat tag tipe-nya
benar — sebuah USERS# yang nyasar alih-alih USER# mengembalikan kosong, secara
diam-diam. Expression builder menghasilkan
KeyConditionExpression dan map ExpressionAttributeValues sehingga prefix-nya
cocok dengan apa yang sebenarnya Anda tulis.
Overload indeks juga
Trik yang sama berlaku untuk sebuah GSI. Beri ia nama key generik — gsi1pk,
gsi1sk — dan biarkan setiap entitas menulis apa pun yang dibutuhkannya. Satu
indeks lalu menjawab pola yang base table tak bisa.
| pk | sk | gsi1pk | gsi1sk |
|---|---|---|---|
| TENANT#acme | INVOICE#2026-0015 | STATUS#open | 2026-06-30 |
| TENANT#acme | INVOICE#2026-0014 | STATUS#paid | 2026-06-12 |
| TENANT#beta | INVOICE#2026-0099 | STATUS#open | 2026-06-25 |
Kini Query gsi1 WHERE gsi1pk = "STATUS#open" mendaftarkan setiap invoice
terbuka di seluruh tenant, terurut berdasarkan due-date — sebuah tampilan
lintas-partition yang key tenant-scoped base table tak akan pernah bisa layani.
Sebuah entitas berbeda bisa memakai ulang gsi1 dengan maknanya sendiri (misalnya
gsi1pk = "ROLE#admin"), jadi satu indeks mencakup beberapa pembacaan. Hanya
ingat bahwa sebuah GSI eventually consistent — penulisannya
tertinggal di belakang base table.
Lakukan di DynoTable
Key ter-overload mentah sukar dibaca: INVOICE#2026-0015 dan
EVENT#2026-06-23T09:12Z membaur dalam sebuah daftar datar. Sebuah viewer yang
mengelompokkan berdasarkan partition dan memunculkan prefix-nya mengubah laci
sampah kembali menjadi entitas.

Jebakan
- Pilih delimiter sekali dan jangan pernah mengubahnya.
#adalah konvensinya. Mencampur#dan:di seluruh entitas merusakbegins_withdengan cara yang tak ada peringatannya. - Jangan overload nilai yang butuh perhitungan rentang. Sebuah sort key
INVOICE#2026-0015terurut secara leksikal, bukan numerik — zero-pad id dan pakai tanggal ISO-8601 agar urutan string cocok dengan urutan yang Anda maksud. - Cadangkan ruang nama prefix. Dua tipe entitas yang sama-sama mulai dengan
USER(misalnyaUSER#danUSERGROUP#) akan bertabrakan di bawahbegins_with(sk, "USER"). Buat prefix tak ambigu dari karakter pertama. - Rencanakan pembacaan sebelum key-nya. Overloading melayani pola akses yang telah Anda enumerasi. Jika Anda belum tahu pembacaan Anda, lihat single-table design lebih dulu — key-nya berada di hilir query.
Petakan sebuah partition, lalu unduh DynoTable untuk menjelajahi key
ter-overload Anda sendiri dan amati satu Query menarik seluruh tenant kembali
sekaligus.


