How to create a global DynamoDB table in AWS
In November 2017 AWS announced a DynamoDB feature enabling transparent asynchronous replication of table data between any number of regions. This can be useful in a distributed application and for failover between AWS regions. Data can be written and read in each of the regions with replicas of the table.
This is the missing guide for creating global tables with the AWS Java SDK. You’ll need a recent version of the SDK as older releases lack the classes for dealing with global DynamoDB tables.
The steps for creating a global DynamoDB table:
-
Create a DynamoDB client for each of the AWS regions where you need to have replicas.
-
In each region create the desired DynamoDB table, with the usual parameters, but also enable the table for streaming and specify what is to be streamed - both the new and old images of the item (
StreamViewType.NEW_AND_OLD_IMAGES
). -
Finally, run a request to turn all those created tables into a single global one, by putting them into a replication group. This request can run in any AWS region.
Here is a Java example:
import java.util.Collection;
import java.util.LinkedList;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.*;
import org.junit.Test;
public class AWSGlobalTableTest {
private static final String EU_CENTRAL_1 = "eu-central-1";
private static final String US_EAST_1 = "us-east-1";
private static final String TABLE_NAME = "my_global_table";
@Test
public void createGlobalTable() {
// Create a client for each of the regions with table replicas
AmazonDynamoDB client1 = AmazonDynamoDBClientBuilder
.standard()
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.withRegion(EU_CENTRAL_1)
.build();
AmazonDynamoDB client2 = AmazonDynamoDBClientBuilder
.standard()
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.withRegion(US_EAST_1)
.build();
// The table spec, must be enabled for streaming
Collection<KeySchemaElement> keyAttrs = new LinkedList<>();
keyAttrs.add(new KeySchemaElement("id", KeyType.HASH));
Collection<AttributeDefinition> attrs = new LinkedList<>();
attrs.add(new AttributeDefinition("id", ScalarAttributeType.S));
CreateTableRequest createTableRequest = new CreateTableRequest()
.withTableName(TABLE_NAME)
.withKeySchema(keyAttrs)
.withAttributeDefinitions(attrs)
.withStreamSpecification(
new StreamSpecification()
.withStreamEnabled(true)
.withStreamViewType(StreamViewType.NEW_AND_OLD_IMAGES))
.withProvisionedThroughput(new ProvisionedThroughput(1L, 1L));
// Create the table in each region
client1.createTable(createTableRequest);
client2.createTable(createTableRequest);
// The global table request can be executed in any of the regions
CreateGlobalTableResult createGlobalTableResult = client1.createGlobalTable(
new CreateGlobalTableRequest()
.withGlobalTableName(TABLE_NAME)
.withReplicationGroup(
new Replica().withRegionName(EU_CENTRAL_1),
new Replica().withRegionName(US_EAST_1)));
}
}
Global tables will be automatically provisioned with three extra attributes - the timestamp of the item update, in which region that happened and a flag whether the item is pending deletion.
The Connect2id server for IdP, SSO and API security is going to support global DynamoDB tables in the next 7.6 release. This will make it possible to run a global IdP operation, with the ability to service clients and applications close to their deployment location for minimal latency.