DynamoDB Global Tables are designed to replicate data across multiple AWS regions automatically, but the initial setup and understanding can be a bit nuanced. The surprising truth is that Global Tables don’t just copy data; they maintain a conflict-free replicated data type (CRDT) state for each item, resolving concurrent writes at the item level before replication.
Let’s see this in action. Imagine you have a UserSessions table. We want users to seamlessly maintain their session state even if they are directed to a different region due to latency or failover.
Here’s a simplified UserSessions table definition (in us-east-1):
{
"TableName": "UserSessions",
"KeySchema": [
{
"AttributeName": "session_id",
"KeyType": "HASH"
}
],
"AttributeDefinitions": [
{
"AttributeName": "session_id",
"AttributeType": "S"
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
},
"StreamSpecification": {
"StreamEnabled": true,
"StreamViewType": "NEW_AND_OLD_IMAGES"
}
}
Now, let’s create a replica in eu-west-1:
aws dynamodb create-global-table --global-table-name UserSessions --replication-group RegionName=us-east-1,RegionName=eu-west-1
This command doesn’t just spin up a new DynamoDB table; it orchestrates the creation of a new UserSessions table in eu-west-1 and establishes a bidirectional replication stream between the two. Any write to UserSessions in us-east-1 will be replicated to eu-west-1, and vice-versa.
The magic happens because DynamoDB uses a multi-master replication model. When you update an item, say session_id: "abc-123", in both regions concurrently, DynamoDB doesn’t just pick one write to keep and discard the other. Instead, it uses a "last writer wins" approach based on the timestamp of the write operation at the source region. This timestamp is globally unique and ensures that the replica receiving the update knows which version to apply.
Consider this scenario:
- Write 1 (us-east-1): User
session_id: "abc-123"updates theirlast_activity_timeto1678886400. - Write 2 (eu-west-1): Simultaneously, the same user updates their
last_activity_timeto1678886401.
DynamoDB processes these writes. The write in eu-west-1 has a slightly later timestamp. When the replication streams sync up, DynamoDB will detect this conflict. The item in us-east-1 will be updated to reflect the version from eu-west-1 (with last_activity_time: 1678886401), and the item in eu-west-1 will remain as it is. The data is now consistent across both regions.
The key levers you control are:
- Region Replication: Adding or removing regions from the
ReplicationGroupin yourGlobalTabledefinition. - Capacity Provisioning: Each regional replica needs its own provisioned throughput. You manage this independently per region. If you have high write traffic, you’ll need to ensure sufficient write capacity in each region to handle both local writes and incoming replicated writes.
- Conflict Resolution: While "last writer wins" is the default and only mechanism, understanding that it operates at the item level based on the source region’s timestamp is crucial for debugging and application design.
What most people don’t realize is how DynamoDB handles deleting items in a multi-region setup. When an item is deleted in one region, DynamoDB doesn’t immediately remove it from other regions. Instead, it writes a special "tombstone" record. This tombstone record is then replicated to all other regions. Only after a certain period (typically 14 days, but this can be influenced by the TTL on the item) will the item be permanently removed from all replicas. This ensures that if a delete operation is lost in transit, the item will eventually reappear and can then be correctly deleted once the tombstone replicates.
The next challenge you’ll likely encounter is optimizing read performance by strategically routing application traffic to the nearest replica.