What is Amazon DocumentDB?
Amazon DocumentDB (with MongoDB compatibility) is a fully managed, highly available, and scalable document database service provided by AWS. It is designed to store, query, and index JSON-like documents — the same data format that powers modern web and mobile applications. DocumentDB implements the MongoDB 3.6, 4.0, and 5.0 API protocols, making it compatible with existing MongoDB drivers, tools, and applications while removing the operational burden of managing MongoDB clusters yourself.
At its core, DocumentDB decouples compute and storage, allowing each to scale independently. The storage layer is distributed, fault-tolerant, and self-healing, automatically replicating your data six ways across three Availability Zones. The compute layer consists of instances that process read/write operations and serve your queries.
Key Architecture Concepts
- Clusters: A cluster consists of 0–16 instances (primary + replicas) and a cluster storage volume
- Instances: The compute capacity running the database engine — either primary (read/write) or replica (read-only)
- Cluster Storage Volume: Fully managed SSD-based storage that grows automatically up to 64 TiB
- Endpoints: Cluster endpoint (connects to primary), reader endpoint (load-balances across replicas), and instance endpoints
- Security Groups: Virtual firewalls controlling inbound/outbound traffic to your cluster
Why DocumentDB Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Choosing the right database is a critical architectural decision. DocumentDB addresses several real-world pain points that teams face when running document databases at scale:
Operational Relief
Self-managing MongoDB means handling backups, patching, monitoring, failover, replication, scaling, and security patching. DocumentDB automates all of this. AWS handles the undifferentiated heavy lifting so your team can focus on building features.
High Availability by Default
DocumentDB clusters span multiple Availability Zones. In the event of a primary instance failure, automatic failover promotes a replica within 30–120 seconds. The cluster endpoint automatically points to the new primary, minimizing downtime without application changes.
Scalability Without Downtime
You can add replicas in minutes (up to 15 per cluster) to handle read-heavy workloads. Compute scaling (vertical) supports instance sizes from t3.medium to r6g.16xlarge, and you can modify instances with minimal interruption. Storage scales automatically from 10 GiB to 64 TiB with no pre-provisioning.
Enterprise-Grade Security
DocumentDB integrates with AWS KMS for encryption at rest, supports VPC isolation, IAM-based authentication, and TLS-encrypted connections in transit. Audit logging captures all authentication and data events for compliance.
Complete Setup Guide
Prerequisites
- An AWS account with appropriate IAM permissions (DocumentDB full access or admin role)
- A VPC with at least two subnets in different Availability Zones
- AWS CLI installed and configured (optional but recommended)
- A security group allowing inbound traffic on port 27017 from your application hosts
Step 1: Create a Security Group
Navigate to the EC2 console, select Security Groups, and create one for DocumentDB. Add an inbound rule allowing TCP port 27017 from your application's security group or CIDR range.
# AWS CLI example — create a security group for DocumentDB
aws ec2 create-security-group \
--group-name docdb-access-sg \
--description "Security group for DocumentDB cluster access" \
--vpc-id vpc-0abc123def456gh
# Authorize inbound MongoDB traffic on port 27017
aws ec2 authorize-security-group-ingress \
--group-id sg-0abc123def456ghi \
--protocol tcp \
--port 27017 \
--cidr 10.0.0.0/16 # Replace with your actual CIDR or source SG
Step 2: Create a DB Subnet Group
DocumentDB requires a subnet group that specifies which subnets the cluster can use. You need subnets in at least two Availability Zones.
aws docdb create-db-subnet-group \
--db-subnet-group-name docdb-subnet-group \
--db-subnet-group-description "Subnet group for DocumentDB cluster" \
--subnet-ids subnet-abc123 subnet-def456 subnet-ghi789
Step 3: Create the DocumentDB Cluster
When you create a cluster, you specify the instance class, number of instances, engine version, and security groups. The primary instance is created automatically.
aws docdb create-db-cluster \
--db-cluster-identifier my-docdb-cluster \
--engine docdb \
--engine-version "5.0.0" \
--master-username "adminUser" \
--master-user-password "YourSecurePassword123!" \
--db-subnet-group-name docdb-subnet-group \
--vpc-security-group-ids sg-0abc123def456ghi \
--storage-encrypted \
--kms-key-id arn:aws:kms:us-east-1:123456789:key/your-kms-key-id \
--enable-cloudwatch-logs-exports '["audit","profiler"]' \
--backup-retention-period 7 \
--preferred-backup-window "03:00-04:00" \
--preferred-maintenance-window "sun:05:00-sun:06:00"
Wait for the cluster to reach available status. Then create the primary instance:
aws docdb create-db-instance \
--db-instance-identifier my-docdb-instance-1 \
--db-instance-class db.r6g.large \
--engine docdb \
--db-cluster-identifier my-docdb-cluster
# Optional: add a replica instance for read scaling and HA
aws docdb create-db-instance \
--db-instance-identifier my-docdb-instance-2 \
--db-instance-class db.r6g.large \
--engine docdb \
--db-cluster-identifier my-docdb-cluster
Step 4: Retrieve Connection Endpoints
Once the cluster is available, fetch the endpoints. The cluster endpoint always routes to the primary instance. The reader endpoint load-balances across replicas.
aws docdb describe-db-clusters \
--db-cluster-identifier my-docdb-cluster \
--query "DBClusters[0].[Endpoint,ReaderEndpoint,Port]" \
--output text
You'll get output similar to:
my-docdb-cluster.cluster-abc123.us-east-1.docdb.amazonaws.com
my-docdb-cluster.cluster-ro-abc123.us-east-1.docdb.amazonaws.com
27017
Connecting to Your DocumentDB Cluster
Connection Methods
DocumentDB supports several authentication methods. The most common is username/password via SCRAM-SHA-256. You can also use IAM authentication, which allows you to use AWS credentials to connect.
Standard MongoDB Driver Connection
Use the MongoDB-compatible connection string format. Replace the placeholders with your actual endpoints and credentials.
# Standard connection string format
mongodb://adminUser:YourSecurePassword123!@my-docdb-cluster.cluster-abc123.us-east-1.docdb.amazonaws.com:27017/?ssl=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
Node.js Example (MongoDB Native Driver)
Install the MongoDB driver: npm install mongodb
const { MongoClient } = require('mongodb');
// Connection URI — use the cluster endpoint for writes, reader endpoint for reads
const uri = 'mongodb://adminUser:YourSecurePassword123!@' +
'my-docdb-cluster.cluster-abc123.us-east-1.docdb.amazonaws.com:27017/' +
'?ssl=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false';
async function connectAndOperate() {
const client = new MongoClient(uri, {
tls: true,
tlsCAFile: '/path/to/rds-ca-2019-root.pem', // Download from AWS documentation
serverSelectionTimeoutMS: 5000,
connectTimeoutMS: 10000
});
try {
await client.connect();
console.log('Connected successfully to DocumentDB');
const database = client.db('myApplication');
const collection = database.collection('users');
// Insert a document
const insertResult = await collection.insertOne({
name: 'Jane Doe',
email: 'jane.doe@example.com',
createdAt: new Date(),
metadata: {
role: 'admin',
department: 'engineering',
preferences: { theme: 'dark', notifications: true }
}
});
console.log(`Inserted document with _id: ${insertResult.insertedId}`);
// Find documents with a filter
const cursor = collection.find({
'metadata.role': 'admin',
'metadata.department': 'engineering'
}).limit(10);
const users = await cursor.toArray();
console.log(`Found ${users.length} matching users`);
// Update a document
const updateResult = await collection.updateOne(
{ email: 'jane.doe@example.com' },
{ $set: { 'metadata.preferences.theme': 'light' } }
);
console.log(`Modified ${updateResult.modifiedCount} document(s)`);
// Create an index for query performance
await collection.createIndex({ email: 1 }, { unique: true });
console.log('Created unique index on email field');
} catch (error) {
console.error('DocumentDB operation failed:', error);
} finally {
await client.close();
console.log('Connection closed');
}
}
connectAndOperate();
Python Example (PyMongo)
Install PyMongo: pip install pymongo
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure, OperationFailure
import datetime
import os
# Connection URI
DOCDB_URI = (
"mongodb://adminUser:YourSecurePassword123!@"
"my-docdb-cluster.cluster-abc123.us-east-1.docdb.amazonaws.com:27017/"
"?ssl=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false"
)
# Path to the AWS RDS CA bundle for TLS verification
CA_FILE = "/path/to/rds-ca-2019-root.pem"
def connect_and_operate():
client = MongoClient(
DOCDB_URI,
tls=True,
tlsCAFile=CA_FILE,
serverSelectionTimeoutMS=5000,
connectTimeoutMS=10000,
maxPoolSize=50,
minPoolSize=10
)
try:
# Verify connection is alive
client.admin.command('ping')
print("Successfully connected to DocumentDB")
db = client.myApplication
collection = db.users
# Insert multiple documents efficiently
bulk_docs = [
{
"name": f"User_{i}",
"email": f"user_{i}@example.com",
"createdAt": datetime.datetime.utcnow(),
"score": i * 100,
"tags": ["automated", "test"] if i % 2 == 0 else ["manual"]
}
for i in range(1, 101)
]
insert_result = collection.insert_many(bulk_docs)
print(f"Inserted {len(insert_result.inserted_ids)} documents in bulk")
# Aggregation pipeline example
pipeline = [
{"$match": {"tags": "automated"}},
{"$group": {
"_id": None,
"averageScore": {"$avg": "$score"},
"totalUsers": {"$sum": 1}
}},
{"$project": {
"_id": 0,
"averageScore": 1,
"totalUsers": 1
}}
]
agg_result = list(collection.aggregate(pipeline))
if agg_result:
print(f"Aggregation result: avg score = {agg_result[0]['averageScore']:.2f}, "
f"total users = {agg_result[0]['totalUsers']}")
# Delete documents based on a condition
delete_result = collection.delete_many({"score": {"$lt": 200}})
print(f"Deleted {delete_result.deleted_count} low-score documents")
except ConnectionFailure as e:
print(f"Connection failed: {e}")
except OperationFailure as e:
print(f"Operation failed: {e}")
finally:
client.close()
print("Connection closed gracefully")
if __name__ == "__main__":
connect_and_operate()
Java Example (MongoDB Java Driver)
Add the MongoDB driver dependency in your pom.xml:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.11.1</version>
</dependency>
Java connection and operation code:
import com.mongodb.*;
import com.mongodb.client.*;
import com.mongodb.client.model.*;
import org.bson.Document;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
public class DocumentDBExample {
private static final String CONNECTION_URI =
"mongodb://adminUser:YourSecurePassword123!@" +
"my-docdb-cluster.cluster-abc123.us-east-1.docdb.amazonaws.com:27017/" +
"?ssl=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false";
public static void main(String[] args) {
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(CONNECTION_URI))
.applyToSslSettings(builder -> builder.enabled(true))
.build();
try (MongoClient mongoClient = MongoClients.create(settings)) {
MongoDatabase database = mongoClient.getDatabase("myApplication");
MongoCollection collection = database.getCollection("products");
// Check connection
database.runCommand(new Document("ping", 1));
System.out.println("Connected to DocumentDB successfully");
// Create a compound index
collection.createIndex(
new Document("category", 1).append("price", -1),
new IndexOptions().name("category_price_idx")
);
// Insert a document
Document product = new Document()
.append("name", "Wireless Headphones")
.append("category", "electronics")
.append("price", 89.99)
.append("stock", 150)
.append("tags", Arrays.asList("wireless", "bluetooth", "audio"));
collection.insertOne(product);
System.out.println("Product inserted");
// Find with filters and projection
Document filter = new Document("category", "electronics")
.append("price", new Document("$lt", 100));
Document projection = new Document("name", 1)
.append("price", 1)
.append("_id", 0);
FindIterable results = collection
.find(filter)
.projection(projection)
.sort(new Document("price", 1))
.limit(20);
for (Document doc : results) {
System.out.println("Product: " + doc.toJson());
}
// Update with upsert
UpdateResult updateResult = collection.updateOne(
new Document("name", "Wireless Headphones"),
new Document("$set", new Document("stock", 145))
.append("$inc", new Document("sold", 5)),
new UpdateOptions().upsert(true)
);
System.out.println("Modified: " + updateResult.getModifiedCount() +
", Upserted: " + updateResult.getUpsertedId());
} catch (MongoException e) {
System.err.println("MongoDB/DocumentDB error: " + e.getMessage());
}
}
}
IAM Authentication Setup
DocumentDB supports AWS Identity and Access Management (IAM) authentication, which eliminates the need to store long-lived database passwords in your application. Instead, you use temporary AWS credentials to connect.
Enable IAM Authentication on the Cluster
aws docdb modify-db-cluster \
--db-cluster-identifier my-docdb-cluster \
--enable-iam-database-authentication
Create an IAM User and Policy
# Create an IAM policy document for DocumentDB access
cat > docdb-iam-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-ABC123XYZ/adminUser"
]
}
]
}
EOF
# Attach the policy to your application's IAM role or user
aws iam put-user-policy \
--user-name app-docdb-user \
--policy-name docdb-connect-policy \
--policy-document file://docdb-iam-policy.json
Connect Using IAM Authentication (Python)
import boto3
import pymongo
from pymongo.auth import MongoCredential
from urllib.parse import quote_plus
# Generate an IAM authentication token
def get_iam_token(cluster_endpoint, port, username, region):
client = boto3.client('rds', region_name=region)
# Generate a pre-signed URL valid for 15 minutes
token = client.generate_db_auth_token(
DBHostname=cluster_endpoint,
Port=port,
DBUsername=username,
Region=region
)
return token
# Use the token to connect
CLUSTER_ENDPOINT = "my-docdb-cluster.cluster-abc123.us-east-1.docdb.amazonaws.com"
PORT = 27017
USERNAME = "adminUser"
REGION = "us-east-1"
token = get_iam_token(CLUSTER_ENDPOINT, PORT, USERNAME, REGION)
# URL-encode the token for the connection string
encoded_token = quote_plus(token)
connection_uri = (
f"mongodb://{USERNAME}:{encoded_token}@"
f"{CLUSTER_ENDPOINT}:{PORT}/"
f"?ssl=true&replicaSet=rs0&authSource=$external&authMechanism=MONGODB-AWS"
)
client = pymongo.MongoClient(connection_uri, tls=True)
# Test the connection
client.admin.command('ping')
print("IAM-authenticated connection successful")
Monitoring and Maintenance
CloudWatch Metrics
DocumentDB automatically publishes metrics to Amazon CloudWatch. Key metrics to monitor:
- DatabaseConnections: Current number of client connections
- CPUUtilization: Instance CPU usage percentage
- FreeableMemory: Available RAM in bytes
- VolumeBytesUsed: Storage consumed by the cluster
- ReadIOPS / WriteIOPS: Storage I/O operations per second
- DatabaseThroughput: Total network throughput in bytes per second
Setting Up CloudWatch Alarms
# Alarm for high CPU utilization
aws cloudwatch put-metric-alarm \
--alarm-name docdb-high-cpu \
--alarm-description "Alert when CPU exceeds 80% for 5 minutes" \
--namespace "AWS/DocDB" \
--metric-name "CPUUtilization" \
--dimensions "Name=DBInstanceIdentifier,Value=my-docdb-instance-1" \
--statistic "Average" \
--period 300 \
--evaluation-periods 1 \
--threshold 80 \
--comparison-operator "GreaterThanThreshold" \
--alarm-actions arn:aws:sns:us-east-1:123456789:docdb-alerts
# Alarm for low free memory
aws cloudwatch put-metric-alarm \
--alarm-name docdb-low-memory \
--alarm-description "Alert when free memory drops below 1GB" \
--namespace "AWS/DocDB" \
--metric-name "FreeableMemory" \
--dimensions "Name=DBInstanceIdentifier,Value=my-docdb-instance-1" \
--statistic "Average" \
--period 300 \
--evaluation-periods 2 \
--threshold 1000000000 \
--comparison-operator "LessThanThreshold" \
--alarm-actions arn:aws:sns:us-east-1:123456789:docdb-alerts
Backup and Restore
DocumentDB automatically performs daily snapshots retained for the period you specify (1–35 days). You can also trigger manual snapshots:
# Create a manual snapshot
aws docdb create-db-cluster-snapshot \
--db-cluster-snapshot-identifier my-manual-snapshot-2025-01-15 \
--db-cluster-identifier my-docdb-cluster
# Restore from a snapshot to a new cluster
aws docdb restore-db-cluster-from-snapshot \
--db-cluster-identifier restored-cluster-prod \
--snapshot-identifier my-manual-snapshot-2025-01-15 \
--engine docdb \
--db-subnet-group-name docdb-subnet-group \
--vpc-security-group-ids sg-0abc123def456ghi
# After the cluster is available, create instances in the restored cluster
aws docdb create-db-instance \
--db-instance-identifier restored-instance-1 \
--db-instance-class db.r6g.large \
--engine docdb \
--db-cluster-identifier restored-cluster-prod
Best Practices for DocumentDB
1. Connection Management
Use connection pooling in your application drivers. DocumentDB instances have connection limits based on instance size. For example, a db.r6g.large instance supports approximately 2,500 connections. Configure your driver's maxPoolSize appropriately and implement retry logic with exponential backoff for transient failures.
// Connection pool tuning example (Node.js)
const client = new MongoClient(uri, {
maxPoolSize: 100, // Limit concurrent connections per app instance
minPoolSize: 10, // Maintain a warm pool for low latency
maxIdleTimeMS: 60000, // Close idle connections after 60 seconds
waitQueueTimeoutMS: 5000, // Fail fast if pool is exhausted
retryWrites: true,
retryReads: true
});
2. Indexing Strategy
DocumentDB supports compound, sparse, unique, TTL, text, and geospatial indexes. Always create indexes for query patterns you run frequently. Use the explain() method to verify index usage. Avoid creating too many indexes — each index adds write overhead.
// Create indexes aligned to your query patterns
db.users.createIndex({ "email": 1 }, { unique: true, background: true });
db.orders.createIndex({ "customerId": 1, "createdAt": -1 });
db.sessions.createIndex({ "lastAccess": 1 }, { expireAfterSeconds: 3600 }); // TTL index
3. Use the Reader Endpoint for Read Scaling
Route analytical queries, reporting jobs, and read-heavy operations to the reader endpoint. This distributes load across replicas and preserves primary capacity for writes. Set readPreference=secondaryPreferred in your connection string for read-heavy workloads.
4. Batch Operations and Bulk Writes
When inserting or updating many documents, use bulk write operations. DocumentDB processes bulk writes efficiently and reduces network round-trips.
# Python bulk write example
from pymongo import UpdateOne, InsertOne
bulk_operations = [
InsertOne({"name": "item_1", "qty": 10}),
InsertOne({"name": "item_2", "qty": 20}),
UpdateOne({"name": "item_1"}, {"$inc": {"qty": 5}}),
UpdateOne({"name": "item_3"}, {"$set": {"qty": 15}}, upsert=True),
]
result = collection.bulk_write(bulk_operations, ordered=False)
print(f"Inserted: {result.inserted_count}, Modified: {result.modified_count}, "
f"Upserted: {result.upserted_count}")
5. Avoid Large in-memory Operations
DocumentDB instances have finite memory. Avoid operations that pull huge result sets into memory. Use cursors with appropriate batch sizes, and leverage aggregation pipelines with $match early to reduce data processed. For large result sets, stream documents using cursor iteration rather than fetching all at once.
6. Monitor and Right-Size
Regularly review CloudWatch metrics. If CPUUtilization consistently exceeds 70%, consider scaling up your instance class or adding replicas. Monitor VolumeBytesUsed to track storage growth. Use DatabaseConnections to ensure you're not approaching connection limits.
7. Encryption and Security
Always enable encryption at rest via AWS KMS. Enforce TLS connections (ssl=true) in all connection strings. Use VPC security groups to restrict access. Rotate credentials regularly and consider IAM authentication for credential-free access. Enable audit logging for compliance tracking.
8. Handle Failover Gracefully
Implement retry logic that handles MongoServerSelectionError and transient network errors. During a failover (typically 30–120 seconds), your application should retry with backoff. The cluster endpoint automatically resolves to the new primary after failover completes.
// Retry with exponential backoff (Node.js)
async function withRetry(operation, maxRetries = 5) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (error.code === 'ETIMEDOUT' || error.message.includes('ServerSelection')) {
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
console.log(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error; // Non-transient error, rethrow immediately
}
}
throw lastError;
}
// Usage
const result = await withRetry(() => collection.findOne({ _id: docId }));
9. Tag Resources for Cost Management
Apply AWS tags to your clusters and instances for cost allocation and environment identification:
aws docdb add-tags-to-resource \
--resource-name arn:aws:rds:us-east-1:123456789:cluster:my-docdb-cluster \
--tags "Key=Environment,Value=production" \
"Key=Team,Value=platform-engineering" \
"Key=CostCenter,Value=CC-4567"
10. Test Your Backup Strategy
Regularly restore snapshots to a staging environment to validate backup integrity and document your recovery procedure. Time how long restoration takes so you can set realistic RTO (Recovery Time Objective) expectations.
Conclusion
Amazon DocumentDB provides a compelling managed document database solution that combines MongoDB compatibility with the operational reliability of AWS infrastructure. By decoupling compute and storage, offering automatic failover, and scaling storage transparently up to 64 TiB, it removes the traditional pain points of running document databases in production. The setup process — from creating security groups and subnet groups to provisioning clusters and instances — is straightforward whether you use the AWS Console, CLI, or infrastructure-as-code tools like CloudFormation or Terraform.
Connecting your applications requires minimal changes: standard MongoDB drivers work natively, and you gain the flexibility of password-based or IAM-based authentication. By following best practices around connection pooling, indexing, read/write routing, monitoring, and failover handling, you can build resilient, high-performance applications on DocumentDB. The service's integration with CloudWatch, KMS encryption, VPC isolation, and audit logging ensures you meet security and compliance requirements without additional overhead. Whether you're migrating from self-managed MongoDB or starting a new document database project, DocumentDB offers a robust foundation that lets your team focus on application logic rather than database administration.