Generate UUID in MongoDB
MongoDB supports UUID as a native BSON type (subtype 4). You can use ObjectId (MongoDB's default 12-byte ID) or store proper RFC 4122 UUIDs — both are indexed efficiently.
Quick Reference
| Type | Size | Sortable | Use Case |
|---|---|---|---|
| ObjectId | 12 bytes | Yes (time-ordered) | Default MongoDB ID — recommended for pure MongoDB apps |
| UUID (BSON subtype 4) | 16 bytes | No (v4 random) | Cross-system compatibility, RFC 4122 compliance |
| UUID string | 36+ bytes | No | Simple but less efficient — avoid for high-volume collections |
Primary Implementation
import { MongoClient, UUID, ObjectId } from 'mongodb';
const client = new MongoClient(process.env.MONGODB_URI);
const db = client.db('myapp');
const col = db.collection('orders');
// ── Option 1: ObjectId (MongoDB default — recommended for pure MongoDB) ──
const docWithObjectId = {
_id: new ObjectId(), // 12-byte, time-ordered
customer: 'Alice',
total: 99.99,
};
await col.insertOne(docWithObjectId);
console.log(docWithObjectId._id.toString());
// → "663116800000000000000000"
// ── Option 2: UUID BSON type (RFC 4122 compatible) ────────────────────
const docWithUUID = {
_id: new UUID(), // 16-byte BSON UUID subtype 4
customer: 'Bob',
total: 149.99,
};
await col.insertOne(docWithUUID);
console.log(docWithUUID._id.toString());
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"
// ── Option 3: UUID string (simple, less efficient) ────────────────────
import { randomUUID } from 'crypto';
const docWithStringUUID = {
_id: randomUUID(), // plain string
customer: 'Carol',
total: 199.99,
};
await col.insertOne(docWithStringUUID);
All Approaches
Mongoose schema with UUID _id
import mongoose from 'mongoose';
import { randomUUID } from 'crypto';
const orderSchema = new mongoose.Schema({
_id: {
type: String,
default: () => randomUUID(), // UUID v4 string as _id
},
customer: { type: String, required: true },
total: { type: Number, required: true },
status: { type: String, enum: ['pending', 'paid', 'shipped'], default: 'pending' },
}, {
_id: false, // disable auto ObjectId generation
timestamps: true,
});
const Order = mongoose.model('Order', orderSchema);
// Create an order — UUID auto-assigned
const order = await Order.create({ customer: 'Alice', total: 99.99 });
console.log(order._id); // → "f47ac10b-58cc-4372-a567-0e02b2c3d479"
MongoDB shell — UUID in mongosh
// In mongosh (MongoDB Shell)
// Generate a UUID
const id = UUID();
print(id.toString()); // → "f47ac10b-58cc-4372-a567-0e02b2c3d479"
// Insert with UUID _id
db.orders.insertOne({
_id: UUID(),
customer: 'Alice',
total: 99.99,
});
// Query by UUID
db.orders.findOne({
_id: UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')
});
// Generate ObjectId (default)
const oid = new ObjectId();
print(oid.toString()); // → "663116800000000000000000"
print(oid.getTimestamp()); // → 2024-04-30T00:00:00.000Z
Python — PyMongo with UUID
import uuid
from pymongo import MongoClient
from bson.binary import Binary, UuidRepresentation
from bson.codec_options import CodecOptions
client = MongoClient("mongodb://localhost:27017")
db = client["myapp"]
# Configure UUID representation (STANDARD = RFC 4122 BSON subtype 4)
opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD)
col = db.get_collection("orders", codec_options=opts)
# Insert with UUID _id
order_id = uuid.uuid4()
col.insert_one({"_id": order_id, "customer": "Alice", "total": 99.99})
# Query by UUID
doc = col.find_one({"_id": order_id})
print(doc["_id"]) # → UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')
Common Mistakes
Mixing UUID string and UUID BSON type in the same collection
If some documents store _id as a plain string and others as a BSON UUID, queries will fail to match across types. Pick one representation and use it consistently. The BSON UUID type is more efficient but requires driver support.
Not configuring UuidRepresentation in PyMongo
PyMongo's default UUID representation is PYTHON_LEGACY — not compatible with other drivers. Always set UuidRepresentation.STANDARD in CodecOptions for cross-driver compatibility.
Using UUID when ObjectId is sufficient
If your app is purely MongoDB and doesn't need to interoperate with relational databases or external systems, ObjectId is the better choice — it's 12 bytes (vs 16 for UUID), time-ordered by default, and has first-class MongoDB driver support.
ObjectId vs UUID
ObjectId is MongoDB's native 12-byte ID: 4 bytes timestamp + 5 bytes random machine ID + 3 bytes incrementing counter. It's time-ordered, compact, and has zero configuration overhead.
UUID (BSON subtype 4) is a 16-byte RFC 4122 v4 UUID. Use it when you need to share IDs with relational databases, external APIs, or systems that expect standard UUIDs.
Both are indexed efficiently in MongoDB's WiredTiger storage engine.
Output Formats
new ObjectId().toString()
663116800000000000000000
new UUID().toString()
f47ac10b-58cc-4372-a567-0e02b2c3d479
randomUUID() (string)
f47ac10b-58cc-4372-a567-0e02b2c3d479
Best Practices
Use ObjectId for pure MongoDB apps — it's smaller, time-ordered, and has first-class support.
Use BSON UUID type (not string) when you need RFC 4122 UUIDs — it's 16 bytes vs 36+ bytes for strings.
Be consistent — pick one ID type per collection and never mix them.
Performance
ObjectId is 12 bytes and time-ordered — sequential inserts are cache-friendly and index-efficient. UUID v4 is 16 bytes and random — causes some B-tree fragmentation on very large collections.
For write-heavy collections with 100M+ documents, ObjectId or a time-ordered UUID (v7) will outperform random UUID v4 as the primary key.
Driver Support
Security
MongoDB's UUID() in mongosh and the driver's new UUID() use the platform CSPRNG — cryptographically secure.
ObjectId is not suitable for security-sensitive IDs — it encodes a timestamp and is partially predictable. Use UUID v4 for session tokens and API keys stored in MongoDB.