---
title: DynamoDB Streams を Lambda のトリガーで使う話
tags:  #aws #jaws-ug #dynamodb #lambda  
author: [hmatsu47(まつ)](https://www.docswell.com/user/hmatsu47)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/LJL9Y3117R.jpg?width=480
description: JAWS-UG 名古屋 推しの AWS サービスを語る LT 会 2023/03/29
published: March 29, 23
canonical: https://www.docswell.com/s/hmatsu47/5P99XX-2023-03-27-210851
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/LJL9Y3117R.jpg)

DynamoDB Streams を
Lambda のトリガーで使う話
JAWS-UG 名古屋 推しの AWS サービスを語る LT 会
2023/3/29
まつひさ（hmatsu47）


# Page. 2

![Page Image](https://bcdn.docswell.com/page/47MZNDW5JW.jpg)

自己紹介…は時間省略のためスキップ
松久裕保（@hmatsu47）
●
https://qiita.com/hmatsu47
2


# Page. 3

![Page Image](https://bcdn.docswell.com/page/P7R6D4YZE9.jpg)

本日のネタは
● RDS / Aurora
3


# Page. 4

![Page Image](https://bcdn.docswell.com/page/PJXM12G1EX.jpg)

本日のネタは
● RDS / Aurora
4


# Page. 5

![Page Image](https://bcdn.docswell.com/page/3JKG2M4M7D.jpg)

本日のネタは
● RDS / Aurora ではなく DynamoDB + Lambda
● データ登録用の DynamoDB テーブルでストリームを設定
● それをトリガーに Lambda を実行させる話
○ 元テーブルのデータを加工して別テーブルにコピーする
○ Lambda で何らかの非同期 API を呼び出す
■
「中身が見えるキュー」としての使い方
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/LE3N4YL2E5.jpg)

どういうときに使う？
● 違う設計の参照用テーブルを（複数）用意したいケース
○ インデックスの数が多すぎる
■
GSI は 20 個まで、LSI は 5 個まで
○ 後から LSI を追加したくなった
○ 参照用テーブルに必要なパーティションキーまたはソートキーが
非正規形で、テーブルごとに値の組み合わせを変えたい
■
例）テーブル A では登録日＋ユーザー ID、テーブル B では ユーザー ID ＋
商品 ID をパーティションキーにしたい
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/8EDWQ5N67G.jpg)

どういうときに使う？
● 「中身が見えるキュー」として使いたいケース
○ アプリケーションの実装者がキューの扱いに慣れていない
■
キューの中身が見えないと不安
○ 中身を確認後「キューの一部だけ選んで Lambda 再発火」したい
■
レコードを変更して保存すれば再びストリームに流れる
○ ベストプラクティスは別にあるとしても、使う人に合わせた技術
（処理方法）選定があっても良いのでは？
7


# Page. 8

![Page Image](https://bcdn.docswell.com/page/V7P9LGNZJ8.jpg)

使用例（1/2）
● blastengine API でメール送信
○ 送信用テーブルに挿入・変更すると、
↑
ここ
（ストリーム）
○ Streams をトリガーに Lambda を起動
■
blastengine API にリクエストし、
■
成功したら送信履歴テーブルに記録
●
■
送信用テーブルのレコードは削除
失敗したら時間をあけてリトライ
●
レートリミット対策
○ バウンス処理部分の図示・説明は省略
8


# Page. 9

![Page Image](https://bcdn.docswell.com/page/2JVMQ6KMJQ.jpg)

使用例（2/2）
● Qiita 記事はこちら
○
https://qiita.com/hmatsu47/items/e6e8fc9290eede7c8a55
○ API コールを失敗したレコードだけが送信用テーブルに残る
■
必要があれば対象レコードの変更で Lambda 再発火
○ 送信履歴テーブルはバウンス（Webhook で取得）と突合する
■
ここでは説明を省略
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/5EGGWNQXEL.jpg)

実行例（送信用テーブルに挿入）
10


# Page. 11

![Page Image](https://bcdn.docswell.com/page/4JQX3QK5EP.jpg)

実行例（送信用テーブル : API コール失敗レコードが残る）
11


# Page. 12

![Page Image](https://bcdn.docswell.com/page/K7461NPVE1.jpg)

実行例（送信履歴テーブル : API コール成功レコードのみ）
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/LJ1VG594EG.jpg)

実行例（実際に届いたメール）
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/GJWLK5QZE2.jpg)

トリガーの設定例（1/3）
挿入・更新・削除レコードを
最大 100 件ずつまとめて
Lambda に渡す
挿入・更新・削除レコードを
まとめるために待機する秒数
14


# Page. 15

![Page Image](https://bcdn.docswell.com/page/4EZMZNWLJ3.jpg)

トリガーの設定例（2/3）
Lambda 関数の実行がエラー
になったときの再試行回数
（デフォルトは -1: 無制限）
チェックするとエラー再試行時
にレコード行数を半分に分割
15


# Page. 16

![Page Image](https://bcdn.docswell.com/page/Y76NZ8GM7V.jpg)

トリガーの設定例（3/3）
同一シャードから
同時に呼び出される
Lambda は 1 つ
挿入・更新時のみ
Lambdaを呼び出す
16


# Page. 17

![Page Image](https://bcdn.docswell.com/page/G755W9VQ74.jpg)

注意点（1/2）
● 1 テーブルで複数ストリームが流れる
○ シャード単位でストリームが分かれるので、挿入・更新・削除の
順序が完全に保証されるわけではない
■
1 シャード 複数パーティション・1 パーティション複数シャードの両方あり
○ 一方で、ストリームごとの Lambda の処理時間が長すぎると処理
が詰まってしまう
■
Step Functions を呼び出す形を検討
17


# Page. 18

![Page Image](https://bcdn.docswell.com/page/9J2NQ23WER.jpg)

注意点（2/2）
● デフォルトでは Lambda のトリガー再試行は無制限
○ 処理途中に捕捉し損ねたエラー・例外があると課金死の危険が
■
エラー・例外の捕捉漏れが無いようにする
■
再試行の回数を限定しておいたほうが良い
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/DEYPWY19EM.jpg)

まとめ
● DynamoDB の制約に引っ掛かる場合に使える
○ インデックスが多すぎる or LSI を追加したいけどできない
● 「中身が見えるキュー」として使える
○ 中身を見た上で選択的に Lambda を再発火させることも
● ストリームの順序と無限再試行に注意
○ 順序の保証が必要な場合は使わない
○ 再試行の回数を限定して課金死を防ぐ
19


