DynamoDB Local runs entirely in memory, making it surprisingly slow for any operation beyond basic key-value lookups.
Let’s get DynamoDB Local up and running so you can iterate quickly on your application without hitting the actual AWS service.
First, you need to download the DynamoDB Local JAR file. You can find the latest version on the AWS documentation page. As of this writing, the direct download link for the standalone executable JAR is:
https://dynamodb-local.s3-website-us-west-2.amazonaws.com/dynamodb_local_latest
Once downloaded, you can start it with a simple Java command. It’s best to run this in a terminal window that you’ll keep open during your development session.
java -Djava.library.path=./DynamoDBLocal_lib -jar dynamodb_local.jar -sharedDb
Let’s break this down:
java -Djava.library.path=./DynamoDBLocal_lib: This tells Java where to find the native libraries required by DynamoDB Local. Make sure you extract the downloaded zip file into a directory namedDynamoDBLocal_libin the same location where you’re running this command.-jar dynamodb_local.jar: This executes the downloaded JAR file.-sharedDb: This is crucial for development. Without it, DynamoDB Local creates a new in-memory database every time it starts, wiping out any tables you might have created. With-sharedDb, it persists data in a file namedshared-local-instance.dbin the current directory, allowing you to restart DynamoDB Local and retain your table structure and data.
When it starts, you’ll see output indicating that DynamoDB Local is listening on a specific port. By default, this is 8000.
...
DynamoDB Local running at http://localhost:8000
...
Your application’s AWS SDK needs to be configured to point to this local endpoint instead of the global AWS endpoint. How you do this depends on your SDK and programming language.
For the AWS SDK for Java V2, you’ll configure your DynamoDbClient like this:
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.awssdk.services.dynamodb.model.TableStatus;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
public class DynamoDBLocalExample {
public static void main(String[] args) {
// Configure the DynamoDB client to point to local
DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
.endpointOverride(URI.create("http://localhost:8000")) // Local endpoint
.region(Region.US_EAST_1) // Region doesn't matter for local, but required
.build();
String tableName = "MyLocalTestTable";
// Create a table
try {
dynamoDbClient.createTable(CreateTableRequest.builder()
.tableName(tableName)
.attributeDefinitions(
software.amazon.awssdk.services.dynamodb.model.AttributeDefinition.builder()
.attributeName("id")
.attributeType("S")
.build())
.keySchema(
software.amazon.awssdk.services.dynamodb.model.KeySchemaElement.builder()
.attributeName("id")
.keyType("HASH")
.build())
.provisionedThroughput(software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput.builder()
.readCapacityUnits(5L)
.writeCapacityUnits(5L)
.build())
.build());
System.out.println("Table '" + tableName + "' created.");
} catch (Exception e) {
// Table might already exist if -sharedDb is used and not deleted
System.out.println("Could not create table (might already exist): " + e.getMessage());
}
// Wait for table to be active (optional but good practice)
dynamoDbClient.waiter().waitUntilTableExists(
software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest.builder()
.tableName(tableName)
.build());
System.out.println("Table '" + tableName + "' is active.");
// Put an item
Map<String, AttributeValue> item = new HashMap<>();
item.put("id", AttributeValue.builder().s("user123").build());
item.put("name", AttributeValue.builder().s("Alice").build());
PutItemRequest putItemRequest = PutItemRequest.builder()
.tableName(tableName)
.item(item)
.build();
dynamoDbClient.putItem(putItemRequest);
System.out.println("Item put into '" + tableName + "'.");
// Get an item
Map<String, AttributeValue> key = new HashMap<>();
key.put("id", AttributeValue.builder().s("user123").build());
GetItemRequest getItemRequest = GetItemRequest.builder()
.tableName(tableName)
.key(key)
.build();
Map<String, AttributeValue> retrievedItem = dynamoDbClient.getItem(getItemRequest).item();
System.out.println("Retrieved item: " + retrievedItem);
// Scan items
ScanRequest scanRequest = ScanRequest.builder()
.tableName(tableName)
.build();
dynamoDbClient.scan(scanRequest).items().forEach(System.out::println);
// Clean up (optional)
// dynamoDbClient.deleteTable(DeleteTableRequest.builder().tableName(tableName).build());
// System.out.println("Table '" + tableName + "' deleted.");
dynamoDbClient.close();
}
}
For the AWS SDK for Python (Boto3), you’d initialize your client like this:
import boto3
# Configure the DynamoDB client to point to local
dynamodb = boto3.resource(
'dynamodb',
endpoint_url="http://localhost:8000",
region_name="us-east-1", # Region doesn't matter for local, but required
aws_access_key_id='DUMMYKEY', # Dummy credentials for local
aws_secret_access_key='DUMMYSECRET' # Dummy credentials for local
)
table_name = 'MyLocalTestTable'
# Create a table (if it doesn't exist)
try:
table = dynamodb.create_table(
TableName=table_name,
KeySchema=[
{
'AttributeName': 'id',
'KeyType': 'HASH'
}
],
AttributeDefinitions=[
{
'AttributeName': 'id',
'AttributeType': 'S'
}
],
ProvisionedThroughput={
'ReadCapacityUnits': 5,
'WriteCapacityUnits': 5
}
)
print(f"Table '{table_name}' created.")
table.meta.client.get_waiter('table_exists').wait(TableName=table_name)
print(f"Table '{table_name}' is active.")
except Exception as e:
print(f"Could not create table (might already exist): {e}")
table = dynamodb.Table(table_name) # Get existing table object
# Put an item
table.put_item(
Item={
'id': 'user123',
'name': 'Alice'
}
)
print("Item put into table.")
# Get an item
response = table.get_item(
Key={
'id': 'user123'
}
)
print(f"Retrieved item: {response['Item']}")
# Scan items
response = table.scan()
print("Scanned items:")
for item in response['Items']:
print(item)
# Clean up (optional)
# table.delete()
# print(f"Table '{table_name}' deleted.")
The real power here is the ability to rapidly test changes without incurring costs or waiting for deployments to actual AWS. You can spin up DynamoDB Local, make schema changes, write data, run your tests, and then tear it all down.
When you’re done, simply stop the java process in your terminal (usually by pressing Ctrl+C). If you used the -sharedDb flag, the shared-local-instance.db file will be present, and your tables will persist for the next run. If you want a completely fresh start, delete this file.
The next hurdle you’ll likely face is understanding how to simulate specific DynamoDB behaviors like throttling or network latency in your local environment.