DynamoDB LocalでTTLを使うなら、TTL属性をレンジキーにしない方がいい

  • AWS
  • DynamoDB
  • CLI

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

認証トークンを保存するテーブルをDynamoDB Localで作った。TTL属性はHASH/RANGEどちらのキーにも含めず、独立した属性として持たせる構成にした。

なぜRANGEキーにしない方がいいか

DynamoDBのキー(HASH/RANGE)は不変。値を変えたいときは UpdateItem ではなく実質的に別アイテムの作成になる。

トークンの有効期限を延長する運用(セッション延長など)がある場合、expire がRANGEキーだと「有効期限を更新する」つもりが「新しいアイテムを作って古い方が残る」という挙動になる。用途がワンショットの使い捨てトークンで延長が発生しないなら実害は少ないが、そうでないなら最初からTTL属性はキー外に置いた方が安全。

修正後のテーブル定義

token のみをHASHキーにして、TTL属性 ttl は通常の属性として持たせる。

dynamodb-local-create-table-ExampleTokens.json

{
"AttributeDefinitions": [
{
"AttributeName": "token",
"AttributeType": "S"
}
],
"TableName": "ExampleTokens",
"KeySchema": [
{
"AttributeName": "token",
"KeyType": "HASH"
}
],
"BillingMode": "PAY_PER_REQUEST"
}
$ aws dynamodb create-table --cli-input-json file://dynamodb-local-create-table-ExampleTokens.json --endpoint-url http://localhost:8000 --region ap-northeast-1

TTL属性はNumber型(UNIX epoch秒)である必要がある。ttl は AttributeDefinitions には書かない(キーにしない属性はテーブル定義時に宣言不要)。

TTLの有効化

$ aws dynamodb update-time-to-live --table-name ExampleTokens --time-to-live-specification "Enabled=true, AttributeName=ttl"
$ aws dynamodb describe-time-to-live --table-name ExampleTokens
{
"TimeToLiveDescription": {
"AttributeName": "ttl",
"TimeToLiveStatus": "ENABLED"
}
}

コマンド自体はキーがHASHのみの構成でもRANGE付きの構成でも変わらない。

DynamoDB LocalではTTLの自動削除は動かない

update-time-to-live は成功するし describe-time-to-live も ENABLED を返すが、DynamoDB Local(amazon/dynamodb-local)はTTLによるバックグラウンド削除処理自体を実装していないという報告が多い。つまりローカルでは期限切れアイテムがいつまで経っても消えない。公式ドキュメントで明言された記述は見つけられなかったので未確認情報として書いておくが、ローカルでTTL削除の動作確認をしたい場合は事前に検証した方がいい。

本番のDynamoDBでもTTL削除は即時ではなく非同期のバックグラウンド処理で、期限切れから典型的には2日以内に削除される。期限切れ後もreadやqueryには残り続けるので、削除を前提にしたテストをするなら別途フィルタ処理が必要。

テーブル削除

$ aws dynamodb delete-table --table-name ExampleTokens --endpoint-url http://localhost:8000 --region ap-northeast-1