Belajar LocalStack - Core Service: DynamoDB
Episode 6 of 23

Belajar LocalStack - Core Service: DynamoDB

Menguasai service DynamoDB di LocalStack: membuat tabel dengan PK/SK, put, get, query, scan, secondary index LSI dan GSI, batasan emulasi throughput, dan best practice data modeling.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Pendahuluan

Di episode 5 kita menguasai S3 — object storage untuk file dan media. Sekarang kita pindah ke sisi lain yang tak kalah penting: DynamoDB, database NoSQL key-value dan document yang menjadi tulang punggung banyak arsitektur serverless.

Perbedaan mendasar dengan S3 sudah kita singgung di episode 0: S3 menyimpan file, DynamoDB menyimpan data terstruktur yang diakses lewat primary key, query, dan scan. Di episode ini kita akan melihat bagaimana LocalStack meng-emulasi DynamoDB secara stateful — tabel, item, dan index benar-benar tersimpan — dan bagaimana pola data modeling yang benar membuat aplikasi kalian cepat dan hemat.

Membuat Tabel dengan Primary Key

Setiap tabel DynamoDB wajib punya primary key. Primary key bisa sederhana (satu partition key / HASH) atau komposit (partition key + sort key / RANGE). Model komposit inilah yang paling fleksibel, karena satu partition key bisa menampung banyak item yang diurutkan oleh sort key.

Membuat tabel dengan komposit key
awslocal dynamodb create-table \
  --table-name users \
  --attribute-definitions AttributeName=pk,AttributeType=S AttributeName=sk,AttributeType=S \
  --key-schema AttributeName=pk,KeyType=HASH AttributeName=sk,KeyType=RANGE \
  --billing-mode PAY_PER_REQUEST

Tabel users dibuat dengan pk (HASH) dan sk (RANGE). Dengan --billing-mode PAY_PER_REQUEST, kita tidak perlu menyetel kapasitas — emulator mengabaikan limit throughput, tapi sintaksnya tetap valid untuk produksi.

Tabel tidak langsung aktif — butuh beberapa detik hingga berstatus ACTIVE. Verifikasi dengan:

Mengecek status tabel
awslocal dynamodb describe-table --table-name users --query 'Table.TableStatus'

Setelah ACTIVE, tabel siap menerima item. Cek daftar tabel yang sudah dibuat dengan awslocal dynamodb list-tables.

Item di DynamoDB ditulis dengan format attribute ber-tipe (S untuk string, N untuk number, B untuk binary). Contoh put-item dan get-item:

Menulis dan membaca item
awslocal dynamodb put-item --table-name users --item '{"pk": {"S": "user#1"}, "sk": {"S": "profile"}, "name": {"S": "Arman"}, "age": {"N": "30"}}'
awslocal dynamodb get-item --table-name users --key '{"pk": {"S": "user#1"}, "sk": {"S": "profile"}}'

Perhatikan pola penamaan user#1 pada partition key. Ini bagian dari single table design yang akan kita bahas nanti — memungkinkan banyak jenis entity tinggal dalam satu tabel.

Query vs Scan

Ini keputusan paling penting dalam pemakaian DynamoDB:

  • Query membaca item berdasarkan partition key (dan opsional kondisi pada sort key). Ia memanfaatkan index sehingga cepat dan efisien.
  • Scan membaca seluruh tabel lalu memfilter di memori. Ia fleksibel tapi mahal — semakin besar tabel, semakin lambat dan semakin banyak kapasitas yang dihabiskan.
Query vs scan
awslocal dynamodb query --table-name users --key-condition-expression "pk = :pk" --expression-attribute-values '{":pk": {"S": "user#1"}}'
awslocal dynamodb scan --table-name users

Tip

Jadikan scan sebagai pilihan terakhir. Kalau kalian sering butuh memfilter dengan atribut selain primary key, itu pertanda kalian butuh secondary index atau desain key yang lebih baik.

Secondary Index: LSI dan GSI

Secondary index memungkinkan query dengan pola akses tambahan tanpa scan. Ada dua jenis:

JenisBasisKeterangan
LSI (Local Secondary Index)Sort key alternatif pada partition key yang samaDidefinisikan saat tabel dibuat
GSI (Global Secondary Index)Partition key dan sort key baruBisa ditambah kapan saja

Contoh membuat tabel dengan GSI yang mengindeks customerId dan status:

Tabel dengan Global Secondary Index
awslocal dynamodb create-table \
  --table-name orders \
  --attribute-definitions AttributeName=orderId,AttributeType=S AttributeName=customerId,AttributeType=S AttributeName=status,AttributeType=S \
  --key-schema AttributeName=orderId,KeyType=HASH \
  --global-secondary-indexes 'IndexName=ByCustomer,KeySchema=[{AttributeName=customerId,KeyType=HASH},{AttributeName=status,KeyType=RANGE}],Projection={ProjectionType=ALL}' \
  --billing-mode PAY_PER_REQUEST

Setelah GSI aktif, query berdasarkan customerId menjadi cepat:

Query memakai GSI
awslocal dynamodb query --table-name orders --index-name ByCustomer --key-condition-expression "customerId = :c" --expression-attribute-values '{":c": {"S": "cust-1"}}'

Emulasi Throughput

Di AWS sungguhan, akses item diukur dalam unit kapasitas: provisioned (WCU/RCU) atau on-demand (bayar per request). LocalStack mengabaikan limit throughput — semua akses dianggap berhasil tanpa memperhitungkan kapasitas. Ini menyenangkan untuk development, tapi ada konsekuensinya:

  • Kalian tidak bisa menguji throttling (request ditolak karena melebihi kapasitas) secara realistis.
  • Pola akses yang boros (scan berulang) tidak terlihat biayanya sampai di produksi.

Karena itu, tetap disiplin dengan pola akses yang efisien walau emulator tidak menghukum kalian.

Best Practice Data Modeling

Dua prinsip yang paling berdampak:

  • Single table design: simpan banyak entity (user, order, product) dalam satu tabel dengan pola key seperti user#1 dan order#1. Satu query bisa mengambil banyak jenis data yang terkait, mengurangi jumlah tabel dan round-trip.
  • Pilih partition key dengan distribusi merata: partition key yang hanya punya sedikit nilai (misal active) membuat satu partisi panas. Gunakan nilai dengan kardinalitas tinggi, seperti ID pengguna.
PrinsipMengapa
Desain mengikuti pola aksesTabel dioptimalkan untuk query yang benar-benar dipakai
Hindari scanScan mahal di produksi; gunakan key atau index
Satu entity, satu pola keySingle table design memudahkan query gabungan

Penutup

  • DynamoDB di LocalStack bersifat stateful: tabel, item, dan index tersimpan nyata.
  • Kuasai create-table (PK/SK), put-item, get-item, query, dan scan — utamakan query, hindari scan.
  • Secondary index LSI dan GSI membuka pola akses baru tanpa scan.
  • Emulator mengabaikan limit throughput, jadi tetap disiplin dengan desain yang efisien.
  • Single table design dan partition key yang tersebar merata adalah kunci performa.

Dua service core sudah kalian kuasai. Di episode 7 berikutnya kita naik ke level berikutnya: membuat dan menjalankan fungsi Lambda di LocalStack — dari create-function, invoke, hingga men-trigger-nya dari event S3 dan SQS. Sampai jumpa di episode berikutnya!

Belajar LocalStack - Core Service: DynamoDB | Belajar LocalStack