DocumentDB and MongoDB on AWS

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

See the section bibliography for the reference material consulted while preparing these pages.

Commands and behaviour on this page are current for AWS CLI v2 (2.37 line) and Amazon DocumentDB engine versions 3.6, 4.0, 5.0 and 8.0 as listed in the official documentation (checked 2026-10-01); DocumentDB 8.0 was released on 14 November 2025 and 5.0.1 on 8 June 2026. Re-verify the supported-features tables and the Region and instance-class availability before relying on any of it, because both change often. Examples use us-east-1 and the placeholder account ID 111122223333; both are stand-ins for your own values.

MongoDB is the document database this site documents in depth (see MongoDB Reference). On AWS there are two managed ways to run it, and a third that you operate yourself. Amazon DocumentDB (with MongoDB compatibility) is AWS’s own document database: it speaks the MongoDB wire protocol and is compatible with the 3.6, 4.0, 5.0 and 8.0 MongoDB APIs, but it is a different engine on a storage layer shared with the other AWS database services, not MongoDB itself. MongoDB Atlas on AWS is MongoDB Inc.'s own managed service running real mongod processes in your chosen AWS Region, bought directly or through AWS Marketplace. Self-managed MongoDB on EC2 or EKS gives you the genuine server and all the operations work. This page covers DocumentDB in depth (cluster types, compatibility, TLS and authentication, connecting from Spring Data MongoDB, backups, scaling, pricing, troubleshooting), then Atlas on AWS, a comparison, migration, and the Bookshelf orders variant (the orders-api database as DocumentDB cluster bookshelf-orders, the alternative to the DynamoDB Orders table of Amazon DynamoDB).

The wider map of AWS database options is on Managed Databases on AWS; the relational alternatives are Amazon RDS and Amazon Aurora, and the key-value alternative is Amazon DynamoDB. For the Azure counterpart, which exposes a MongoDB API on Cosmos DB, see Cosmos DB and Azure DocumentDB.

Choosing between the options

Aspect Amazon DocumentDB MongoDB Atlas on AWS Self-managed MongoDB on EC2 or EKS

What it is

AWS-built, MongoDB-compatible engine with a log-structured storage volume replicated six ways across three Availability Zones.

The real MongoDB server operated by MongoDB Inc. inside AWS Regions (and other clouds).

The real MongoDB server (Community or Enterprise) that you install and run.

Compatibility

MongoDB 3.6, 4.0, 5.0 and 8.0 API levels with documented gaps (see below).

Full MongoDB feature set of the chosen server version, including Atlas Search and Atlas Vector Search.

Full feature set of the version you install.

Operations

AWS patches, backs up, fails over and scales storage automatically.

MongoDB Inc. patches, backs up and scales; auto-scaling tiers available.

You do everything: replica sets, sharding, upgrades, backups, monitoring.

Billing and procurement

Normal AWS bill; covered by AWS commitments and the AWS support plan.

Atlas invoice, or an AWS Marketplace subscription so charges land on the AWS bill and count towards AWS spend commitments.

EC2/EBS/EKS cost on the AWS bill plus MongoDB Enterprise licence if used.

Network access

Only inside a VPC (no public endpoint); reach it from outside through VPN, bastion or SSH tunnel.

Public endpoint with IP access list, VPC peering, or AWS PrivateLink private endpoints.

Whatever you build in your VPC.

Choose it when

You are all-in on AWS, want IAM, KMS, CloudWatch and VPC integration, and your queries stay within the supported subset.

You need full MongoDB compatibility, newest server features, multi-cloud, or Atlas Search and vector search.

You need an unsupported feature or version, or want to avoid vendor-managed services.

Behind the choice sits one question: does your application use any MongoDB feature that DocumentDB documents as unsupported? Run the compatibility checks below against your real queries before committing, because migrating afterwards in either direction is a project.

flowchart TD A["Need a managed document database on AWS"] --> B{"Uses features DocumentDB lacks,
or needs newest MongoDB server features?"} B -- "Yes" --> C["MongoDB Atlas on AWS
(Marketplace billing, PrivateLink)"] B -- "No" --> D{"Multi-cloud or Atlas Search
required?"} D -- "Yes" --> C D -- "No" --> E{"Workload size and shape"} E -- "Steady, up to 256 TiB" --> F["DocumentDB instance-based cluster"] E -- "Spiky or unknown" --> G["DocumentDB serverless instances"] E -- "Millions of writes per second,
petabytes, 5.0 API" --> H["DocumentDB elastic cluster"]

Amazon DocumentDB concepts

Cluster

A cluster is zero to sixteen instances plus one cluster storage volume. All writes go through the single primary instance; every instance, primary or replica, serves reads. Compute and storage are separate: the volume keeps six copies of the data across three Availability Zones (even in a Region where only two zones can host instances) and grows automatically in 10 GB steps, up to 256 TiB on engine version 8.0 and 128 TiB on earlier versions.

Instance

A compute node of a given instance class: memory-optimised db.r8g, db.r6g, db.r6gd, db.r5, db.r4, burstable db.t4g and db.t3 for development, and db.serverless. Not every class exists in every Region. Up to 15 replicas share the primary’s storage, so adding one takes minutes regardless of data size and replica lag is typically single-digit milliseconds.

Endpoints

The cluster endpoint always points at the current primary; the reader endpoint load-balances across replicas; each instance also has its own instance endpoint. Applications should connect as a replica set (rs0) through the cluster endpoint with readPreference=secondaryPreferred rather than hard-coding instance names.

Cluster parameter group

The settings that govern every instance of a cluster, for example tls (enabled, disabled or fips-140-3), audit_logs, profiler and ttl_monitor. Parameter groups are not available on elastic clusters.

Subnet group

A set of subnets in at least two Availability Zones of one VPC where the instances may be placed (see VPC Networking).

Storage configuration

Engine 5.0 instance-based clusters offer Standard (I/O billed per request) and I/O-Optimized (higher instance and storage price, no per-I/O charge) storage configurations; I/O-Optimized pays off for I/O-heavy workloads.

Three cluster types

Type Scaling model API level Notable limits

Instance-based (provisioned)

Vertical (instance class) plus up to 15 read replicas; storage grows by itself.

3.6, 4.0, 5.0 or 8.0.

One writer; storage up to 256 TiB on 8.0 (128 TiB earlier); all features.

Instance-based with db.serverless instances

Each instance scales between a minimum and maximum number of DocumentDB capacity units (DCUs, in half-unit steps) within seconds, per instance. Instances in a cluster may mix serverless and provisioned.

5.0 and later (check the serverless limitations page for the exact versions and Regions).

Same features as provisioned, including IAM authentication, reader instances, Multi-AZ and global clusters.

Elastic cluster (docdb-elastic)

Horizontal: 1 to 32 shards, each with 2 to 64 vCPUs per shard instance and up to 16 shard instances; AWS manages the shard instances and patching.

MongoDB 5.0-compatible wire protocol; not available on engine 8.0, not in China Regions or GovCloud.

Hash sharding only on a single-field key that cannot be changed, existing collections cannot be sharded in place; no transactions, change streams, point-in-time restore, global clusters, parameter groups or IAM database authentication; check the current limitations list for index types.

Choose instance-based for most applications, serverless when load is unpredictable or the environment is idle most of the day, and elastic only when a single writer cannot keep up or the data will outgrow one volume.

MongoDB compatibility

DocumentDB "supports the MongoDB 3.6, 4.0, 5.0 and 8.0 APIs": drivers written for those protocol levels connect and most CRUD, aggregation, index and transaction code works unchanged. It does not run MongoDB source code, so a feature list per engine version is the contract. The facts that most often decide a project:

Area Behaviour on DocumentDB

Engine versions

3.6 reached the end of standard support on 30 March 2026 and is now in paid Extended Support until 30 March 2029; 4.0 and 5.0 are supported; 8.0 (released 14 November 2025) adds drivers for MongoDB 6.0, 7.0 and 8.0 and, among other things, $vectorSearch, views (createView), $facet, $merge, $graphLookup, $bucket, window functions and mapReduce. Plan upgrades from 3.6 now.

Transactions

Multi-document ACID transactions from 4.0 on instance-based clusters; not in 3.6 and not on elastic clusters. Spring’s MongoTransactionManager therefore works against 4.0 and later.

Retryable writes

Supported from engine 8.0.2; earlier engines do not support them, so connection strings for 3.6 to 5.0 clusters must carry retryWrites=false (current Java, Node.js, Python drivers default to true and otherwise fail).

Change streams

Supported on instance-based clusters (3.6 on), with a retention window you enable per collection; not on elastic clusters.

Indexes

Single-field, compound, multikey, 2dsphere, TTL, unique and sparse are supported. Text and partial indexes need 5.0 or later, case-insensitive and hidden indexes need 8.0 (hidden from 8.0.1). Vector indexes exist on 5.0 and 8.0 for similarity search. Hashed, wildcard and 2d indexes are not supported.

Query and aggregation

$lookup, $group, $unwind and most operators work; $where, $unionWith, $densify, $fill and the $expMovingAvg-style window operators do not; $text and $search need 5.0 or later. Always check an operator in the per-version support table before depending on it.

Data types

DBRef, JavaScript, Symbol and undefined values are not supported.

Collections

Capped collections and tailable cursors are not supported; time series collections are not part of the documented API.

Wire compression

snappy only, from 8.0.1; other compressors negotiate down to no compression.

Administration

No mongod configuration, no mongos/config servers (outside elastic clusters), no oplog access; use cluster parameter groups and the service API instead.

Practical method: run the open-source DocumentDB Compatibility Tool (linked from the migration guide) or your own test suite against a development cluster, and keep application code to the intersection of the two feature sets if you may later move to Atlas. The MongoDB concepts behind each of these features are on this site: documents and BSON in Documents, BSON & data types, indexes in Indexing & query performance, transactions in Multi-document ACID transactions, change streams in Reacting to data changes, the aggregation pipeline in The aggregation framework and special indexes and search in Text, wildcard, geospatial & Atlas search. DocumentDB replaces replica-set and sharding administration (Replica sets & high availability, Horizontal scaling with sharded clusters) with managed equivalents, so those pages explain the model rather than commands you run.

Prerequisites for Bookshelf

Everything below creates the orders-api database in us-east-1 inside the Bookshelf VPC (see VPC Networking).

  • A VPC with at least two private subnets in different Availability Zones. DocumentDB has no public endpoint, so the instances live in private subnets.

  • A security group sg-orders-db that allows inbound TCP 27017 only from the security group of orders-api (and, for administration, from a bastion or CloudShell VPC environment).

  • An IAM identity that may create DocumentDB, EC2 networking and Secrets Manager resources (policy below).

  • Shell variables used by all commands:

export AWS_REGION=us-east-1
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export CLUSTER=bookshelf-orders
export SUBNET_A=subnet-0aaa1111bbb22222a   # private subnet, AZ a (placeholder)
export SUBNET_B=subnet-0ccc3333ddd44444b   # private subnet, AZ b (placeholder)
export DB_SG=sg-0123456789abcdef0          # sg-orders-db (placeholder)

Permissions

The IAM policy of the person or pipeline that provisions the cluster, scoped to the Bookshelf names. The docdb actions use the rds resource ARN namespace because DocumentDB shares control-plane infrastructure with RDS:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ManageBookshelfOrdersCluster",
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBCluster", "rds:ModifyDBCluster", "rds:DeleteDBCluster",
        "rds:CreateDBInstance", "rds:ModifyDBInstance", "rds:DeleteDBInstance",
        "rds:RebootDBInstance", "rds:FailoverDBCluster",
        "rds:CreateDBClusterSnapshot", "rds:DeleteDBClusterSnapshot",
        "rds:AddTagsToResource", "rds:ListTagsForResource"
      ],
      "Resource": [
        "arn:aws:rds:us-east-1:111122223333:cluster:bookshelf-orders*",
        "arn:aws:rds:us-east-1:111122223333:db:bookshelf-orders*",
        "arn:aws:rds:us-east-1:111122223333:cluster-snapshot:bookshelf-orders*"
      ]
    },
    {
      "Sid": "SharedDocDbBuildingBlocks",
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBSubnetGroup", "rds:DeleteDBSubnetGroup",
        "rds:CreateDBClusterParameterGroup", "rds:ModifyDBClusterParameterGroup",
        "rds:DeleteDBClusterParameterGroup"
      ],
      "Resource": [
        "arn:aws:rds:us-east-1:111122223333:subgrp:bookshelf-orders*",
        "arn:aws:rds:us-east-1:111122223333:cluster-pg:bookshelf-orders*"
      ]
    },
    {
      "Sid": "DescribeAndNetworking",
      "Effect": "Allow",
      "Action": [
        "rds:Describe*",
        "ec2:DescribeVpcs", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups",
        "ec2:DescribeAvailabilityZones", "kms:DescribeKey", "kms:ListAliases"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ManagedMasterSecret",
      "Effect": "Allow",
      "Action": ["secretsmanager:CreateSecret", "secretsmanager:TagResource", "secretsmanager:DescribeSecret"],
      "Resource": "arn:aws:secretsmanager:us-east-1:111122223333:secret:rds!cluster-*"
    }
  ]
}

Elastic clusters use the docdb-elastic:* action namespace and the AWS managed policy AmazonDocDBElasticFullAccess. At run time the application needs no DocumentDB control-plane permissions, only the ability to read its credentials; this policy goes on the orders-api task role (see Secrets Manager, Parameter Store and KMS):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ReadOrdersDbSecret",
    "Effect": "Allow",
    "Action": "secretsmanager:GetSecretValue",
    "Resource": "arn:aws:secretsmanager:us-east-1:111122223333:secret:bookshelf/orders/docdb-*"
  }]
}

Creating an instance-based cluster

In the AWS Management Console

  1. Select the Region in the top-right selector (us-east-1 here) and open Amazon DocumentDB.

  2. Under Subnet groups choose Create, name it bookshelf-orders, pick the Bookshelf VPC and select the two private subnets in different Availability Zones.

  3. Under Clusters choose Create. For Cluster type choose Instance-based cluster.

  4. Cluster identifier: bookshelf-orders. Engine version: choose 8.0.0 for new work unless you need elastic clusters (5.0) or a feature only listed for a lower level.

  5. Cluster storage configuration: Amazon DocumentDB Standard (change to I/O-Optimized if I/O is more than about a quarter of your database cost).

  6. Instance configuration: pick an instance class (for example a db.r8g or db.r6g size, or db.t4g.medium for development, or Serverless with a capacity range) and Number of regular replica instances 1 or 2, so a failover target exists in another Availability Zone.

  7. Connectivity: choose Don’t connect to an EC2 compute resource (you will connect from the application later) and expand Network settings to select the bookshelf-orders subnet group and the sg-orders-db security group.

  8. Authentication: enter primary user name ordersadmin and choose Managed in AWS Secrets Manager so no password appears in templates, history or tickets.

  9. Under Advanced settings: encryption at rest stays on (default or your own KMS key), set Backup retention (1 to 35 days, 7 is a sensible start), enable Log exports for audit and profiler if required, and enable Deletion protection.

  10. Choose Create cluster. Creation takes several minutes; the status moves from Creating to Available.

With the AWS CLI

Create the subnet group, a cluster parameter group that keeps TLS enabled and exports audit logs, the cluster and the instances. --manage-master-user-password makes DocumentDB generate the primary password and store it in Secrets Manager.

aws docdb create-db-subnet-group \
  --db-subnet-group-name bookshelf-orders \
  --db-subnet-group-description "Bookshelf orders DocumentDB" \
  --subnet-ids "$SUBNET_A" "$SUBNET_B"

aws docdb create-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bookshelf-orders-docdb8 \
  --db-parameter-group-family docdb8.0 \
  --description "Bookshelf orders parameters"

aws docdb modify-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bookshelf-orders-docdb8 \
  --parameters ParameterName=tls,ParameterValue=enabled,ApplyMethod=pending-reboot \
               ParameterName=audit_logs,ParameterValue=enabled,ApplyMethod=pending-reboot

aws docdb create-db-cluster \
  --db-cluster-identifier "$CLUSTER" \
  --engine docdb \
  --engine-version 8.0.0 \
  --master-username ordersadmin \
  --manage-master-user-password \
  --db-subnet-group-name bookshelf-orders \
  --db-cluster-parameter-group-name bookshelf-orders-docdb8 \
  --vpc-security-group-ids "$DB_SG" \
  --storage-encrypted \
  --backup-retention-period 7 \
  --enable-cloudwatch-logs-exports audit profiler \
  --deletion-protection \
  --tags Key=app,Value=bookshelf

aws docdb create-db-instance \
  --db-cluster-identifier "$CLUSTER" \
  --db-instance-identifier "$CLUSTER-1" \
  --db-instance-class db.r6g.large \
  --engine docdb \
  --availability-zone us-east-1a

aws docdb create-db-instance \
  --db-cluster-identifier "$CLUSTER" \
  --db-instance-identifier "$CLUSTER-2" \
  --db-instance-class db.r6g.large \
  --engine docdb \
  --availability-zone us-east-1b

aws docdb wait db-instance-available --db-instance-identifier "$CLUSTER-2"

aws docdb describe-db-clusters --db-cluster-identifier "$CLUSTER" \
  --query 'DBClusters[0].[Endpoint,ReaderEndpoint,MasterUserSecret.SecretArn]' --output text

The first instance created in a cluster becomes the primary; the second becomes a replica and the failover target. The parameter group family and engine version strings track the engine you pick (for example docdb5.0 with 5.0.0); list what the Region offers with aws docdb describe-db-engine-versions --engine docdb. Both instance creates are separate calls on purpose: DocumentDB’s create-db-cluster makes an empty cluster, unlike the console, which creates the cluster and instances together.

Serverless and elastic variants

A serverless-capable cluster only adds a scaling range to create-db-cluster, and the instances use the db.serverless class (one DCU is roughly 2 GiB of memory with matching CPU and networking; check the serverless instance-limits page for the allowed minimum and maximum):

aws docdb create-db-cluster \
  --db-cluster-identifier bookshelf-orders-sl \
  --engine docdb --engine-version 5.0.0 \
  --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=16 \
  --master-username ordersadmin --manage-master-user-password \
  --db-subnet-group-name bookshelf-orders --vpc-security-group-ids "$DB_SG"

aws docdb create-db-instance \
  --db-cluster-identifier bookshelf-orders-sl \
  --db-instance-identifier bookshelf-orders-sl-1 \
  --db-instance-class db.serverless --engine docdb

Elastic clusters have their own CLI namespace and shard model; the cluster below has two shards of 4 vCPUs each with two instances per shard:

aws docdb-elastic create-cluster \
  --cluster-name bookshelf-orders-elastic \
  --shard-capacity 4 --shard-count 2 --shard-instance-count 2 \
  --admin-user-name ordersadmin \
  --admin-user-password "$ADMIN_PASSWORD_FROM_SECRETS_MANAGER" \
  --auth-type PLAIN_TEXT \
  --vpc-security-group-ids "$DB_SG" \
  --subnet-ids "$SUBNET_A" "$SUBNET_B"

Shard capacity accepts 2, 4, 8, 16, 32 or 64 vCPUs. The elastic --auth-type SECRET_ARN option reads the password from a Secrets Manager secret you create beforehand, which is the better choice outside a throwaway test. In the console, choose Elastic cluster in the Cluster type section instead. A collection is distributed only after sh.shardCollection("orders.orders", { "customerId": "hashed" }); choose a high-cardinality key, because there is no way to change it later.

TLS and authentication

TLS

TLS is enabled by default through the tls cluster parameter (enabled, disabled or fips-140-3, the last in a limited set of Regions on 5.0 and later). Leave it on and trust the Amazon RDS certificate bundle, which also covers DocumentDB:

curl -sS -o global-bundle.pem https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

mongosh connects with the bundle and the replica-set parameters. Because the client sits outside the cluster’s VPC only through a tunnel or VPN, run it from CloudShell with a VPC environment, an EC2 bastion in the Bookshelf VPC, or the console’s Connect to cluster button, which starts a CloudShell session already wired to the cluster:

SECRET_ARN=$(aws docdb describe-db-clusters --db-cluster-identifier "$CLUSTER" \
  --query 'DBClusters[0].MasterUserSecret.SecretArn' --output text)
DB_PASSWORD=$(aws secretsmanager get-secret-value --secret-id "$SECRET_ARN" \
  --query SecretString --output text | jq -r .password)
ENDPOINT=$(aws docdb describe-db-clusters --db-cluster-identifier "$CLUSTER" \
  --query 'DBClusters[0].Endpoint' --output text)

mongosh --tls --host "$ENDPOINT:27017" --tlsCAFile global-bundle.pem \
  --username ordersadmin --password "$DB_PASSWORD" --retryWrites false

The --retryWrites false flag is for engines older than 8.0.2; omit it on newer ones. Java applications trust the bundle either by importing it into a JKS trust store and pointing javax.net.ssl.trustStore at it (the official guide has the import script), or by building an SSLContext from the PEM file.

Users, roles and IAM authentication

Authentication on DocumentDB is MongoDB-style. The primary user created with the cluster is an administrator; do not use it from the application. Connect as the primary user and create one least-privilege user per application:

use orders
db.createUser({
  user: "orders_api",
  pwd: passwordPrompt(),
  roles: [ { role: "readWrite", db: "orders" } ]
})

Store that user’s password in Secrets Manager (for example as bookshelf/orders/docdb) and rotate it with a rotation Lambda function; DocumentDB provides a rotation template, and the primary user’s managed secret is rotated by the service itself. On instance-based clusters running engine 5.0 you can go password-less with IAM identities: create the user in the $external database with mechanisms: ["MONGODB-AWS"] and the ARN of the IAM role as the user name, then connect with authSource=$external&authMechanism=MONGODB-AWS. The driver resolves temporary credentials from the compute environment (task role, Lambda execution role, EC2 instance profile, or EKS Pod Identity), so there is no password at all. The primary user cannot use IAM authentication, IAM authentication needs a driver that implements MONGODB-AWS (Node.js driver 6.13.1 or newer, PyMongo with the aws extra), and it is not available on elastic clusters. Network access is enforced by VPC security groups; there are no IP allow lists and no public endpoint.

For compliance, enable the audit_logs parameter and the CloudWatch Logs export of audit and profiler; encryption at rest with AWS KMS is chosen at creation and cannot be turned on later.

Application code: Spring Data MongoDB

Spring Data MongoDB talks to DocumentDB through the ordinary MongoDB Java driver, so the mapping model on Spring Data MongoDB applies unchanged: @Document, MongoRepository, MongoTemplate and MongoTransactionManager. Only the connection differs. The Bookshelf orders-api document:

package com.example.bookshelf.orders;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.List;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

@Document("orders")
public record Order(
        @Id String id,
        @Indexed String customerId,
        List<Line> lines,
        BigDecimal total,
        Instant createdAt) {

    public record Line(String isbn, int quantity, BigDecimal unitPrice) {}
}
package com.example.bookshelf.orders;

import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface OrderRepository extends MongoRepository<Order, String> {
    List<Order> findByCustomerIdOrderByCreatedAtDesc(String customerId);
}

Configuration is a connection string. Credentials come from Secrets Manager through the Spring Cloud AWS config import (see Secrets Manager, Parameter Store and KMS and Configuration and Profiles), so nothing sensitive sits in the repository. With the secret holding the keys username and password, application.yml is:

spring:
  config:
    import: aws-secretsmanager:bookshelf/orders/docdb
  data:
    mongodb:
      uri: mongodb://${username}:${password}@${DOCDB_ENDPOINT}:27017/orders?tls=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false&tlsCAFile=/etc/ssl/global-bundle.pem
      auto-index-creation: false

Three DocumentDB-specific details are in that URI. replicaSet=rs0 plus readPreference=secondaryPreferred makes the driver use the cluster endpoint for writes and spread reads over replicas. retryWrites=false is required on engines before 8.0.2. And tlsCAFile is a convenience of some drivers only: the Java driver ignores it, so either import global-bundle.pem into a JKS trust store passed with -Djavax.net.ssl.trustStore, or bake the trust store into the container image and set the system properties there. In Spring Boot 4 the connection properties moved from spring.data.mongodb. to spring.mongodb. with the old names still accepted for a deprecation period; check the Boot version you use. Set auto-index-creation to false in production and create indexes in a deployment step, because index builds on a live DocumentDB cluster are I/O work you want to schedule. With IAM authentication, replace the user and password with authSource=%24external&authMechanism=MONGODB-AWS and give the orders-api task role (or EKS Pod Identity role) as the database user.

Multi-document transactions work on engine 4.0 and later instance-based clusters when you declare a MongoTransactionManager bean and annotate service methods with @Transactional; keep them short, because DocumentDB limits how long a transaction may run. The semantics (snapshot isolation, write conflicts, retry on transient errors) are described on Multi-document ACID transactions.

Connecting from Bookshelf: networking

  • Where the cluster lives. Private subnets only; the cluster endpoint resolves to private IP addresses of the instances. There is no public accessibility flag.

  • Who may connect. sg-orders-db allows inbound 27017 from sg-orders-api only. Reference a security group, not a CIDR, so scaling orders-api tasks or Lambda functions never needs a rule change.

  • Different VPC or account. Use VPC peering or a Transit Gateway (see VPC Networking); DocumentDB has no PrivateLink endpoint of its own for data-plane traffic.

  • From a laptop. Use an SSH tunnel through a bastion in the VPC, SSM Session Manager port forwarding, or Client VPN (see VPN and Hybrid Connectivity). Tunnelling breaks replica-set discovery unless you connect with directConnection=true to a single instance, which is acceptable for administration but not for applications.

  • Lambda. A function must be attached to the VPC and its subnets need a route to nothing more than the database; create the MongoClient outside the handler so connections are reused across invocations.

  • Connection limits. Each instance class has a connection ceiling (it grows with memory), so size pools (maxPoolSize) by the number of application tasks multiplied by the pool size, not by one task.

Backups, restore and high availability

Automated backups are continuous and incremental and stored in Amazon S3; they restore the cluster to any second inside the retention period (1 to 35 days) up to the last five minutes, and they never slow the cluster. Manual cluster snapshots persist until deleted and can be copied to other Regions or shared with other accounts (encrypted snapshots require sharing the KMS key).

aws docdb create-db-cluster-snapshot \
  --db-cluster-identifier "$CLUSTER" --db-cluster-snapshot-identifier bookshelf-orders-pre-release

# Point-in-time restore creates a NEW cluster; add instances to it afterwards
aws docdb restore-db-cluster-to-point-in-time \
  --db-cluster-identifier bookshelf-orders-restored \
  --source-db-cluster-identifier "$CLUSTER" \
  --restore-type full-copy \
  --use-latest-restorable-time \
  --db-subnet-group-name bookshelf-orders --vpc-security-group-ids "$DB_SG"

# Planned failover test
aws docdb failover-db-cluster --db-cluster-identifier "$CLUSTER"

Failover to a replica is typically well under a minute and the cluster endpoint follows automatically; with no replica, DocumentDB creates a replacement instance, which takes longer. Global clusters add read-only secondary clusters in other Regions (storage-based replication, typically under a second of lag) for disaster recovery and local reads; they exist for instance-based clusters, need supported instance classes (not the burstable ones) and cannot be elastic. Clones, restore-to-new-cluster and global clusters are the DocumentDB equivalents of the replica-set recovery described on Backups, import/export & GridFS, which still explains the logical-backup option (mongodump) for portable copies.

Engine 5.0 and 8.0 instance-based clusters support vector indexes (HNSW and IVFFlat) and the $vectorSearch stage on 8.0, so a catalogue of book embeddings can live next to the documents. Create the index with createIndex using a vectorOptions document (dimensions, similarity euclidean, cosine or dotProduct), then query with an aggregation pipeline. For vector-database trade-offs against other engines see Comparing Vector Databases; the MongoDB-flavoured features (Atlas Vector Search, $vectorSearch) are covered on Text, wildcard, geospatial & Atlas search and MongoDB Atlas Search, which apply to Atlas rather than DocumentDB unless noted.

Scaling and operations

Need How

More read capacity

Add replicas (up to 15) and send reads to the reader endpoint; replicas share storage, so no data copy occurs.

More CPU or memory per node

modify-db-instance --db-instance-class on replicas first, then fail over and modify the old primary; the cluster stays available except for the failover pause.

Unpredictable load

Use db.serverless instances; set the minimum high enough for your working set (the buffer cache shrinks as it scales down) and the maximum to cap the bill.

More write capacity or beyond one volume

Elastic cluster (shards and per-shard vCPUs scale independently, in-place, with limits on DDL during scaling).

Storage

Automatic; nothing to do and nothing to provision.

Maintenance

Preferred maintenance window per cluster; minor engine updates are applied there, and major upgrades (for example 5.0 to 8.0) are an explicit in-place major version upgrade or a DMS-based migration.

Monitoring

CloudWatch metrics (CPUUtilization, FreeableMemory, DatabaseConnections, BufferCacheHitRatio, DBClusterReplicaLagMaximum, VolumeBytesUsed), profiler and audit logs to CloudWatch Logs, Performance Insights on instance-based clusters, and CloudWatch alarms or event subscriptions through SNS.

See Monitoring and Observability for the alarm and dashboard patterns that apply to any database.

MongoDB Atlas on AWS

MongoDB Atlas deploys dedicated clusters (tiers M10 and above), shared and Flex tiers for development, and serverless-style autoscaling into AWS Regions you choose. It speaks genuine MongoDB, adds Atlas Search and Atlas Vector Search, and brings its own backup, monitoring and auto-scaling. Four things matter for the AWS side.

Billing through AWS Marketplace

The MongoDB Atlas (pay as you go) listing lets AWS invoice your Atlas usage. This puts Atlas on the same bill as your other AWS usage and lets the spend count towards AWS commitments such as an Enterprise Discount Program, where the agreement allows it. Private offers with committed spend are negotiated with MongoDB and accepted in Marketplace.

Network access

Atlas offers an IP access list on the public endpoint, VPC peering and AWS PrivateLink private endpoints. PrivateLink is the recommended production option on AWS because traffic never leaves the AWS network and no CIDR coordination between your VPC and the Atlas VPC is needed.

Security

TLS is always on; authentication is SCRAM, X.509 or, for AWS workloads, AWS IAM (MONGODB-AWS) so a task or function role signs in without a password; Atlas encrypts at rest with its own keys or your AWS KMS key.

Operations

Clusters scale tiers and storage online, take continuous cloud backups with point-in-time restore, and can be managed through the Atlas CLI, the Atlas Admin API, Terraform and CloudFormation extensions.

Subscribing through AWS Marketplace in the console

  1. In the AWS Management Console open AWS Marketplace and choose Discover products.

  2. Search for MongoDB Atlas and open the MongoDB Atlas (pay as you go) listing from MongoDB, Inc.

  3. Choose View purchase options, review the pricing dimensions (they refer to Atlas usage, not to AWS resources) and choose Subscribe.

  4. Choose Set up your account. Marketplace redirects to the Atlas sign-up page.

  5. Sign in or create an Atlas account, and either create a new Atlas organisation or link an existing one so that its usage bills through the Marketplace subscription.

  6. In Atlas, create a project and use Build a Database, choose AWS as the provider, pick the Region (for example us-east-1) and a tier.

  1. In Atlas open the project, then Network Access and Private Endpoint, and choose Add Private Endpoint for the AWS Region of your VPC. Atlas returns a VPC endpoint service name and asks for the VPC endpoint ID.

  2. In the AWS console open VPC, Endpoints, choose Create endpoint, type Endpoint services that use NLBs and GWLBs (an interface endpoint), paste the service name from Atlas, choose Verify service, pick the Bookshelf VPC, the private subnets and a security group that allows outbound to the ports Atlas lists (the range is 1024 to 65535) and inbound only from orders-api.

  3. Copy the new endpoint ID (vpce-…​) back into Atlas and choose Create. Wait until the endpoint shows Available.

  4. Use the private endpoint-aware connection string that Atlas shows under Connect, not the public or standard one.

With the AWS CLI the VPC side is one call, the same Atlas CLI can register the endpoint, and the password is again read from Secrets Manager rather than typed:

# ATLAS_SERVICE_NAME comes from Atlas (Network Access > Private Endpoint)
VPCE_ID=$(aws ec2 create-vpc-endpoint \
  --vpc-endpoint-type Interface \
  --vpc-id "$VPC_ID" \
  --service-name "$ATLAS_SERVICE_NAME" \
  --subnet-ids "$SUBNET_A" "$SUBNET_B" \
  --security-group-ids "$ATLAS_ENDPOINT_SG" \
  --query 'VpcEndpoint.VpcEndpointId' --output text)

# Register the interface endpoint with the Atlas endpoint service
atlas privateEndpoints aws interfaces create "$ATLAS_ENDPOINT_SERVICE_ID" --privateEndpointId "$VPCE_ID"

Atlas private endpoints are available for dedicated tiers (M10 and up), not free or Flex clusters. Spring Data MongoDB then uses the Atlas mongodb+srv:// private-endpoint string unchanged; the Atlas CA is public, so there is no trust store work, which is one practical advantage over DocumentDB.

Derived from the MongoDB documentation AWS PrivateLink private endpoints in Atlas, Set up passwordless authentication with AWS IAM and the MongoDB, Inc. listings in AWS Marketplace and the AWS reference Create an interface VPC endpoint.

Migrating to DocumentDB

Method Notes

mongodump and mongorestore

Simplest for small and medium databases and an offline cutover; mongorestore into DocumentDB with --noIndexRestore first, then create indexes explicitly, and restore with --numInsertionWorkersPerCollection tuned to instance size. The tools are described on Backups, import/export & GridFS.

AWS Database Migration Service

Full load plus change data capture from a MongoDB replica set (or an Atlas cluster, or an earlier DocumentDB version) into DocumentDB, with a short cutover. Create a source endpoint, a target endpoint with the TLS CA bundle, a replication instance and a migration task; DMS needs the source oplog and does not copy indexes, users or roles.

Export and import

mongoexport and mongoimport for single collections when types allow; JSON loses BSON types such as Decimal128 unless extended JSON is used.

Major engine upgrade

DocumentDB can upgrade 3.6 to 4.0 to 5.0 to 8.0 in place per the engine support documentation, or you can restore a snapshot into a new cluster of a newer version and cut over; always rehearse on a copy.

Before migrating, run the compatibility tool against your real workload, verify indexes and the aggregation pipelines in the table above, and decide on retryable writes (8.0.2 and later). Reverse migration to MongoDB or Atlas follows the same steps with DocumentDB as the source.

The Bookshelf orders variant

The database for the orders-api can be the DynamoDB Orders table (Amazon DynamoDB) or this DocumentDB cluster. Choose DocumentDB when the order model is a genuinely nested document queried by several fields, you want aggregation pipelines, or the team already knows MongoDB; choose DynamoDB when every access path is known up front and you want zero capacity management. The Bookshelf wiring is:

flowchart LR U["Browser"] --> CF["CloudFront bookshelf-cdn"] CF --> ALB["ALB alb-bookshelf"] ALB --> ORD["orders-api on ECS Fargate
(task role)"] ORD -->|"27017 TLS, sg-orders-db"| DOC[("DocumentDB bookshelf-orders
primary + replica")] ORD -->|"GetSecretValue"| SM["Secrets Manager
bookshelf/orders/docdb"] DOC -.->|"audit and profiler logs"| CW["CloudWatch Logs"] DOC -.->|"continuous backup"| S3[("Backup storage")]

Steps: (1) create the bookshelf-orders subnet group, parameter group, cluster and two instances as above; (2) connect as ordersadmin from CloudShell and create the orders_api user and a compound index on customerId and createdAt; (3) store the user’s password as the secret bookshelf/orders/docdb; (4) add the ReadOrdersDbSecret policy to the orders-api task role and sg-orders-db ingress from the task security group (see ECS and Fargate for how task roles and secrets injection work); (5) deploy the Spring Data MongoDB configuration above. A CloudFormation fragment for the cluster, usable beside the baseline in Infrastructure as Code:

Resources:
  OrdersSubnetGroup:
    Type: AWS::DocDB::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: Bookshelf orders
      SubnetIds: [!Ref PrivateSubnetA, !Ref PrivateSubnetB]
  OrdersCluster:
    Type: AWS::DocDB::DBCluster
    DeletionPolicy: Snapshot
    UpdateReplacePolicy: Snapshot
    Properties:
      DBClusterIdentifier: bookshelf-orders
      EngineVersion: 8.0.0
      MasterUsername: ordersadmin
      ManageMasterUserPassword: true
      DBSubnetGroupName: !Ref OrdersSubnetGroup
      VpcSecurityGroupIds: [!Ref OrdersDbSecurityGroup]
      StorageEncrypted: true
      BackupRetentionPeriod: 7
      DeletionProtection: true
      EnableCloudwatchLogsExports: [audit, profiler]
  OrdersInstance1:
    Type: AWS::DocDB::DBInstance
    Properties:
      DBClusterIdentifier: !Ref OrdersCluster
      DBInstanceClass: db.r6g.large
  OrdersInstance2:
    Type: AWS::DocDB::DBInstance
    Properties:
      DBClusterIdentifier: !Ref OrdersCluster
      DBInstanceClass: db.r6g.large

Derived from AWS::DocDB::DBCluster.

Pricing model

No prices are quoted here; the numbers change by Region and over time, so use the Amazon DocumentDB pricing page and the AWS Pricing Calculator. The cost drivers for instance-based clusters are:

  • Instance hours, billed per second with a ten-minute minimum, by instance class. Every replica is a full instance, so the Multi-AZ choice (one primary plus one replica) roughly doubles compute.

  • Storage, per GiB-month of the volume (billed on what is used, not provisioned), and I/O requests per million on the Standard configuration. The I/O-Optimized configuration removes the per-I/O charge in exchange for higher instance and storage rates.

  • Backup storage beyond the free allowance equal to your cluster volume size, which grows with retention and manual snapshots.

  • Data transfer out to the internet or other Regions, and cross-Availability-Zone transfer between your application and the database.

  • Serverless instances bill DCU-hours metered per second between the configured minimum and maximum.

  • Elastic clusters bill by the vCPU-hours of the shard instances plus storage, snapshot storage and I/O.

  • Extended Support surcharges apply per vCPU-hour once an engine version passes its end of standard support (3.6 since 31 March 2026), with higher rates in year 3.

  • A one-month free trial for new DocumentDB users covers a stated amount of instance and I/O usage.

Atlas bills by tier, storage, backup, data transfer and Atlas Search nodes, even when paid through Marketplace; the cost of PrivateLink is the interface endpoint’s hourly and per-GB charge on the AWS side (see VPC Networking). Cost-control checklist: use db.t4g instances for development and stop them when idle (a stopped cluster restarts automatically after a few days), keep non-production on serverless with a low maximum, set the shortest backup retention that meets your recovery objective, and delete manual snapshots you no longer need. Budget guidance is in Cost Management and Support.

Limits and recent changes

  • Cluster: up to 16 instances (one primary and 15 replicas), 128 TiB of storage (256 TiB from engine 8.0), backup retention up to 35 days, a default quota on clusters, instances and subnet groups per Region, adjustable through Service Quotas.

  • Elastic cluster: 32 shards, 16 shard instances per shard and 64 vCPUs per shard instance.

  • Documents and transactions: the maximum BSON document size matches MongoDB at 16 MiB; transactions are time limited.

  • Recent changes (verify dates in the release notes): DocumentDB 8.0 general availability on 14 November 2025; retryable writes from 8.0.2; wire-protocol compression from 8.0.1; engine 5.0.1 on 8 June 2026; IAM database authentication for 5.0 clusters; serverless instances; I/O-Optimized storage; 3.6 end of standard support on 30 March 2026 with Extended Support to 30 March 2029.

  • Older guides: tutorials that show mongo shells and sslCAFile=rds-combined-ca-bundle.pem, 3.6-only features, or that say DocumentDB cannot do transactions are outdated; the current bundle is global-bundle.pem, transactions arrived with 4.0, and the legacy mongo shell is replaced by mongosh.

Troubleshooting

Symptom Likely cause and fix

Connection times out

DocumentDB has no public endpoint. Confirm the client is inside the VPC (or tunnelled), the security group allows 27017 from the client’s security group, and the route tables and NACLs permit it. Test with nc -zv "$ENDPOINT" 27017.

SSL: CERTIFICATE_VERIFY_FAILED or PKIX path building failed

The client does not trust the Amazon bundle. Download the current global-bundle.pem; for Java import it into the trust store; do not disable verification.

Authentication failed

Wrong user or password, wrong authSource, a user created in a different database from the one you authenticate against, or a rotated secret the application has cached. For IAM authentication check the role ARN user in $external and the driver version.

Retryable writes are not supported (or Command is not supported)

Add retryWrites=false to the connection string for engines older than 8.0.2.

Feature not supported or no such command

The operator or command is outside DocumentDB’s compatibility list for your engine version; check the per-version table, upgrade the engine, or rewrite the query.

Replica-set discovery errors through a tunnel

The driver tries the instance endpoints it learns from the replica-set configuration. Use directConnection=true for administration, or run the application inside the VPC.

Reads return stale data

secondaryPreferred reads replicas, which lag by milliseconds; use readPreference=primary where read-your-writes is needed.

Spikes in latency and BufferCacheHitRatio drops

Working set exceeds instance memory. Scale up the instance class, add indexes, or review FreeableMemory; for serverless raise the minimum DCUs.

Many connections, Too many connections

Pool size multiplied by task count exceeds the instance class limit. Reduce maxPoolSize, reuse the MongoClient (especially in Lambda), or scale the instance.

Failover is slow or the cluster has no replica

With no replica DocumentDB must create a new instance. Keep at least one replica in another Availability Zone.

Atlas private endpoint stays in Pending

The VPC endpoint ID was not registered in Atlas, the endpoint is in a different Region from the Atlas cluster, or the security group blocks ports 1024 to 65535 outbound.

Clean up

Deletion protection, final snapshots and secret recovery windows protect against mistakes; delete in dependency order. The cluster stops billing for instances as soon as they are deleted, but the cluster’s storage and backups remain until the cluster is deleted.

aws docdb modify-db-cluster --db-cluster-identifier "$CLUSTER" --no-deletion-protection --apply-immediately

aws docdb delete-db-instance --db-instance-identifier "$CLUSTER-2"
aws docdb delete-db-instance --db-instance-identifier "$CLUSTER-1"
aws docdb wait db-instance-deleted --db-instance-identifier "$CLUSTER-1"

# Keep a final snapshot, or use --skip-final-snapshot for throwaway data
aws docdb delete-db-cluster --db-cluster-identifier "$CLUSTER" \
  --final-db-snapshot-identifier bookshelf-orders-final

aws docdb delete-db-cluster-snapshot --db-cluster-snapshot-identifier bookshelf-orders-pre-release
aws docdb delete-db-cluster-parameter-group --db-cluster-parameter-group-name bookshelf-orders-docdb8
aws docdb delete-db-subnet-group --db-subnet-group-name bookshelf-orders

# Serverless and elastic variants
aws docdb delete-db-instance --db-instance-identifier bookshelf-orders-sl-1
aws docdb delete-db-cluster --db-cluster-identifier bookshelf-orders-sl --skip-final-snapshot
aws docdb-elastic delete-cluster --cluster-arn "$ELASTIC_CLUSTER_ARN"

# Application secret (recovery window keeps it restorable for 7 days)
aws secretsmanager delete-secret --secret-id bookshelf/orders/docdb --recovery-window-in-days 7

# Private networking you created for this page
aws ec2 delete-security-group --group-id "$DB_SG"

The managed master-user secret (rds!cluster-…​) is deleted with the cluster. If you used the CloudFormation fragment instead, aws cloudformation delete-stack removes the cluster and, because of DeletionPolicy: Snapshot, leaves a final snapshot to delete separately. For Atlas: terminate the cluster in the Atlas console, delete the private endpoint in Atlas, delete the interface VPC endpoint with aws ec2 delete-vpc-endpoints --vpc-endpoint-ids "$VPCE_ID", and cancel the Marketplace subscription under AWS Marketplace, Manage subscriptions so no new Atlas charges arrive.