Menengah8 menit baca

Throttling DynamoDB — Kenapa Terjadi dan Cara Memperbaikinya

Throttling adalah cara DynamoDB memberi tahu Anda bahwa sebuah batas tersentuh — tapi ada empat batas berbeda, tiga exception berbeda, dan perbaikan untuk satu penyebab justru memperburuk penyebab lainnya. Menaikkan kapasitas tabel tidak berguna untuk hot key; beralih ke on-demand juga tidak berguna untuk hot key dan tetap bisa mem-throttle berdasarkan aturannya sendiri. Panduan ini adalah payungnya: batas mana yang sebenarnya Anda sentuh, bagaimana metriknya membedakan, dan perbaikan yang cocok untuk tiap penyebab.

Kenapa DynamoDB mem-throttle permintaan saya?

Salah satu dari empat alasan yang terdokumentasi: satu partisi melampaui batas per-partisinya yang tetap, yaitu 3.000 read unit atau 1.000 write unit per detik (sebuah hot key — terjadi di kedua mode kapasitas); tabel melampaui RCU/WCU provisioned-nya (mode provisioned); akun melampaui kuota throughput di tingkat region; atau sebuah tabel on-demand tumbuh lebih cepat daripada dua kali lipat puncaknya sebelumnya dalam 30 menit. Perbaikannya bergantung pada yang mana, jadi diagnosis dulu sebelum Anda mengubah ukuran apa pun.

Empat skenario throttling

Halaman troubleshooting AWS sendiri membagi throttling menjadi tepat empat kasus:

  1. Throughput key-range (partisi) terlampaui — kedua mode. Setiap partisi dirancang untuk maksimum 3.000 read unit dan 1.000 write unit per detik (dokumentasi partition key), dan ukuran item ikut diperhitungkan. Tidak ada setelan di tingkat tabel yang menaikkannya; hanya desain key yang menyebarkannya. Ini adalah kasus hot partition, dan tabelnya bisa tampak sangat kurang terpakai sementara ia di-throttle.
  2. Provisioned throughput terlampaui — mode provisioned. Konsumsi mengalahkan RCU/WCU provisioned tabel (atau sebuah GSI), dan bantalan burst capacity ~5 menit sudah habis. Tangga perbaikannya ada di sisi kapasitas: auto scaling, provision yang lebih tinggi, atau ganti mode.
  3. Kuota di tingkat akun terlampaui. Kuota akun per region membatasi total throughput — secara default 40.000 read unit dan 40.000 write unit per tabel, dan untuk mode provisioned 80.000 RCU dan 80.000 WCU per akun (kuota); ini adalah default awal, bisa disesuaikan lewat Service Quotas, dan tabel on-demand tidak punya kuota throughput di tingkat akun.
  4. Throughput maksimum on-demand terlampaui. On-demand seketika mengakomodasi hingga dua kali lipat puncak sebelumnya; tumbuh melewati dua kali lipat dalam 30 menit dan ia bisa mem-throttle (dokumentasi on-demand). Tabel on-demand baru sanggup menahan 4.000 penulisan/detik dan 12.000 pembacaan/detik sejak awal. Untuk lonjakan bertahap yang terencana (peluncuran, sale, migrasi), pre-warm tabelnya dengan warm throughput alih-alih berharap kenaikannya landai.

Tiga exception, dan field yang menyebut penyebabnya

  • ProvisionedThroughputExceededException — throttling kapasitas mode provisioned: "you exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes". Detailnya ada di halaman error khususnya.
  • ThrottlingException — operasi control-plane yang dikeluarkan terlalu cepat, dan, pada tabel on-demand, operasi data-plane apa pun yang lajunya terlalu tinggi (itulah exception di balik aturan dua-kali-puncak — lihat halaman error on-demand dan ThrottlingException).
  • RequestLimitExceeded — batas throughput di tingkat akun: wilayah "hubungi AWS Support", dibahas di halaman error-nya.

Ketiganya ditandai bisa di-retry, dan ketiganya kini membawa nilai ThrottlingReason terstruktur berbentuk resource + operasi + batas — TableReadProvisionedThroughputExceeded, IndexWriteKeyRangeThroughputExceeded, TableWriteAccountLimitExceeded, dan seterusnya (referensi error). Bacalah reason-nya, bukan cuma kelas exception-nya: ia menyebut resource-nya (tabel atau index), arah operasinya, dan yang mana dari empat batas itu yang Anda sentuh — dan itu persis diagnosisnya. Satu kehati-hatian yang dipaksakan dokumentasinya sendiri: halaman-halaman AWS berbeda pendapat soal apakah throttling batas akun muncul sebagai RequestLimitExceeded atau sebagai ThrottlingException dengan reason AccountLimitExceeded, jadi sandarkan penanganan Anda pada string reason-nya.

Apa yang menyerap beban sebelum Anda di-throttle

Dua mekanisme bawaan melunakkan batas, dan mengetahui tepinya menjelaskan "kemarin masih jalan kok":

  • Burst capacity menyimpan hingga lima menit (300 detik) kapasitas baca dan tulis yang tak terpakai untuk lonjakan — tapi DynamoDB juga bisa memakainya untuk pemeliharaan latar belakang "without prior notice", dan AWS secara eksplisit mencatat bahwa detailnya bisa berubah. Jangan mendesain bergantung pada burst; perlakukan sebagai keberuntungan.
  • Adaptive capacity secara otomatis dan seketika menggeser throughput ke arah partisi yang panas dan bisa mengisolasi sebuah item yang sering diakses ke partisinya sendiri — tapi hanya "provided that traffic does not exceed your table's total provisioned capacity or the partition maximum capacity". Ia menyeimbangkan ulang kemiringan; ia tidak pernah mengangkat plafon per-partisi 3.000/1.000, dan ia tidak akan memecah koleksi item ketika tabelnya punya LSI. Halaman troubleshooting AWS saat ini bersandar pada split-for-heat — partisi yang memecah diri di bawah panas berkelanjutan — yang butuh waktu dan tidak membantu satu hot key.

Diagnosis dari metriknya

CloudWatch memisahkan request dari event, dan pembedaan itulah yang mengerjakan diagnosisnya (referensi metrik):

  • ThrottledRequests menghitung sebuah request satu kali kalau ada event di dalamnya yang di-throttle — sebuah PutItem pada tabel dengan tiga GSI adalah satu request tapi empat write event. Di dalam sebuah batch, ia hanya bertambah kalau setiap item di-throttle.
  • ReadThrottleEvents / WriteThrottleEvents menghitung setiap event yang di-throttle — sebuah BatchGetItem untuk 10 item adalah 10 event GetItem. Untuk melihat throttle tulis sebuah GSI, Anda harus meng-query metriknya dengan TableName sekaligus GlobalSecondaryIndexName — beginilah GSI back-pressure bersembunyi dari dashboard di tingkat tabel.
  • Metrik event spesifik-reason yang lebih baru (WriteProvisionedThroughputThrottleEvents, ReadKeyRangeThroughputThrottleEvents, …AccountLimitThrottleEvents, …MaxOnDemandThroughputThrottleEvents) memecah hitungannya berdasarkan empat penyebab yang sama — kalau region Anda menampilkannya, mereka menjawab pertanyaan "batas yang mana" secara langsung.

Satu jebakan: SDK me-retry permintaan yang di-throttle secara otomatis — mode retry standar melakukan 3 percobaan total secara default (peluncuran retry opt-in 2026 memindahkan klien DynamoDB ke 4 percobaan dengan jeda yang lebih rapat). Karena itu throttling ringan muncul sebagai latensi, bukan sebagai error; awasi metrik throttle-nya, bukan cuma log exception Anda.

yesnoyesnoprovisionedon-demandThrottling observedThrottleEvents on a GSI(TableName + IndexName)?GSI back-pressure:scale the indexTable utilization far belowprovisioned / expected?Hot key: fix key design,split-for-heat needs timeCapacity mode?Raise capacity /auto scaling / switch modeGrew past 2x previous peak:pre-warm or spread the ramp

GSI back-pressure: throttle yang menunjuk tabel yang salah

Kalau ada GSI yang tidak sanggup menyerap amplifikasi tulis, "DynamoDB throttles writes to the base table to maintain data consistency" (dokumentasi throttling GSI) — bahkan ketika tabel dasarnya masih punya kapasitas berlebih. ResourceArn exception-nya menunjuk ke index, tapi operasi yang gagal adalah penulisan tabel dasar Anda. Setiap index butuh rencana kapasitasnya sendiri (dan policy auto scaling-nya sendiri); kenapa GSI mem-throttle tulisan tabel dasar membahas mekanismenya.

Cocokkan perbaikan dengan penyebabnya

PenyebabYang memperbaikinyaYang tidak
Hot key / partisiDesain key yang menyebarkan beban (hot partition); waktu untuk split-for-heatMenaikkan kapasitas tabel, beralih ke on-demand
Kapasitas provisionedAuto scaling, minimum yang lebih tinggi, atau on-demandRetry saja — malah menambah beban
GSI back-pressureSkalakan index-nya; ubah sparse index atau projectionMenskalakan tabel dasarnya
Kuota akunKenaikan lewat Service QuotasSetelan di tingkat tabel
Lonjakan bertahap on-demandPre-warm (warm throughput); sebarkan kenaikannya selama 30+ menitMenunggu — dua-kali-puncak turun perlahan

Lakukan di DynoTable

Sebagian besar throttling akibat ulah sendiri berawal dari pembacaan yang biayanya lebih besar daripada tampaknya: sebuah Scan yang difilter tetap mengonsumsi pembacaan penuh. Pratinjau biaya pra-eksekusi DynoTable menunjukkan apakah sebuah statement menjadi Query atau Scan, index yang dikenainya, dan perkiraan biaya baca sebelum Anda membelanjakannya — perbaikan throttling termurah adalah pembacaan mahal yang tidak Anda jalankan. Panduan Scan vs Query membahas perbedaannya; kalkulator ukuran item gratis mengubah sebuah item nyata menjadi angka RCU/WCU yang dipakai untuk mengukur batas-batas di atas.

Jebakan dan langkah berikutnya

  • Retry memperbesar kelebihan beban. Backoff sudah dibangun ke dalam SDK, tapi loop retry ketat di tingkat aplikasi di atas retry SDK melipatgandakan tekanan tepat pada partisi yang sedang kepayahan.
  • Batch menyembunyikan throttling parsial. Sebuah BatchWriteItem mengembalikan item yang tak terproses alih-alih melempar exception selama ada item yang berhasil — periksa UnprocessedItems, bukan cuma exception.
  • Tampilan di tingkat tabel berbohong soal GSI. Selalu grafikkan throttle event per index; dashboard tabel dasar terlihat bersih selama back-pressure.
  • Perbaikan kapasitas makan menit; desain key itu selamanya. Auto scaling bereaksi dalam ~5 menit, kenaikan kuota butuh tiket dukungan, tapi sebuah hot key mengikuti Anda ke setiap mode kapasitas — curahkan usaha di tempat yang berbunga: cara kerja partition key.

Unduh DynoTable untuk melihat rencana Scan-lawan-Query dan biaya baca setiap query sebelum ia berjalan terhadap kapasitas Anda.

Diperbarui