You do not need a live AWS table to test DynamoDB code. DynamoDB Local is the same engine packaged to run on your machine, and moto mocks the API in-process for Python. Both let tests run offline, for free, in milliseconds, and in CI.
This page shows how to point either SDK at DynamoDB Local, how to mock with moto, and how to structure tests so each starts from a clean table. The only change to your application code is the client's endpoint.
# --- Python (boto3) ---import boto3# Point the SDK at DynamoDB Local. Credentials can be dummy values.ddb = boto3.resource( "dynamodb", endpoint_url="http://localhost:8000", region_name="us-east-1", aws_access_key_id="local", aws_secret_access_key="local",)
// --- TypeScript (AWS SDK v3) ---import { DynamoDBClient } from "@aws-sdk/client-dynamodb";import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";// Point the SDK at DynamoDB Local. Credentials can be dummy values.const doc = DynamoDBDocumentClient.from(new DynamoDBClient({ endpoint: "http://localhost:8000", region: "us-east-1", credentials: { accessKeyId: "local", secretAccessKey: "local" },}));
When to reach for this:
Unit and integration tests that must not touch real AWS or cost money.
CI pipelines that need a deterministic, disposable table per run.
Local development while offline or before provisioning cloud resources.
Verifying key design, queries, and conditional writes quickly.
Run DynamoDB Local in Docker, then write a test that creates a table in a fixture, exercises put/query, and tears it down. The application code under test is unchanged - only the endpoint differs.
First, start DynamoDB Local (non-SDK, so a plain fence):
# DynamoDB Local in Docker, in-memory, on port 8000.docker run -p 8000:8000 amazon/dynamodb-local -jar DynamoDBLocal.jar -inMemory
Now a test that stands up a table, uses it, and cleans up.
DynamoDB Local is a real, downloadable DynamoDB implementation (Java) that AWS ships as a Docker image (amazon/dynamodb-local) or a JAR. It speaks the actual DynamoDB API, so queries, indexes, transactions, and condition expressions behave as they do in the cloud. Run it -inMemory for disposable test data, or with a shared DB file to persist across restarts. It works with any SDK because it is just an endpoint.
moto is a Python library that patches boto3 in-process - no container, no network. Decorate a test with @mock_aws and boto3 calls hit an in-memory fake. It is the fastest option for pure-Python unit tests, though it reimplements the API and can lag real behavior in edge cases.
// --- TypeScript (AWS SDK v3) ---// No first-party moto for JS: use DynamoDB Local (above), or unit-test the// business logic with aws-sdk-client-mock to stub the DynamoDB client.import { mockClient } from "aws-sdk-client-mock";import { DynamoDBDocumentClient, GetCommand } from "@aws-sdk/lib-dynamodb";const ddbMock = mockClient(DynamoDBDocumentClient);ddbMock.on(GetCommand).resolves({ Item: { id: "a", n: 1 } });
Unit tests: mock the client (aws-sdk-client-mock in TS) or use moto in Python to test business logic and error handling in isolation - fast, no engine.
Integration tests: run against DynamoDB Local to verify real key conditions, indexes, transactions, and pagination.
Contract/smoke tests: a small suite against a real throwaway AWS table (or a per-PR table) to catch what local tools approximate.
Give each test its own state: create and delete a table per test, use a unique table name per test file, or prefix keys per test so parallel runs do not collide. In-memory DynamoDB Local plus a per-test table is the simplest fully isolated setup.
Trusting local behavior for capacity and IAM. DynamoDB Local ignores provisioned throughput limits and does not enforce IAM. Fix: validate capacity and permissions against real AWS.
moto drifting from real behavior. moto reimplements the API and can miss edge cases. Fix: back critical paths with DynamoDB Local or a real table.
Shared state across tests. A persisted local DB leaks data between tests. Fix: run -inMemory and create/drop a table per test.
Forgetting dummy credentials. Some SDK setups still expect credentials to resolve. Fix: pass dummy static credentials for local endpoints.
Region mismatch with a DB file. DynamoDB Local scopes shared files by region and credentials by default. Fix: keep region/credentials consistent, or use -sharedDb.
Testing GSIs without creating them. Local honors only indexes you define. Fix: create the same GSIs/LSIs in your test table as in production.
A downloadable build of DynamoDB from AWS - available as the amazon/dynamodb-local Docker image or a JAR - that runs on your machine and speaks the real DynamoDB API, so tests run offline and free.
How do I point my SDK at it?
Set the client endpoint to http://localhost:8000 (endpoint_url in boto3, endpoint in SDK v3), a region, and dummy credentials. No other application code changes - your data-access functions stay the same.
What is the difference between DynamoDB Local and moto?
DynamoDB Local is the real engine run locally and works with any SDK over an endpoint. moto is a Python library that patches boto3 in-process with an in-memory fake - faster, but a reimplementation that can differ from real behavior.
Is there a moto for TypeScript?
Not a first-party equivalent. For TS, use DynamoDB Local for integration tests, and aws-sdk-client-mock to stub the client for pure unit tests of the logic around your calls.
How do I keep tests isolated?
Create and delete a table per test (or per file), use unique table names, or prefix keys per test. Running DynamoDB Local with -inMemory plus a per-test table gives clean, fully isolated state.
Does DynamoDB Local enforce capacity limits?
No. It ignores provisioned throughput and never throttles, so it cannot validate capacity planning or auto scaling. Confirm those against a real AWS table.
Does it enforce IAM permissions?
No. DynamoDB Local does not evaluate IAM policies, so authorization bugs will not surface locally. Test permissions against real AWS with the actual roles.
Can I persist data between runs?
Yes. Omit -inMemory and use a shared DB file (-sharedDb) to keep data across restarts. For tests, in-memory mode is usually better because it starts clean every time.
Do my indexes work locally?
Yes, if you create them. DynamoDB Local honors the GSIs and LSIs you define on the table, so mirror your production indexes in the test table to exercise index queries.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+). Y29kZWd1aWRlcy5pb3xjZ2lvMTEyN3wyMDI2MDc
Reviewed by Chris St. John·Last updated Jul 23, 2026