dynamo (terraform)

Table with other attributes in addition to the KeySchema (either only hash_key or with range_key)

Update: Terraform AWS provider 4.39.0 added resource:

aws_dynamodb_table_item
which represents a 'record' of the table, not an individual attribute.


Although it's possible in the AWS Console to define a Dynamo table with hash_key (no range_key) and several other attributes; this isn't possible with Terraform:

all attributes must be indexed. Unused attributes


Alternatives:

a) Declare table with only attributes that are going to be used as:

  • Table hash key or range key

  • LSI or GSI hash key or range key

Best option. Leave other attributes undeclared.

b) Global Secondary Index (GSI)

Not recommended. Create as many secondary indexes (using their hash_key either with or without range_key) as needed for all defined attributes.

The number of GSIs per table are limited.

Note: When creating an item from the AWS console, only the hash_key (and range_key if exists) appear, but any additional attribute can be added.

c) Local Secondary Index (LSI)

Not a viable option because local_secondary_index requires that the table KeySchema have a range key

Sample: Create table with auto scaling

pro/main.tf

...

module "dynamodb" {

source = "../modules/dynamodb"

env = local.COUEnv

ci = local.ci

department = local.Departament

program = local.Programa

#PITR only enabled for PRO environment

point_in_time_recovery_enabled = false

dynamo_EmailRedirect_read_cap = "1" # Default Read Capacity

dynamo_EmailRedirect_write_cap = "1" # Default Write Capacity

dynamo_EmailRedirect_aut_max = "40" # Autoscale Max Capacity

dynamo_EmailRedirect_aut_min = "1" # Autoscale Min Capacity

dynamo_EmailRedirect_aut_target = "60" # Autoscale Target Read/Write Capacity %


}

modules/dynamo/variables.tf

variable "env" {}

variable "ci" {}

variable "department" {}

variable "program" {}

#

variable "point_in_time_recovery_enabled" { type = bool }

variable "dynamo_EmailRedirect_read_cap" {}

variable "dynamo_EmailRedirect_write_cap" {}

variable "dynamo_EmailRedirect_aut_max" {}

variable "dynamo_EmailRedirect_aut_min" {}

variable "dynamo_EmailRedirect_aut_target" {}

modules/dynamo/dynamo.tf

# Table EmailRedirect

resource "aws_dynamodb_table" "EmailRedirect" {

name = "${var.env}-${var.ci}-EmailRedirect"

billing_mode = "PROVISIONED"

read_capacity = var.dynamo_EmailRedirect_read_cap

write_capacity = var.dynamo_EmailRedirect_write_cap

hash_key = "Email"

range_key = "Alias"


point_in_time_recovery {

#PITR provides continuous backups, and you can restore to any point in time up to the second during the preceding 35 days.

enabled = var.point_in_time_recovery_enabled

}


lifecycle {

ignore_changes = [

read_capacity,

write_capacity

]

}


attribute {

name = "Email"

type = "S"

}


attribute {

name = "Alias"

type = "S"

}


tags = {

COUEnv = var.env

ci = var.ci

Departament = var.department

Programa = var.program

}

}


# Autoscaling Read

resource "aws_appautoscaling_target" "EmailRedirect_read_target" {

max_capacity = var.dynamo_EmailRedirect_aut_max

min_capacity = var.dynamo_EmailRedirect_aut_min

resource_id = "table/${aws_dynamodb_table.EmailRedirect.name}"

scalable_dimension = "dynamodb:table:ReadCapacityUnits"

service_namespace = "dynamodb"

}


resource "aws_appautoscaling_policy" "EmailRedirect_read_policy" {

name = "DynamoDBReadCapacityUtilization:${aws_appautoscaling_target.EmailRedirect_read_target.resource_id}"

policy_type = "TargetTrackingScaling"

resource_id = aws_appautoscaling_target.EmailRedirect_read_target.resource_id

scalable_dimension = aws_appautoscaling_target.EmailRedirect_read_target.scalable_dimension

service_namespace = aws_appautoscaling_target.EmailRedirect_read_target.service_namespace


target_tracking_scaling_policy_configuration {

predefined_metric_specification {

predefined_metric_type = "DynamoDBReadCapacityUtilization"

}


target_value = var.dynamo_EmailRedirect_aut_target

}

}


# Autoscaling Write

resource "aws_appautoscaling_target" "EmailRedirect_write_target" {

max_capacity = var.dynamo_EmailRedirect_aut_max

min_capacity = var.dynamo_EmailRedirect_aut_min

resource_id = "table/${aws_dynamodb_table.EmailRedirect.name}"

scalable_dimension = "dynamodb:table:WriteCapacityUnits"

service_namespace = "dynamodb"

}


resource "aws_appautoscaling_policy" "EmailRedirect_write_policy" {

name = "DynamoDBWriteCapacityUtilization:${aws_appautoscaling_target.EmailRedirect_write_target.resource_id}"

policy_type = "TargetTrackingScaling"

resource_id = aws_appautoscaling_target.EmailRedirect_write_target.resource_id

scalable_dimension = aws_appautoscaling_target.EmailRedirect_write_target.scalable_dimension

service_namespace = aws_appautoscaling_target.EmailRedirect_write_target.service_namespace


target_tracking_scaling_policy_configuration {

predefined_metric_specification {

predefined_metric_type = "DynamoDBWriteCapacityUtilization"

}


target_value = var.dynamo_EmailRedirect_aut_target

}

}