Home Blog Tutorials Running DynamoDB Locally: Complete Guide with Docker and Java Options
Tutorials

Running DynamoDB Locally: Complete Guide with Docker and Java Options

March 9, 2025 By Alex Mitchell 8 min read
Running DynamoDB Locally: Complete Guide with Docker and Java Options

Developing applications that use Amazon DynamoDB often requires frequent testing and iteration. Running DynamoDB locally provides a cost-effective, internet-independent environment for development and testing, saving both time and money.

This guide covers everything you need to know about running DynamoDB locally, including setup with Docker and the downloadable JAR, connecting your applications, and important limitations to keep in mind.

What is DynamoDB Local?

DynamoDB Local is a downloadable version of Amazon DynamoDB that lets you develop and test applications using a DynamoDB-compatible database on your computer, without accessing the DynamoDB web service. It’s a perfect solution for:

  • Developing and testing without incurring AWS costs
  • Working offline or in environments with limited internet access
  • Running automated tests in CI/CD pipelines
  • Learning DynamoDB without AWS account requirements

DynamoDB Local provides most of the functionality of the AWS DynamoDB service, with a few important differences we’ll cover later in this guide.

Dynomate: Modern DynamoDB GUI Client

Built for real developer workflows with AWS profile integration, multi-session support, and team collaboration.

AWS SSO support & multi-region browsing
Script-like operations with data chaining
Git-friendly local storage for team sharing

Running DynamoDB Local with Docker

Using Docker is the simplest way to get started with DynamoDB Local. It requires minimal setup and works consistently across different operating systems and environments.

Prerequisites

  • Docker installed on your system

Step 1: Pull the Official DynamoDB Local Image

docker pull amazon/dynamodb-local

Step 2: Run the Container

For basic usage:

docker run -p 8000:8000 amazon/dynamodb-local

You should see output indicating that DynamoDB Local is running on port 8000.

Docker with Persistent Data

By default, data in DynamoDB Local is lost when the container stops. To persist your data between sessions:

# Create a directory for DynamoDB data
mkdir -p ~/dynamodb-local-data

# Run with a volume mount
docker run -p 8000:8000 -v ~/dynamodb-local-data:/home/dynamodblocal/data amazon/dynamodb-local -jar DynamoDBLocal.jar -dbPath /home/dynamodblocal/data

Docker Compose Example

For more complex setups, you might prefer using Docker Compose:

# docker-compose.yml
version: '3.8'
services:
  dynamodb-local:
    image: amazon/dynamodb-local
    container_name: dynamodb-local
    ports:
      - "8000:8000"
    volumes:
      - ./dynamodb-data:/home/dynamodblocal/data
    command: "-jar DynamoDBLocal.jar -dbPath /home/dynamodblocal/data"
    working_dir: /home/dynamodblocal

Start it with:

docker-compose up -d

Running DynamoDB Local with Java JAR

If you prefer not to use Docker, you can download and run the DynamoDB Local JAR file directly.

Prerequisites

  • Java Runtime Environment (JRE) version 8.x or newer

Step 1: Download the DynamoDB Local JAR

Download the latest version from the AWS DynamoDB Local download page.

curl -O https://d1ni2b6xgvw0s0.cloudfront.net/v2.x/dynamodb_local_latest.tar.gz
tar -xzf dynamodb_local_latest.tar.gz
cd dynamodb_local_latest

Step 2: Run the JAR

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

Additional command-line options:

  • -port <port-number>: Use a specific port (default is 8000)
  • -dbPath <path>: Specify a directory for database files
  • -sharedDb: Use a single database file instead of separate files per credential/region
  • -inMemory: Run in memory (data will be lost when stopped)
  • -optimizeDbBeforeStartup: Run offline optimization before startup

Example with custom port and path:

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -port 8080 -dbPath /path/to/data/directory -sharedDb

Connecting to DynamoDB Local

Once DynamoDB Local is running, you’ll need to configure your applications and tools to connect to it instead of the AWS DynamoDB service.

Using AWS CLI

Configure the AWS CLI to use the local endpoint:

# List tables in local DynamoDB
aws dynamodb list-tables --endpoint-url http://localhost:8000

# Create a table
aws dynamodb create-table \
    --table-name Users \
    --attribute-definitions AttributeName=UserId,AttributeType=S \
    --key-schema AttributeName=UserId,KeyType=HASH \
    --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
    --endpoint-url http://localhost:8000

# Put an item
aws dynamodb put-item \
    --table-name Users \
    --item '{"UserId": {"S": "user123"}, "Name": {"S": "John Doe"}}' \
    --endpoint-url http://localhost:8000

# Query the table
aws dynamodb scan --table-name Users --endpoint-url http://localhost:8000

Using Python (Boto3)

import boto3

# Connect to local DynamoDB
dynamodb = boto3.resource('dynamodb', endpoint_url='http://localhost:8000')

# Create a table
table = dynamodb.create_table(
    TableName='Users',
    KeySchema=[
        {
            'AttributeName': 'UserId',
            'KeyType': 'HASH'
        }
    ],
    AttributeDefinitions=[
        {
            'AttributeName': 'UserId',
            'AttributeType': 'S'
        }
    ],
    ProvisionedThroughput={
        'ReadCapacityUnits': 5,
        'WriteCapacityUnits': 5
    }
)

# Wait until the table exists
table.meta.client.get_waiter('table_exists').wait(TableName='Users')

# Add an item
table.put_item(
   Item={
        'UserId': 'user123',
        'Name': 'John Doe',
        'Email': 'john@example.com'
    }
)

# Query the table
response = table.scan()
for item in response['Items']:
    print(item)

Using Node.js (AWS SDK v3)

const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const {
  DynamoDBDocumentClient,
  CreateTableCommand,
  PutCommand,
  ScanCommand
} = require("@aws-sdk/lib-dynamodb");

// Create DynamoDB client
const client = new DynamoDBClient({
  region: "local",
  endpoint: "http://localhost:8000"
});

const docClient = DynamoDBDocumentClient.from(client);

async function main() {
  // Create a table
  try {
    await docClient.send(new CreateTableCommand({
      TableName: "Users",
      KeySchema: [
        { AttributeName: "UserId", KeyType: "HASH" }
      ],
      AttributeDefinitions: [
        { AttributeName: "UserId", AttributeType: "S" }
      ],
      ProvisionedThroughput: {
        ReadCapacityUnits: 5,
        WriteCapacityUnits: 5
      }
    }));
    console.log("Table created successfully.");
  } catch (err) {
    console.error("Error creating table:", err);
  }

  // Add an item
  try {
    await docClient.send(new PutCommand({
      TableName: "Users",
      Item: {
        UserId: "user123",
        Name: "John Doe",
        Email: "john@example.com"
      }
    }));
    console.log("Item added successfully.");
  } catch (err) {
    console.error("Error adding item:", err);
  }

  // Query the table
  try {
    const { Items } = await docClient.send(new ScanCommand({
      TableName: "Users"
    }));
    console.log("Scan results:", Items);
  } catch (err) {
    console.error("Error scanning table:", err);
  }
}

main();

Using Java (AWS SDK v2)

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

public class DynamoDBLocalExample {
    public static void main(String[] args) {
        // Set up DynamoDB client
        DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
                .endpointOverride(URI.create("http://localhost:8000"))
                // The region is required, but irrelevant for local DynamoDB
                .region(Region.US_EAST_1)
                // Credentials are required but not actually checked for local DynamoDB
                .credentialsProvider(StaticCredentialsProvider.create(
                        AwsBasicCredentials.create("dummy", "credential")))
                .build();

        // Create table
        try {
            CreateTableRequest request = CreateTableRequest.builder()
                    .tableName("Users")
                    .keySchema(KeySchemaElement.builder()
                            .attributeName("UserId")
                            .keyType(KeyType.HASH)
                            .build())
                    .attributeDefinitions(AttributeDefinition.builder()
                            .attributeName("UserId")
                            .attributeType(ScalarAttributeType.S)
                            .build())
                    .provisionedThroughput(ProvisionedThroughput.builder()
                            .readCapacityUnits(5L)
                            .writeCapacityUnits(5L)
                            .build())
                    .build();

            dynamoDbClient.createTable(request);
            System.out.println("Table created successfully");
        } catch (DynamoDbException e) {
            System.err.println("Error creating table: " + e.getMessage());
        }

        // Add item
        try {
            Map<String, AttributeValue> item = new HashMap<>();
            item.put("UserId", AttributeValue.builder().s("user123").build());
            item.put("Name", AttributeValue.builder().s("John Doe").build());
            item.put("Email", AttributeValue.builder().s("john@example.com").build());

            PutItemRequest request = PutItemRequest.builder()
                    .tableName("Users")
                    .item(item)
                    .build();

            dynamoDbClient.putItem(request);
            System.out.println("Item added successfully");
        } catch (DynamoDbException e) {
            System.err.println("Error adding item: " + e.getMessage());
        }

        // Scan table
        try {
            ScanRequest scanRequest = ScanRequest.builder()
                    .tableName("Users")
                    .build();

            ScanResponse response = dynamoDbClient.scan(scanRequest);
            response.items().forEach(item -> {
                System.out.println("Item: " + item);
            });
        } catch (DynamoDbException e) {
            System.err.println("Error scanning table: " + e.getMessage());
        }
    }
}

Testing Your Connection

To verify that DynamoDB Local is running correctly:

aws dynamodb list-tables --endpoint-url http://localhost:8000

If DynamoDB Local is running, this command should return a JSON response with an empty list of table names (if you haven’t created any tables yet).

Familiar with these Dynamodb Challenges ?

  • Writing one‑off scripts for simple DynamoDB operations
  • Constantly switching between AWS profiles and regions
  • Sharing and managing database operations with your team

You should try Dynomate GUI Client for DynamoDB

  • Create collections of operations that work together like scripts
  • Seamless integration with AWS SSO and profile switching
  • Local‑first design with Git‑friendly sharing for team collaboration

Usage Tips for DynamoDB Local

Throughput Considerations

When using DynamoDB Local, throughput settings (ReadCapacityUnits and WriteCapacityUnits) are required but not enforced. You can specify any values, and your operations won’t be throttled.

Data Persistence

  • In-memory mode: Data is lost when DynamoDB Local stops
  • File mode: Data is saved to disk and persists between restarts
  • Shared database mode: All clients use the same database file instead of separate ones per AWS credentials/region

Working with Multiple Applications

You can share a single DynamoDB Local instance among multiple applications by using the -sharedDb flag. This simplifies testing across different components.

Resetting the Database

If you need to start fresh, you can:

  • Delete the data files (if using file mode)
  • Stop and restart the container with the -inMemory flag
  • Use the AWS CLI to delete and recreate your tables:
# Delete all tables
for table in $(aws dynamodb list-tables --endpoint-url http://localhost:8000 --query 'TableNames' --output text); do
    aws dynamodb delete-table --table-name $table --endpoint-url http://localhost:8000
done

Limitations of DynamoDB Local

While DynamoDB Local is excellent for development and testing, it has some important limitations compared to the AWS DynamoDB service:

Features Not Supported

  • DynamoDB Streams: The change data capture feature is not fully supported
  • Global Tables: Multi-region replication is not available
  • Time to Live (TTL): While the API is present, actual automatic expiration doesn’t occur
  • On-demand capacity mode: While the API accepts this setting, it doesn’t function exactly as in AWS
  • AWS Identity and Access Management (IAM): Authentication and authorization are minimal
  • AWS CloudWatch integration: Metrics are not published
  • Some transactional APIs: May have partial implementation

Performance Differences

DynamoDB Local performance depends on your local hardware and isn’t representative of the AWS service’s performance. Don’t use it for performance benchmarking.

Consistency Model

While DynamoDB Local supports the ConsistentRead parameter, its actual consistency behavior might differ from the AWS service since it’s a single-node implementation.

Using DynamoDB Local in CI/CD Pipelines

DynamoDB Local is perfect for integration testing in continuous integration environments. Here’s a simple example for GitHub Actions:

# .github/workflows/test.yml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      dynamodb:
        image: amazon/dynamodb-local
        ports:
          - 8000:8000

    steps:
      - uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test
        env:
          DYNAMODB_ENDPOINT: http://localhost:8000

Best Practices

Local Development Workflow

  1. Use Docker Compose to start both your application and DynamoDB Local together
  2. Create a startup script that initializes tables and sample data
  3. Use environment variables to switch between local and AWS endpoints
  4. Consider using .aws/credentials profiles for different environments

Data and Schema Management

  1. Version control your table schemas and initialization scripts
  2. Create seed data for testing different scenarios
  3. Use the same table structure locally as in production

Testing

  1. Reset the database before each test suite
  2. Run tests in parallel using different table names or databases
  3. Simulate error conditions by intercepting SDK calls

Switching from Dynobase? Try Dynomate

Developers are switching to Dynomate for these key advantages:

Better Multi-Profile Support

  • Native AWS SSO integration
  • Seamless profile switching
  • Multiple accounts in a single view

Developer-Focused Workflow

  • Script-like operation collections
  • Chain data between operations
  • Full AWS API logging for debugging

Team Collaboration

  • Git-friendly collection sharing
  • No account required for installation
  • Local-first data storage for privacy

Privacy & Security

  • No account creation required
  • 100% local data storage
  • No telemetry or usage tracking

Conclusion

Running DynamoDB locally provides significant advantages for development and testing, including cost savings, offline capabilities, and faster iteration cycles. Whether you choose Docker or the JAR file approach, DynamoDB Local offers a convenient way to work with a DynamoDB-compatible database without accessing AWS.

Remember to account for the limitations when designing your test strategies, particularly around features that aren’t fully supported in the local version.

Looking for a more powerful way to interact with DynamoDB, both locally and in the cloud? Dynomate provides an intuitive GUI that connects to both DynamoDB Local and AWS DynamoDB, making it easier to visualize your data, design tables, and build queries without writing code.

For more information about working with DynamoDB, check out our related articles:

Share this article:

Related Articles