← Back to DevBytes

DocumentDB: Complete Setup and Configuration Guide

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

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

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:

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.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles