Berapa penulisan per detik sebelum tabel DynamoDB baru kena throttling?
AWS mendokumentasikan bahwa tabel yang baru dibuat melayani "up to 4,000 write request units per second" langsung sejak awal. Studi yang masih dikutip semua orang untuk apa yang sebenarnya terjadi — yang ditautkan Capital One maupun ScyllaDB — mengukurnya pada 2019, sebelum warm throughput, sebelum maksimum yang dapat dikonfigurasi, sebelum aturan penskalaan saat ini ada. Sejauh yang kami tahu, belum ada yang mempublikasikan pengukuran sejak itu.
Jadi kami menjalankan satu pengukuran. Pada 2026-08-27, terhadap tabel yang dibuat beberapa menit sebelumnya di us-east-1, beban write yang ditawarkan dinaikkan bertahap dari 1,000 ke 8,000 request per detik:
| Ditawarkan | Tercapai | Request ter-throttle |
|---|---|---|
| 1,000/s | 1,000/s | 0 |
| 2,000/s | 2,000/s | 0 |
| 3,000/s | 3,000/s | 0 |
| 4,000/s | 4,000/s | 0 |
| 5,000/s | 4,132/s | 25,992 |
| 6,000/s | 4,131/s | 55,966 |
| 8,000/s | 4,134/s | 115,922 |
Baseline yang terdokumentasi bertahan, dan ia sedikit konservatif: layanan menerima semuanya hingga 4,000/s tanpa satu pun penolakan, lalu terpaku di 4,130 ±2 write per detik seberapa keras pun kami mendorong. Tiga jendela, tiga laju yang ditawarkan, plafon yang sama dalam selisih 0.05%. Pembacaan tidak pernah di-throttle sama sekali — kami mendorong tabel yang sudah diisi melewati 12,700 pembacaan eventually-consistent per detik dan kekurangan di atas angka itu adalah klien kami sendiri, bukan DynamoDB.
Satu tabel, satu hari, satu region, item ~1 KB dengan key acak seragam — tidak ada di mana pun. Cakupan itu adalah cetakan jujur di balik setiap angka di sini. Sisa tulisan ini adalah bagaimana kami mengukurnya, termasuk bagian saat benchmark gagal tiga kali sebelum berhasil, dan tidak satu pun kegagalan itu salah DynamoDB.
Throttle-nya adalah 400, dan ia menyebut tersangka yang keliru lebih dulu
Saat plafon tercapai, error yang Anda dapat layak dibaca dengan cermat:
ThrottlingException: Throughput exceeds the current capacity of your table or index.
DynamoDB is automatically scaling your table or index so please try again shortly.
If exceptions persist, check if you have a hot key:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.htmlTiga pengamatan, semuanya terukur:
- Ini HTTP 400, bukan 5xx. Kebijakan retry dan dashboard Anda perlu tahu itu. Klien yang hanya me-retry 5xx akan membuangnya begitu saja; monitor yang hanya beralarm pada 5xx akan menampilkan layanan hijau sementara sepertiga write Anda terpental.
- Throttle pertama datang 0.9–3.8 detik setelah tiap jendela di atas baseline dimulai — layanan memberi Anda burst tenggang singkat sebelum plafon aktif, dan makin tinggi laju yang ditawarkan, makin cepat ia menggigit.
- Petunjuk hot key adalah default, bukan diagnosis. Key kami adalah UUID acak seragam; tidak ada hot key. Pada skala kecil, tersangka pertama untuk pesan ini hanyalah plafon di level tabel.
Latensi tetap acuh terhadap semua itu: latensi write p50 adalah 4–5 ms in-region di setiap jendela, di-throttle atau tidak. Penolakan itu murah bagi layanan — ia tidak melambat, ia hanya berkata tidak.
Anda tidak bisa mengukur ini dari laptop
Instrumen pertama kami adalah yang paling jelas: skrip Node di sebuah laptop di Madrid. Ia memacu 1,000 write per detik dengan bersih dan ambruk di 2,000 — bukan karena DynamoDB mendorong balik, tetapi karena round-trip Atlantik ~100 ms berarti 2,000 request in-flight per detik butuh ratusan socket bersamaan, dan event loop tenggelam. Layanan tidak pernah mem-throttle sekali pun. Kami sedang mem-benchmark Wi-Fi kami sendiri.
Percobaan kedua memindahkan runner ke region yang sama, sebagai satu fungsi Lambda. Round-trip in-region adalah ~5 ms, dan satu fungsi 3 GB memacu 2,000 request per detik dengan bersih pada p50 10 ms. Melewati itu ia mendatar di sekitar 1,100/s dengan CPU mentok: penandatanganan request dan penanganan respons adalah JavaScript single-thread, dan satu runner sederhananya tidak bisa menandatangani 4,000 request per detik. Memori dialokasikan: 3 GB. Memori terpakai: 253 MB. Bottleneck-nya tidak pernah RAM — porsi CPU sebuah Lambda menskala dengan setelan memorinya, dan kami sedang membeli komputasi, bukan penyimpanan.
Jadi instrumen finalnya adalah armada delapan Lambda, masing-masing memacu seperdelapan dari total laju yang ditawarkan, semuanya dimulai terhadap T0 wall-clock bersama agar jendela mereka sejajar. Delapan runner pada 1,000/s yang nyaman masing-masing memberi kami 8,000/s beban yang ditawarkan dengan sisa ruang, dan agregatnya adalah jumlah request yang dihitung — tanpa ekstrapolasi di mana pun.
Tiga run mati sebelum satu berhasil, dan DynamoDB tak bersalah setiap kalinya
Run pertama armada berakhir dengan satu runner melaporkan bahwa ia mulai 882 detik setelah T0 — terlambat lima belas menit untuk janji dua puluh detik. Run kedua mati dengan read timeout. Run ketiga, dengan retry dimatikan, gagal dengan keras di kedelapan runner sekaligus. Sementara itu CloudWatch menunjukkan setiap Lambda menyelesaikan pengukuran empat menitnya dengan bersih, tepat waktu, tanpa error.
Biang keladinya adalah koneksi antara laptop dan Lambda. Invocation sinkron menahan satu koneksi HTTPS tetap terbuka, sepenuhnya senyap, selama seluruh run — dan router rumahan diam-diam mematikan koneksi senyap setelah beberapa menit. CLI, melihat socket mati, melakukan hal terburuk yang mungkin: ia diam-diam me-retry, menjalankan ulang Lambda pengukur yang lalu mendapati T0-nya sudah lama lewat. Harness benchmark yang bisa berjalan dua kali tanpa terlihat bukanlah harness; itu generator angka acak dengan tagihan AWS.
Bentuk yang akhirnya berhasil punya tiga aturan yang kini akan kami pakai untuk pengukuran jarak jauh berdurasi panjang mana pun:
- Fire-and-forget, hasil out-of-band. Runner dipanggil secara asinkron (koneksi menutup dalam milidetik) dan menulis hasilnya sebagai item ke sebuah tabel DynamoDB kecil; driver mem-poll delapan baris hasil. Tidak ada koneksi yang hidup lebih lama dari satu request.
- Retry mati di mana-mana. Klien pengukur berjalan pada satu percobaan per request — sebuah retry akan diam-diam menyerap throttle yang justru kami hitung — dan jalur invocation juga punya retry yang dimatikan, jadi tidak ada runner yang bisa dieksekusi dua kali.
- Watchdog alih-alih hang. Setiap runner mengadu jadwalnya dengan sebuah deadline; jika ada yang macet, ia mengembalikan hitungan parsial plus snapshot persis di mana ia tersangkut, alih-alih timeout dalam diam. Run gagal yang menjelaskan dirinya berbiaya satu pembacaan; run yang menggantung berbiaya satu malam.
Setiap request juga membawa timeout 8 detik. Run yang menggantung terjadi karena satu request in-flight tanpa timeout memacetkan langkah drain terakhir selamanya. Satu penantian tanpa batas, per ~4 juta request, sudah cukup.
Apa yang dilakukan pembacaan
Fase baca berjalan terhadap tabel baru kedua yang diisi 1,000 item, memakai GetItem (~1 KB masing-masing, 0.5 read unit):
| Ditawarkan | Tercapai | Ter-throttle |
|---|---|---|
| 4,000/s | 4,000/s | 0 |
| 8,000/s | 7,941/s | 0 |
| 12,000/s | 11,119/s | 0 |
| 16,000/s | 12,762/s | 0 |
Nol throttle, sama sekali. Baseline terdokumentasi 12,000 baca/s bertahan dan kami tidak menemukan tepinya: pada 16,000/s yang ditawarkan, lima dari delapan runner kami mencapai saturasi sisi klien mereka sendiri, jadi angka 12,762/s adalah tempat armada kami mentok, bukan tempat DynamoDB mentok. Kami mengatakannya terus terang alih-alih mendandaninya sebagai limit layanan. Pembacaan in-region berjalan pada p50 2–4 ms.
Dua angka lebih kecil yang layak disimpan: tabel on-demand baru bergerak dari CreateTable ke ACTIVE dalam 22 detik pada run benchmark dan 7.4 detik pada probe sebelumnya — anggarkan untuk variansinya, bukan untuk kasus terbaiknya. Dan seluruh benchmark, 672,116 write tertagih dan 1.08 juta pembacaan, berbiaya $0.97. Instrumennya bisa dipakai ulang; eksperimennya seharga secangkir kopi.
Setengah jam tekanan tidak melipatgandakan plafon
Aturan pertumbuhan AWS mengatakan kapasitas on-demand mengakomodasi hingga dua kali puncak Anda sebelumnya. Kami ingin melihat itu terjadi, jadi setelah run plafon kami menahan sebuah tabel pada beban 8,000 write/s yang ditawarkan selama 34 menit berturut-turut dan mengelompokkan laju tercapai per 10 detik. Bentuknya:
| Menit di bawah beban | Plafon |
|---|---|
| 0–8 | ~4,000/s (baseline, tak bergerak) |
| 9–25 | ~5,000/s |
| 26 | ~6,000/s |
| 27–34 | ~7,000/s |
Pertumbuhan datang dalam langkah ~1,000/s yang mendadak, bukan tanjakan — satu menit datar pada satu laju, menit berikutnya datar pada laju berikutnya. Plafon pertama lengket selama 8 menit penuh permintaan berlebih yang terus-menerus. Dan setelah 34 menit tabel melayani 7,000/s: 1.75× dari tempatnya bermula, masih kurang dari 8,000 yang ditawarkan dan dari penggandaan yang bersih. Jika peluncuran Anda butuh lebih dari ~4,000 write/s pada tabel baru, panaskan lebih dulu atau setel throughput on-demand maksimumnya secara eksplisit — mekanisme pertumbuhannya nyata tetapi ia tidak instan maupun murah hati pada jadwal Anda. Perilakunya juga stabil: di bawah beban 9,000/s yang ditawarkan, tabel studi 2019 telah tumbuh ke sekitar 7,000/s saat pengujian berakhir — plateau yang sama yang dicapai tabel kami tujuh tahun kemudian. Run itu berbiaya $12.67, hal termahal yang kami lakukan sepanjang hari.
Apa yang bisa diterapkan jika Anda mengukur layanan cloud sendiri
- Letakkan generator beban di region yang sama dengan targetnya. Jika tidak, Anda mengukur rute Anda, bukan layanannya.
- Satu proses Node mentok di sekitar 2,000 request tertandatangani per detik berapa pun memorinya; pecah bebannya ke beberapa runner dan jumlahkan hasil yang dihitung.
- Matikan retry pada jalur pengukuran, di setiap lapisan. Retry ada untuk menyembunyikan persis apa yang ingin dilihat sebuah benchmark.
- Jangan pernah menahan koneksi senyap sepanjang run yang panjang. Panggil secara asinkron, kirim hasil out-of-band, poll.
- Beri setiap request sebuah timeout dan setiap runner sebuah watchdog yang mengembalikan data parsial dengan snapshot keadaan macetnya.
- Setel plafon operasi yang keras per runner agar bug pacing membatalkan diri alih-alih menggelembungkan tagihan, dan bongkar semua yang dibuat run itu — tabel, role, fungsi, log — di dalam
finally.
Halaman referensi yang disuplai data ini
Dataset lengkapnya — setiap jendela, setiap runner, persentil latensi, string error verbatim — kini menopang tabel terukur di referensi limit DynamoDB kami, bersama probe ukuran item dan limit halaman yang kami publikasikan sebelumnya. Jika Anda bekerja dengan DynamoDB setiap hari, DynoTable adalah klien desktop kami untuknya — tim yang sama, kebiasaan yang sama untuk mengecek klaim terhadap layanan live sebelum mengulanginya.