Table
Provides a DynamoDB table resource.
Note: It is recommended to use
ignoreChangesforread_capacityand/orwrite_capacityif there'sautoscaling policyattached to the table. Note: When using aws.dynamodb.TableReplica with this resource, uselifecycleignore_changesforreplica, e.g.,lifecycle { ignore_changes = [replica] }.
DynamoDB Table attributes
Only define attributes on the table object that are going to be used as:
Table hash key or range key
LSI or GSI hash key or range key The DynamoDB API expects attribute structure (name and type) to be passed along when creating or updating GSI/LSIs or creating the initial table. In these cases it expects the Hash / Range keys to be provided. Because these get re-used in numerous places (i.e the table's range key could be a part of one or more GSIs), they are stored on the table object to prevent duplication and increase consistency. If you add attributes here that are not used in these scenarios it can cause an infinite loop in planning.
Example Usage
Basic Example
The following dynamodb table description models the table and GSI shown in the AWS SDK example documentation
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const basic_dynamodb_table = new aws.dynamodb.Table("basic-dynamodb-table", {
name: "GameScores",
billingMode: "PROVISIONED",
readCapacity: 20,
writeCapacity: 20,
hashKey: "UserId",
rangeKey: "GameTitle",
attributes: [
{
name: "UserId",
type: "S",
},
{
name: "GameTitle",
type: "S",
},
{
name: "TopScore",
type: "N",
},
],
ttl: {
attributeName: "TimeToExist",
enabled: false,
},
globalSecondaryIndexes: [{
name: "GameTitleIndex",
hashKey: "GameTitle",
rangeKey: "TopScore",
writeCapacity: 10,
readCapacity: 10,
projectionType: "INCLUDE",
nonKeyAttributes: ["UserId"],
}],
tags: {
Name: "dynamodb-table-1",
Environment: "production",
},
});import pulumi
import pulumi_aws as aws
basic_dynamodb_table = aws.dynamodb.Table("basic-dynamodb-table",
name="GameScores",
billing_mode="PROVISIONED",
read_capacity=20,
write_capacity=20,
hash_key="UserId",
range_key="GameTitle",
attributes=[
aws.dynamodb.TableAttributeArgs(
name="UserId",
type="S",
),
aws.dynamodb.TableAttributeArgs(
name="GameTitle",
type="S",
),
aws.dynamodb.TableAttributeArgs(
name="TopScore",
type="N",
),
],
ttl=aws.dynamodb.TableTtlArgs(
attribute_name="TimeToExist",
enabled=False,
),
global_secondary_indexes=[aws.dynamodb.TableGlobalSecondaryIndexArgs(
name="GameTitleIndex",
hash_key="GameTitle",
range_key="TopScore",
write_capacity=10,
read_capacity=10,
projection_type="INCLUDE",
non_key_attributes=["UserId"],
)],
tags={
"Name": "dynamodb-table-1",
"Environment": "production",
})using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var basic_dynamodb_table = new Aws.DynamoDB.Table("basic-dynamodb-table", new()
{
Name = "GameScores",
BillingMode = "PROVISIONED",
ReadCapacity = 20,
WriteCapacity = 20,
HashKey = "UserId",
RangeKey = "GameTitle",
Attributes = new[]
{
new Aws.DynamoDB.Inputs.TableAttributeArgs
{
Name = "UserId",
Type = "S",
},
new Aws.DynamoDB.Inputs.TableAttributeArgs
{
Name = "GameTitle",
Type = "S",
},
new Aws.DynamoDB.Inputs.TableAttributeArgs
{
Name = "TopScore",
Type = "N",
},
},
Ttl = new Aws.DynamoDB.Inputs.TableTtlArgs
{
AttributeName = "TimeToExist",
Enabled = false,
},
GlobalSecondaryIndexes = new[]
{
new Aws.DynamoDB.Inputs.TableGlobalSecondaryIndexArgs
{
Name = "GameTitleIndex",
HashKey = "GameTitle",
RangeKey = "TopScore",
WriteCapacity = 10,
ReadCapacity = 10,
ProjectionType = "INCLUDE",
NonKeyAttributes = new[]
{
"UserId",
},
},
},
Tags =
{
{ "Name", "dynamodb-table-1" },
{ "Environment", "production" },
},
});
});package main
import (
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/dynamodb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := dynamodb.NewTable(ctx, "basic-dynamodb-table", &dynamodb.TableArgs{
Name: pulumi.String("GameScores"),
BillingMode: pulumi.String("PROVISIONED"),
ReadCapacity: pulumi.Int(20),
WriteCapacity: pulumi.Int(20),
HashKey: pulumi.String("UserId"),
RangeKey: pulumi.String("GameTitle"),
Attributes: dynamodb.TableAttributeArray{
&dynamodb.TableAttributeArgs{
Name: pulumi.String("UserId"),
Type: pulumi.String("S"),
},
&dynamodb.TableAttributeArgs{
Name: pulumi.String("GameTitle"),
Type: pulumi.String("S"),
},
&dynamodb.TableAttributeArgs{
Name: pulumi.String("TopScore"),
Type: pulumi.String("N"),
},
},
Ttl: &dynamodb.TableTtlArgs{
AttributeName: pulumi.String("TimeToExist"),
Enabled: pulumi.Bool(false),
},
GlobalSecondaryIndexes: dynamodb.TableGlobalSecondaryIndexArray{
&dynamodb.TableGlobalSecondaryIndexArgs{
Name: pulumi.String("GameTitleIndex"),
HashKey: pulumi.String("GameTitle"),
RangeKey: pulumi.String("TopScore"),
WriteCapacity: pulumi.Int(10),
ReadCapacity: pulumi.Int(10),
ProjectionType: pulumi.String("INCLUDE"),
NonKeyAttributes: pulumi.StringArray{
pulumi.String("UserId"),
},
},
},
Tags: pulumi.StringMap{
"Name": pulumi.String("dynamodb-table-1"),
"Environment": pulumi.String("production"),
},
})
if err != nil {
return err
}
return nil
})
}package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.dynamodb.Table;
import com.pulumi.aws.dynamodb.TableArgs;
import com.pulumi.aws.dynamodb.inputs.TableAttributeArgs;
import com.pulumi.aws.dynamodb.inputs.TableTtlArgs;
import com.pulumi.aws.dynamodb.inputs.TableGlobalSecondaryIndexArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var basic_dynamodb_table = new Table("basic-dynamodb-table", TableArgs.builder()
.name("GameScores")
.billingMode("PROVISIONED")
.readCapacity(20)
.writeCapacity(20)
.hashKey("UserId")
.rangeKey("GameTitle")
.attributes(
TableAttributeArgs.builder()
.name("UserId")
.type("S")
.build(),
TableAttributeArgs.builder()
.name("GameTitle")
.type("S")
.build(),
TableAttributeArgs.builder()
.name("TopScore")
.type("N")
.build())
.ttl(TableTtlArgs.builder()
.attributeName("TimeToExist")
.enabled(false)
.build())
.globalSecondaryIndexes(TableGlobalSecondaryIndexArgs.builder()
.name("GameTitleIndex")
.hashKey("GameTitle")
.rangeKey("TopScore")
.writeCapacity(10)
.readCapacity(10)
.projectionType("INCLUDE")
.nonKeyAttributes("UserId")
.build())
.tags(Map.ofEntries(
Map.entry("Name", "dynamodb-table-1"),
Map.entry("Environment", "production")
))
.build());
}
}resources:
basic-dynamodb-table:
type: aws:dynamodb:Table
properties:
name: GameScores
billingMode: PROVISIONED
readCapacity: 20
writeCapacity: 20
hashKey: UserId
rangeKey: GameTitle
attributes:
- name: UserId
type: S
- name: GameTitle
type: S
- name: TopScore
type: N
ttl:
attributeName: TimeToExist
enabled: false
globalSecondaryIndexes:
- name: GameTitleIndex
hashKey: GameTitle
rangeKey: TopScore
writeCapacity: 10
readCapacity: 10
projectionType: INCLUDE
nonKeyAttributes:
- UserId
tags:
Name: dynamodb-table-1
Environment: productionGlobal Tables
This resource implements support for DynamoDB Global Tables V2 (version 2019.11.21) via replica configuration blocks. For working with DynamoDB Global Tables V1 (version 2017.11.29), see the aws.dynamodb.GlobalTable resource.
Note: aws.dynamodb.TableReplica is an alternate way of configuring Global Tables. Do not use
replicaconfiguration blocks ofaws.dynamodb.Tabletogether with aws_dynamodb_table_replica.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.dynamodb.Table("example", {
name: "example",
hashKey: "TestTableHashKey",
billingMode: "PAY_PER_REQUEST",
streamEnabled: true,
streamViewType: "NEW_AND_OLD_IMAGES",
attributes: [{
name: "TestTableHashKey",
type: "S",
}],
replicas: [
{
regionName: "us-east-2",
},
{
regionName: "us-west-2",
},
],
});import pulumi
import pulumi_aws as aws
example = aws.dynamodb.Table("example",
name="example",
hash_key="TestTableHashKey",
billing_mode="PAY_PER_REQUEST",
stream_enabled=True,
stream_view_type="NEW_AND_OLD_IMAGES",
attributes=[aws.dynamodb.TableAttributeArgs(
name="TestTableHashKey",
type="S",
)],
replicas=[
aws.dynamodb.TableReplicaArgs(
region_name="us-east-2",
),
aws.dynamodb.TableReplicaArgs(
region_name="us-west-2",
),
])using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.DynamoDB.Table("example", new()
{
Name = "example",
HashKey = "TestTableHashKey",
BillingMode = "PAY_PER_REQUEST",
StreamEnabled = true,
StreamViewType = "NEW_AND_OLD_IMAGES",
Attributes = new[]
{
new Aws.DynamoDB.Inputs.TableAttributeArgs
{
Name = "TestTableHashKey",
Type = "S",
},
},
Replicas = new[]
{
new Aws.DynamoDB.Inputs.TableReplicaArgs
{
RegionName = "us-east-2",
},
new Aws.DynamoDB.Inputs.TableReplicaArgs
{
RegionName = "us-west-2",
},
},
});
});package main
import (
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/dynamodb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := dynamodb.NewTable(ctx, "example", &dynamodb.TableArgs{
Name: pulumi.String("example"),
HashKey: pulumi.String("TestTableHashKey"),
BillingMode: pulumi.String("PAY_PER_REQUEST"),
StreamEnabled: pulumi.Bool(true),
StreamViewType: pulumi.String("NEW_AND_OLD_IMAGES"),
Attributes: dynamodb.TableAttributeArray{
&dynamodb.TableAttributeArgs{
Name: pulumi.String("TestTableHashKey"),
Type: pulumi.String("S"),
},
},
Replicas: dynamodb.TableReplicaTypeArray{
&dynamodb.TableReplicaTypeArgs{
RegionName: pulumi.String("us-east-2"),
},
&dynamodb.TableReplicaTypeArgs{
RegionName: pulumi.String("us-west-2"),
},
},
})
if err != nil {
return err
}
return nil
})
}package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.dynamodb.Table;
import com.pulumi.aws.dynamodb.TableArgs;
import com.pulumi.aws.dynamodb.inputs.TableAttributeArgs;
import com.pulumi.aws.dynamodb.inputs.TableReplicaArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Table("example", TableArgs.builder()
.name("example")
.hashKey("TestTableHashKey")
.billingMode("PAY_PER_REQUEST")
.streamEnabled(true)
.streamViewType("NEW_AND_OLD_IMAGES")
.attributes(TableAttributeArgs.builder()
.name("TestTableHashKey")
.type("S")
.build())
.replicas(
TableReplicaArgs.builder()
.regionName("us-east-2")
.build(),
TableReplicaArgs.builder()
.regionName("us-west-2")
.build())
.build());
}
}resources:
example:
type: aws:dynamodb:Table
properties:
name: example
hashKey: TestTableHashKey
billingMode: PAY_PER_REQUEST
streamEnabled: true
streamViewType: NEW_AND_OLD_IMAGES
attributes:
- name: TestTableHashKey
type: S
replicas:
- regionName: us-east-2
- regionName: us-west-2Replica Tagging
You can manage global table replicas' tags in various ways. This example shows using replica.*.propagate_tags for the first replica and the aws.dynamodb.Tag resource for the other.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const current = aws.getRegion({});
const alternate = aws.getRegion({});
const third = aws.getRegion({});
const example = new aws.dynamodb.Table("example", {
billingMode: "PAY_PER_REQUEST",
hashKey: "TestTableHashKey",
name: "example-13281",
streamEnabled: true,
streamViewType: "NEW_AND_OLD_IMAGES",
attributes: [{
name: "TestTableHashKey",
type: "S",
}],
replicas: [
{
regionName: alternate.then(alternate => alternate.name),
},
{
regionName: third.then(third => third.name),
propagateTags: true,
},
],
tags: {
Architect: "Eleanor",
Zone: "SW",
},
});
const exampleTag = new aws.dynamodb.Tag("example", {
resourceArn: pulumi.all([example.arn, current, alternate]).apply(([arn, current, alternate]) => std.replaceOutput({
text: arn,
search: current.name,
replace: alternate.name,
})).apply(invoke => invoke.result),
key: "Architect",
value: "Gigi",
});import pulumi
import pulumi_aws as aws
import pulumi_std as std
current = aws.get_region()
alternate = aws.get_region()
third = aws.get_region()
example = aws.dynamodb.Table("example",
billing_mode="PAY_PER_REQUEST",
hash_key="TestTableHashKey",
name="example-13281",
stream_enabled=True,
stream_view_type="NEW_AND_OLD_IMAGES",
attributes=[aws.dynamodb.TableAttributeArgs(
name="TestTableHashKey",
type="S",
)],
replicas=[
aws.dynamodb.TableReplicaArgs(
region_name=alternate.name,
),
aws.dynamodb.TableReplicaArgs(
region_name=third.name,
propagate_tags=True,
),
],
tags={
"Architect": "Eleanor",
"Zone": "SW",
})
example_tag = aws.dynamodb.Tag("example",
resource_arn=example.arn.apply(lambda arn: std.replace_output(text=arn,
search=current.name,
replace=alternate.name)).apply(lambda invoke: invoke.result),
key="Architect",
value="Gigi")using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var current = Aws.GetRegion.Invoke();
var alternate = Aws.GetRegion.Invoke();
var third = Aws.GetRegion.Invoke();
var example = new Aws.DynamoDB.Table("example", new()
{
BillingMode = "PAY_PER_REQUEST",
HashKey = "TestTableHashKey",
Name = "example-13281",
StreamEnabled = true,
StreamViewType = "NEW_AND_OLD_IMAGES",
Attributes = new[]
{
new Aws.DynamoDB.Inputs.TableAttributeArgs
{
Name = "TestTableHashKey",
Type = "S",
},
},
Replicas = new[]
{
new Aws.DynamoDB.Inputs.TableReplicaArgs
{
RegionName = alternate.Apply(getRegionResult => getRegionResult.Name),
},
new Aws.DynamoDB.Inputs.TableReplicaArgs
{
RegionName = third.Apply(getRegionResult => getRegionResult.Name),
PropagateTags = true,
},
},
Tags =
{
{ "Architect", "Eleanor" },
{ "Zone", "SW" },
},
});
var exampleTag = new Aws.DynamoDB.Tag("example", new()
{
ResourceArn = Output.Tuple(example.Arn, current, alternate).Apply(values =>
{
var arn = values.Item1;
var current = values.Item2;
var alternate = values.Item3;
return Std.Replace.Invoke(new()
{
Text = arn,
Search = current.Apply(getRegionResult => getRegionResult.Name),
Replace = alternate.Apply(getRegionResult => getRegionResult.Name),
});
}).Apply(invoke => invoke.Result),
Key = "Architect",
Value = "Gigi",
});
});package main
import (
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws"
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/dynamodb"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
current, err := aws.GetRegion(ctx, nil, nil)
if err != nil {
return err
}
alternate, err := aws.GetRegion(ctx, nil, nil)
if err != nil {
return err
}
third, err := aws.GetRegion(ctx, nil, nil)
if err != nil {
return err
}
example, err := dynamodb.NewTable(ctx, "example", &dynamodb.TableArgs{
BillingMode: pulumi.String("PAY_PER_REQUEST"),
HashKey: pulumi.String("TestTableHashKey"),
Name: pulumi.String("example-13281"),
StreamEnabled: pulumi.Bool(true),
StreamViewType: pulumi.String("NEW_AND_OLD_IMAGES"),
Attributes: dynamodb.TableAttributeArray{
&dynamodb.TableAttributeArgs{
Name: pulumi.String("TestTableHashKey"),
Type: pulumi.String("S"),
},
},
Replicas: dynamodb.TableReplicaTypeArray{
&dynamodb.TableReplicaTypeArgs{
RegionName: pulumi.String(alternate.Name),
},
&dynamodb.TableReplicaTypeArgs{
RegionName: pulumi.String(third.Name),
PropagateTags: pulumi.Bool(true),
},
},
Tags: pulumi.StringMap{
"Architect": pulumi.String("Eleanor"),
"Zone": pulumi.String("SW"),
},
})
if err != nil {
return err
}
_, err = dynamodb.NewTag(ctx, "example", &dynamodb.TagArgs{
ResourceArn: example.Arn.ApplyT(func(arn string) (std.ReplaceResult, error) {
return std.ReplaceOutput(ctx, std.ReplaceOutputArgs{
Text: arn,
Search: current.Name,
Replace: alternate.Name,
}, nil), nil
}).(std.ReplaceResultOutput).ApplyT(func(invoke std.ReplaceResult) (*string, error) {
return invoke.Result, nil
}).(pulumi.StringPtrOutput),
Key: pulumi.String("Architect"),
Value: pulumi.String("Gigi"),
})
if err != nil {
return err
}
return nil
})
}package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.dynamodb.Table;
import com.pulumi.aws.dynamodb.TableArgs;
import com.pulumi.aws.dynamodb.inputs.TableAttributeArgs;
import com.pulumi.aws.dynamodb.inputs.TableReplicaArgs;
import com.pulumi.aws.dynamodb.Tag;
import com.pulumi.aws.dynamodb.TagArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var current = AwsFunctions.getRegion();
final var alternate = AwsFunctions.getRegion();
final var third = AwsFunctions.getRegion();
var example = new Table("example", TableArgs.builder()
.billingMode("PAY_PER_REQUEST")
.hashKey("TestTableHashKey")
.name("example-13281")
.streamEnabled(true)
.streamViewType("NEW_AND_OLD_IMAGES")
.attributes(TableAttributeArgs.builder()
.name("TestTableHashKey")
.type("S")
.build())
.replicas(
TableReplicaArgs.builder()
.regionName(alternate.applyValue(getRegionResult -> getRegionResult.name()))
.build(),
TableReplicaArgs.builder()
.regionName(third.applyValue(getRegionResult -> getRegionResult.name()))
.propagateTags(true)
.build())
.tags(Map.ofEntries(
Map.entry("Architect", "Eleanor"),
Map.entry("Zone", "SW")
))
.build());
var exampleTag = new Tag("exampleTag", TagArgs.builder()
.resourceArn(example.arn().applyValue(arn -> StdFunctions.replace()).applyValue(invoke -> invoke.result()))
.key("Architect")
.value("Gigi")
.build());
}
}resources:
example:
type: aws:dynamodb:Table
properties:
billingMode: PAY_PER_REQUEST
hashKey: TestTableHashKey
name: example-13281
streamEnabled: true
streamViewType: NEW_AND_OLD_IMAGES
attributes:
- name: TestTableHashKey
type: S
replicas:
- regionName: ${alternate.name}
- regionName: ${third.name}
propagateTags: true
tags:
Architect: Eleanor
Zone: SW
exampleTag:
type: aws:dynamodb:Tag
name: example
properties:
resourceArn:
fn::invoke:
Function: std:replace
Arguments:
text: ${example.arn}
search: ${current.name}
replace: ${alternate.name}
Return: result
key: Architect
value: Gigi
variables:
current:
fn::invoke:
Function: aws:getRegion
Arguments: {}
alternate:
fn::invoke:
Function: aws:getRegion
Arguments: {}
third:
fn::invoke:
Function: aws:getRegion
Arguments: {}Import
Using pulumi import, import DynamoDB tables using the name. For example:
$ pulumi import aws:dynamodb/table:Table basic-dynamodb-table GameScoresProperties
Configuration block(s) with DynamoDB Global Tables V2 (version 2019.11.21) replication configurations. See below.
Timestamp, in ISO 8601 format, for this stream. Note that this timestamp is not a unique identifier for the stream on its own. However, the combination of AWS customer ID, table name and this field is guaranteed to be unique. It can be used for creating CloudWatch Alarms. Only available when stream_enabled = true.