DynamoDB ローカルではkeyやindexに含まれないattributeを宣言できてしまう

結論

Amazon DynamoDBではテーブル作成時にkeyやindexに含まれていないattributeを宣言しようとするとエラーになるのだが、
ローカル版ではこれが問題なく宣言できてしまう。

バージョン

DynamoDB ローカルについて

AWS DynamoDBはローカル動作するバージョンが公式に提供されているが、
動作は実際のDynamoDBと異なる場合がある。
そのことは上記公式ドキュメントに示されているが、明記されていない違いもある。

前提

DynamoDBでは以下のようなJSONでテーブル構造を宣言する。

    "TableName": "user_activity",
    "AttributeDefinitions": [
        {
            "AttributeName": "user_id",
            "AttributeType": "S"
        },
        {
            "AttributeName": "created_at",
            "AttributeType": "S"
        }
    ],
    "KeySchema": [
      {
          "AttributeName": "user_id",
          "KeyType": "HASH"
      },
      {
          "AttributeName": "created_at",
          "KeyType": "RANGE"
      }
    ]

この定義からはuser_idcreated_atがkeyであるテーブルが作成される。
attributeはuser_idcreated_atだけである。

keyはこれで良いとしてもっとattributeの多いテーブルを作ろうと、
contents_idというattributeを追加するとエラーが発生する。

    "TableName": "user_activity",
    "AttributeDefinitions": [
        {
            "AttributeName": "user_id",
            "AttributeType": "S"
        },
        {
            "AttributeName": "created_at",
            "AttributeType": "S"
        },
        {
            "AttributeName": "contents_id",
            "AttributeType": "N"
        }
    ],
    "KeySchema": [
      {
          "AttributeName": "user_id",
          "KeyType": "HASH"
      },
      {
          "AttributeName": "created_at",
          "KeyType": "RANGE"
      }
    ]
The number of attributes in key schema must match the number of attributes defined in attribute definitions.

要するにkey(あるいは各種index)に含まれないattributeは宣言できないということになる。
そもそもDynamoDBはスキーマレスで、attributeは各データが好きに追加できるのだから、
無駄なものを定義するなということなのだろう。

ローカルでは

ところが、DynamoDB ローカルではエラーが発生せず、
実際にそのattributeを持ったテーブルが作成されてしまう。

これによって追加分のattributeがデータの挿入時に必須になる、
とかいう事はないので、単に宣言したattributeがdescribe-table等で表示されるようになるという程度。

ローカルでの動作上は特に問題ないのだが、
このテーブル定義で実際のDynamoDBにテーブルを作成しようとするとエラーになって慌てるので注意しよう、というお話。