Migrate MongoDB to DynamoDB: Plan, Import, and Cut Over

Written by Charlie Fish
Last updated: October 23rd, 2026
Migrating from MongoDB to DynamoDB requires redesigning queries and keys, converting BSON values, and moving data with a controlled cutover. Use AWS DMS for supported source deployments that need ongoing change capture, or transform an export and import it through S3 when a bulk load into a new table fits. Copying documents alone does not migrate MongoDB indexes, aggregation pipelines, or application behavior.
Outline
Keep the original migration sequence, but give each stage a measurable exit condition:
- Study: identify which MongoDB features the application actually uses.
- Plan: map every required read and write to a DynamoDB key, index, or transaction.
- Code: implement type conversion and the new application access layer.
- Migrate: backfill records and capture changes, or stop writes for an offline migration.
- Monitor: reconcile data and compare application behavior before switching traffic.
- Cleanup: retire the old path only after the rollback window and recovery checks pass.
The DynamoDB vs MongoDB comparison covers the product tradeoffs. A migration is justified when the resulting design fits the application, not merely because both products accept documents.
Server
MongoDB can be self-managed or hosted through MongoDB Atlas. Atlas already handles substantial infrastructure work, so moving to DynamoDB is not necessarily a move from unmanaged to managed storage. It changes APIs, identity, capacity planning, and operational responsibilities.
DynamoDB's production service runs on AWS. Choose the Region, IAM permissions, capacity mode, backup settings, and deployment process before loading data. On-demand capacity is useful when measuring a new workload, but hot keys and throughput quotas still matter.
Use DynamoDB Local for fast application tests. Also test against a real AWS table before cutover because local behavior does not reproduce every managed-service limit, identity rule, or failure mode.
Items and BSON type mapping
MongoDB stores BSON, not plain JSON. Its type system includes ObjectId, Date, Decimal128, binary subtypes, and other values that need an explicit destination representation. DynamoDB supports strings, numbers, binary values, booleans, nulls, lists, maps, and sets, but has no native BSON ObjectId or date type.
| MongoDB value or feature | DynamoDB migration decision |
|---|---|
| ObjectId | Convert to a stable string, and preserve the original ID for reconciliation |
| Date | Use a UTC ISO 8601 string or numeric epoch value with documented units |
| Decimal128 / large integers | Preserve precision; reject unsupported ranges instead of silently rounding |
| Binary / UUID | Preserve bytes and document subtype or UUID representation where necessary |
| Embedded documents and arrays | Map to maps/lists, split into related items, or externalize large payloads |
| Unique index | Design a uniqueness guard, often with conditional writes and a transaction |
| TTL index | Convert to a numeric epoch-seconds attribute and enable TTL separately |
| Geospatial index or aggregation | Redesign the query, materialize a result, or retain a suitable query system |
DynamoDB's item limit is 400 KB, including names and values, and numbers have up to 38 digits of precision. MongoDB allows 16 MiB BSON documents. Check the DynamoDB constraints and MongoDB limits before a bulk run. A document fitting MongoDB may require several DynamoDB items or an S3 object plus metadata.
Do not flatten all missing values into nulls, or all numeric values into strings. Those choices affect filters, indexes, sorting, and application deserialization. Define the contract first and test malformed and boundary values.
Querying and access-pattern redesign
Write down each operation's inputs, output, ordering, pagination, consistency, and expected traffic. Include less visible paths such as scheduled jobs, support tools, exports, and uniqueness checks.
For an order summary, one possible model is:
| Access pattern | Destination design |
|---|---|
| Get an order by its original ID | Table key: pk = ORDER#<id>, sk = METADATA |
| List a customer's orders by creation time | GSI ByCustomer: gsi1pk = CUSTOMER#<id>, gsi1sk = <UTC timestamp>#<order id> |
| Change order status if its version still matches | Conditional update on the base-table key |
| Calculate an arbitrary cross-customer report | A planned aggregate or analytics system, not a request-time table scan |
This deliberately uses a stable order ID in the base key. Changing a customer's ownership or a timestamp can update index attributes without changing the order's primary key. The GSI is eventually consistent, so use the table key for read-after-write checks that require a strong read.
DynamoDB read APIs have distinct purposes:
- GetItem: fetch one item with its full primary key.
- BatchGetItem: fetch several known keys; retry unprocessed keys and do not rely on response order.
- Query: read a partition-key value and optional sort-key range from a table or index.
- Scan: evaluate every item in the selected table or index, page by page. Useful for controlled administrative work, but usually a poor replacement for an indexed MongoDB application query.
A filter applies after DynamoDB reads candidate items. It does not save the read capacity used to evaluate them. Follow pagination even when a filtered page contains no results. MongoDB $lookup and aggregation stages do not become equivalent operations merely by switching to DynamoDB PartiQL.
Application reads with AWS SDK for JavaScript v3
Install @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb in the application. This ES module reads the Orders model above and pages through its customer index:
Use the application's AWS profile or workload role and Region configuration; do not embed credentials. Test authorization and decimal handling in the real application, not only the migration script.
Migration: choose a transfer path
| Path | Fits when | Main work you still own |
|---|---|---|
| DMS full load plus CDC | Source version and deployment are supported; changes continue during backfill | Object mappings, source permissions, change retention, target validation, and cutover |
| Export, transform, S3 import | A new table and a controlled export or write pause fit | Consistent extraction, type mapping, duplicate keys, and changes after the export |
| Application backfill plus change processing | The model needs custom splitting, joins, or materialized views | Checkpoints, version ordering, idempotency, deletes, retries, and reconciliation |
Option 1: AWS DMS with a MongoDB source
AWS documents MongoDB source support and a DynamoDB target. Check the current supported-source matrix for your MongoDB and DMS versions; the matrix checked for this update lists MongoDB through 8.0, not 9.0. Do not assume support for a newer server release.
DMS offers document and table metadata modes. Document mode places the source document in _doc; table mode exposes fields and imposes type-consistency requirements. For ongoing document-mode changes, configure _id as a separate column as documented. CDC needs a suitable replica-set/change-history configuration and sufficient retained history to survive backfill and interruptions.
For the target, object mappings determine keys and attributes. DMS can create target tables, but it does not automatically implement the application model above. Review its restrictions around changing primary-key values, unsupported task settings, and source field names before running the task.
A practical sequence is to test endpoints, load a representative collection, inspect the resulting types and keys, and exercise inserts, updates, and deletes. Then run the production full load with CDC, monitor lag and errors, and reconcile against a defined source checkpoint. Do not assume a successful transfer has reproduced MongoDB indexes or query semantics.
Option 2: transform an export and import from S3
DynamoDB's S3 import accepts CSV, DynamoDB JSON, or Amazon Ion and creates a new table. It does not import into an existing table and does not consume the new table's write capacity. Storage and import charges still apply.
MongoDB Extended JSON is not DynamoDB JSON. For this offline example, pause writes and background mutations for the exported dataset, or use a separately designed consistent extraction process. The source must remain stable until cutover unless you also capture and apply subsequent changes.
Export the orders collection with mongoexport. Configure MONGODB_EXPORT_HOST and MONGODB_EXPORT_USER for your deployment; omitting the password lets the tool prompt for it. Adjust the authentication database if needed:
mongoexport is a data export tool, not a deployment backup. Retain an actual source backup for rollback. Canonical Extended JSON helps preserve BSON type information; decode it with PyMongo's BSON utilities.
The following Python script requires pymongo and boto3. Save it as convert_orders.py. It intentionally handles a bounded order-summary schema, not arbitrary MongoDB documents: _id is an ObjectId, customerId and status are strings, createdAt is a BSON Date, and total is Decimal128. Other fields are omitted deliberately; extend and validate the mapping before using it for your own dataset.
The required import format is one Item object per line containing typed DynamoDB attributes. Do not wrap the output in an array or put BatchWrite request objects around it. Only upload output from a successful conversion run. Check primary-key uniqueness separately; duplicate destination keys can overwrite records during import.
Save this table definition as orders-table.json. Its key and index names match the converter and SDK example:
With a dedicated S3 prefix, appropriate S3/DynamoDB permissions, and an AWS CLI v2 profile and Region configured, start the import. Set MIGRATION_BUCKET to a bucket you control. The Orders table must not already exist:
Wait for the returned import's status to become COMPLETED using describe-import. Inspect error counts and logs before accepting the table, then enable the required backups, alarms, and access policies. Keep unrelated or older files out of the imported prefix.
For a smaller load into an existing table, a custom writer can use boto3's batch_writer, which buffers writes and retries unprocessed items. Batch writes overwrite matching keys and do not support per-item conditions. Use conditional individual writes when source-version checks are required; do not race an unconditional backfill against live updates.
Option 3: backfill with application change processing
A custom pipeline fits when one MongoDB document becomes several items or needs data from other collections. Capture a durable change boundary before the snapshot, retain events until applied, checkpoint progress, and make replay idempotent.
Plain dual writes are not enough. MongoDB can succeed while DynamoDB fails, and a slow backfill can overwrite a newer value. Keep one authoritative writer during migration and use an outbox or durable change capture with retries and reconciliation. Preserve version ordering per record and handle deletes explicitly, including deletes that occur before the backfill reaches a record.
Cut over, monitor, and clean up
For an offline migration, keep writes paused until validation finishes and the new application path is ready. For an online migration, briefly fence source writes, drain changes to a known boundary, reconcile, and then switch the authoritative writer. Switching reads first is useful for testing only when you understand the remaining replication lag.
Validate more than a row count:
- Compare source IDs with destination keys, including missing and duplicate records.
- Compare canonical field values after the agreed type mapping, especially decimals and dates.
- Run every access pattern, including pagination, sort order, conditional conflicts, and deletes.
- Measure latency, throttling, consumed capacity, GSI lag, and migration backlog under load.
- Restore a backup and exercise the application routing needed to use it.
DynamoDB's reported table item count is not a real-time reconciliation proof. Use a controlled read of the migrated key set or application-level reconciliation against the frozen source boundary.
After DynamoDB accepts new writes, rolling back to MongoDB requires those writes to reach MongoDB or be replayed there. Keeping an old snapshot alone is insufficient. Define rollback and reconciliation before cutover, then retain the source and migration artifacts for the agreed period. Remove obsolete credentials, connections, jobs, and infrastructure only after that period and the verification gates pass.
Dynamoose
Dynamoose is a DynamoDB modeling library inspired by Mongoose. It provides schema validation and a higher-level interface, but it is not a drop-in implementation of Mongoose queries, population, middleware, or transactions.
If you use it, review each model and operation against the destination access patterns. A familiar method name does not guarantee the same query cost or consistency. The direct SDK v3 example above keeps those operations explicit while the model is being validated. The DynamoDB ORM comparison runs Dynamoose, ElectroDB and DynamoDB Toolbox against the same model.
DynamoDB starting tips and checks
Start with one representative collection and its application endpoints. Include large documents, unusual BSON values, old records, and active writes in the rehearsal. Keep a repeatable conversion and a record of the source boundary, mapping version, destination table, and validation results.
Use the DynamoDB tutorials for individual APIs. Dynobase's data-modeling workspace can help record access patterns and indexes, and its S3 import workflow can help inspect the bulk-import setup. Neither replaces application-level reconciliation or a cutover plan.
Frequently Asked Questions
Can AWS DMS migrate MongoDB to DynamoDB?
Can I import a MongoDB JSON export directly into DynamoDB?
Will MongoDB queries work after migration?
Can the migration run without downtime?
Does Dynamoose make Mongoose migration automatic?
Dynobase is a Professional GUI Client for DynamoDB
Start your 7-day free trial today
Product Features
DynamoDB Tools
- SSH GUI Client
- Chat With Cloud
- MongoDB GUI Client
- AWS Cost Monitoring
- DynamoDB Query Builder
- DynamoDB Code Examples
- DynamoDB Node.js Queries
- DynamoDB JSON Converter
- DynamoDB UUID Generator
- DynamoDB Local Admin GUI
- DynamoDB Pricing Calculator
- DynamoDB Single-Table Design
- Best DynamoDB GUI Clients
- Dynobase vs DynoTable