Dynamodb add GSI to existing table

I created a table but now want to add a GSI. I add a new item to the AttributeDefinitions and then add in the info to the GlobalSecondaryIndexes. When I start up (offline - sls offline start) I am greeted with:

Serverless: DynamoDB - Warn - table bapi_deployments_local already exists

and of course my table is not updated with the GSI. If I wipe out my local table and restart, it does work, but when I want to deploy on AWS I can’t wipe it out. How do I force an update?

    resources:
        Resources:
            bapiDeployments:
                Type: AWS::DynamoDB::Table
                DeletionPolicy: Retain
                Properties:
                    TableName: 'bapi_deployments_${self:provider.stage}'
                    AttributeDefinitions:
                        -
                            AttributeName: user_id
                            AttributeType: S
                        -
                            AttributeName: deployment_id
                            AttributeType: N
                        -
                            AttributeName: org_id
                            AttributeType: S
                    KeySchema:
                        -
                            AttributeName: user_id
                            KeyType: HASH
                        -
                            AttributeName: deployment_id
                            KeyType: RANGE
                    ProvisionedThroughput:
                        ReadCapacityUnits: 1
                        WriteCapacityUnits: 1
                    GlobalSecondaryIndexes:
                        -
                            IndexName: bapi_sources_orgs
                            KeySchema:
                                -
                                    AttributeName: org_id
                                    KeyType: HASH
                                -
                                    AttributeName: deployment_id
                                    KeyType: RANGE
                            Projection:
                                ProjectionType: ALL
                            ProvisionedThroughput:
                                ReadCapacityUnits: 1
                                WriteCapacityUnits: 1

If in doubt reference the documentation. There are only limited circumstances in which updating is supported. If you’re making changes to AttributeDefinitions or KeySchema then be aware it might cause replacement of the table too.

Yea it appears that because I had to add an AttributeDefinition, it did not work. I thought it should be ok since it was not part of the KeySchema to begin with, it was ok, but apparently it is not. What’s strange is that I can add it via the Console just fine, but via Serverless / CF I cannot.

Thanks

I haven’t come across this myself but I have heard that DynamoDB has trouble if you try to make too many changes at once. Perhaps try adding the attribute and then make changes to the GSI? Otherwise I’m out of ideas.

I’ve found that using the aws-cli, I could add a single attribute along with a GSI definition. If I add that attribute and GSI to my serverless.yml file, it fails stating it already exists. If I then delete the index using the AWS console, sls deploy can then create the GSI from the YML definition. I haven’t found another way of adding an attribute and GSI to an existing table at the same time, but something like the following works:

aws dynamodb update-table --table-name mytablename  --attribute-definitions AttributeName=NewFieldName,AttributeType=S --global-secondary-index-updates file://gsi-command-NewFieldName.json

gsi-command-NewFieldName.json would contain something like:

[
  {
    "Create": {
      "IndexName": "NewFieldName-index",
      "KeySchema": [
        {
          "AttributeName": "NewFieldName",
          "KeyType": "HASH"
        }
      ],
      "Projection": {
        "ProjectionType": "KEYS_ONLY"
      },
      "ProvisionedThroughput": {
        "ReadCapacityUnits": 1,
        "WriteCapacityUnits": 1
      }
    }
  }
]

After it’s finished creating the index and Attribute, delete the index and run sls deploy with attribute and gsi defined and it should recreate it under the control of the serverless stack.

I’m curious of this CLI creat, CLI delete, sls deploy process is still the preferred way to add a GSI to an existing table? After doing these steps, I get the following error on deployment:

Property AttributeDefinitions is inconsistent with the KeySchema of the table and the secondary indexes.

Replying to my own comment here for posterity…I had added the index to GlobalSecondaryIndexes but hadn’t added the attribute to AttributeDefinitions, hence it’s complaint.