Ctrl + K
Identifiers17 min read

MongoDB ObjectId Explained

Learn how MongoDB ObjectIds work, what their 24-character format contains, how they are generated, and how they compare with UUIDs.

Published: 2026-09-02

MongoDB ObjectId is the default identifier type commonly used for documents in MongoDB. It is a compact 12-byte value that can be represented as a 24-character hexadecimal string. ObjectId was designed to provide unique document identifiers without requiring a central counter or database-generated integer sequence.

One of the most useful properties of ObjectId is that it contains a timestamp component. This means an ObjectId is not simply a random value: part of its structure encodes information about when the identifier was generated. The remaining bytes provide additional uniqueness information.

What Is a MongoDB ObjectId?

An ObjectId is a BSON type used by MongoDB to identify documents. When MongoDB creates a document without an explicitly supplied _id value, the MongoDB driver typically generates an ObjectId and assigns it to the document.

{
  "_id": "507f1f77bcf86cd799439011",
  "name": "Example document"
}

Although ObjectId is often displayed as a hexadecimal string, the actual BSON value is a 12-byte binary identifier. The 24-character hexadecimal representation is simply a convenient textual encoding of those 12 bytes.

What Does an ObjectId Look Like?

A standard ObjectId is commonly displayed as 24 hexadecimal characters. Hexadecimal characters include digits from 0 to 9 and letters from a to f.

507f1f77bcf86cd799439011

The string contains exactly 24 hexadecimal characters, which corresponds to 12 bytes because each hexadecimal character represents four bits.

ObjectId Size

RepresentationSize
Binary ObjectId12 bytes
Bits96 bits
Hexadecimal string24 characters

The 12-byte size makes ObjectId smaller than a 128-bit UUID while still providing a very large identifier space and useful generation properties.

MongoDB ObjectId Structure

The ObjectId format consists of several components. In the traditional ObjectId design, the 12 bytes are divided into a four-byte timestamp followed by five bytes of process-unique data and a three-byte incrementing counter.

ComponentSizePurpose
Timestamp4 bytesSeconds since the Unix epoch
Random / process component5 bytesDistinguishes generators and processes
Counter3 bytesProvides uniqueness for IDs generated close together

The exact internal implementation can depend on the MongoDB driver and version. Modern drivers are responsible for generating ObjectIds according to the ObjectId specification, so applications generally should not depend on undocumented internal details beyond the documented format and behavior.

The Timestamp Component

The first four bytes of an ObjectId represent a timestamp measured in seconds since the Unix epoch. This gives ObjectId an approximate creation-time property.

ObjectId

┌──────────────┬──────────────────────┬──────────────┐
│ 4-byte time  │ 5-byte unique data  │ 3-byte count │
└──────────────┴──────────────────────┴──────────────┘

Because the timestamp has one-second resolution, an ObjectId does not record the exact millisecond at which it was generated. It provides a coarse timestamp that is useful for approximate ordering and date extraction.

Can You Get a Date From an ObjectId?

Yes. The timestamp component allows applications and MongoDB drivers to extract an approximate generation time from an ObjectId.

const id = new ObjectId("507f1f77bcf86cd799439011");

console.log(id.getTimestamp());

This timestamp should be treated as the time associated with the ObjectId's generation, not as a guaranteed document creation timestamp. Applications that need an authoritative creation date should store an explicit date field.

Does ObjectId Contain the Document Creation Date?

ObjectId contains a timestamp associated with the generation of the identifier, which often happens when a document is created. However, these are not necessarily the same event.

An application can generate an ObjectId before inserting a document, reuse an ObjectId, or explicitly provide an ObjectId that was generated earlier. Therefore, the ObjectId timestamp should not be treated as a replacement for a dedicated createdAt field when precise application-level timestamps matter.

The Unique Data Component

The next five bytes provide data intended to distinguish ObjectId generators. This component helps different processes or machines generate identifiers without requiring a shared database counter.

Modern MongoDB drivers can use random or process-specific data for this portion. Developers generally do not need to manage these bytes manually.

The Counter Component

The final three bytes act as an incrementing counter. The counter allows a generator to produce multiple ObjectIds during the same second while keeping the identifiers distinct.

A three-byte counter provides 16,777,216 possible counter values. When the counter reaches its limit, it wraps around according to the ObjectId generation algorithm.

Same timestamp
      │
      ├── counter 000001
      ├── counter 000002
      ├── counter 000003
      └── ...

Why Is ObjectId Unique?

ObjectId combines several pieces of information to make collisions extremely unlikely. The timestamp separates identifiers generated at different times, the unique component distinguishes generators, and the counter separates identifiers produced by the same generator during the same time period.

As with other distributed identifier schemes, uniqueness depends on correct implementation. ObjectId should be generated using a standard MongoDB driver or a compliant implementation rather than manually assembled without understanding the format.

Is MongoDB ObjectId Guaranteed to Be Unique?

ObjectId is designed to provide unique identifiers, but no finite identifier scheme can offer an absolute mathematical guarantee under every possible implementation error. The practical collision probability is extremely low when ObjectIds are generated correctly.

The most important practical rule is to use a trusted MongoDB driver or implementation. Do not manually generate ObjectIds by simply combining arbitrary timestamps and random values unless you specifically need to implement the format yourself.

ObjectId and Distributed Systems

ObjectId is well suited to distributed applications because an application instance can generate an identifier locally. The application does not need to ask MongoDB for the next integer before creating a document.

This is particularly useful when many application servers are connected to the same database or when an application needs to create identifiers before a database write occurs.

  • No central counter is required.
  • Multiple processes can generate IDs independently.
  • ObjectIds can be generated before insertion.
  • The identifier contains approximate time information.
  • The binary value is only 12 bytes.

ObjectId as the MongoDB _id Field

Every MongoDB document normally has an _id field that uniquely identifies it within its collection. If an application does not provide an _id, the MongoDB driver commonly creates an ObjectId automatically.

const user = {
  name: "Alice"
};

// The MongoDB driver can assign _id automatically.
await users.insertOne(user);

After insertion, the document will have an _id value that can be used to retrieve, update or delete the document.

Can You Use a String Instead of ObjectId?

Yes. MongoDB does not require _id to be an ObjectId. An application can use strings, numbers or other supported BSON types as identifiers, provided the values are unique within the collection.

{
  "_id": "user_12345",
  "name": "Alice"
}

ObjectId is simply the conventional default for many MongoDB applications. Whether it is the best choice depends on the application's data model and integration requirements.

ObjectId vs UUID

ObjectId and UUID are both commonly used for distributed identifiers, but they have different sizes and design goals. ObjectId is 12 bytes and includes a timestamp, while UUID is 16 bytes and comes in multiple versions.

FeatureObjectIdUUID
Binary size12 bytes16 bytes
Bits96128
TimestampYesDepends on UUID version
Typical text length24 hex characters36 characters with hyphens
MongoDB integrationNative and conventionalSupported but not the default
Standardized identifier familyMongoDB-specificYes
Distributed generationYesYes

ObjectId is usually the natural choice for a MongoDB-native application. UUID can be more convenient when identifiers need to be shared across different databases, services or systems that already use UUID.

ObjectId vs UUID v4

UUID v4 is primarily random, while ObjectId includes a timestamp and generator-specific information. UUID v4 has a larger identifier space, but ObjectId provides useful time-related information directly in the value.

PropertyObjectIdUUID v4
Size96 bits128 bits
TimestampYesNo
Primary designMongoDB document identifiersRandom unique identifiers
Text form24 hex characters36 characters
MongoDB defaultYesNo
Time sortingApproximatelyNo

ObjectId vs UUID v7

UUID v7 is a useful comparison because it also provides time-ordered identifiers. Unlike ObjectId, UUID v7 is part of the standardized UUID family and uses a 128-bit structure.

FeatureObjectIdUUID v7
Binary size12 bytes16 bytes
Time informationYesYes
Time resolutionSecondsHigher-resolution timestamp
Standardized UUIDNoYes
MongoDB native defaultYesNo
Text length24 hex characters36 characters

If an application needs a MongoDB-native identifier, ObjectId remains a straightforward choice. If a standardized identifier must work consistently across many systems, UUID v7 may be more appropriate.

ObjectId vs Snowflake ID

Snowflake IDs and ObjectIds both combine time information with additional uniqueness data, but they use different formats. Snowflake identifiers are commonly 64-bit integers, while ObjectId is a 96-bit binary value.

FeatureObjectIdSnowflake ID
Binary size96 bitsUsually 64 bits
TimestampYesYes
Worker informationGenerator-specificExplicit worker component
SequenceCounterSequence component
Primary ecosystemMongoDBDistributed applications
Text representation24 hex charactersOften decimal

ObjectId vs ULID

ULID is a 128-bit identifier designed for textual use and lexicographic sorting. ObjectId is smaller and tightly integrated with MongoDB.

FeatureObjectIdULID
Binary size96 bits128 bits
Text length24 characters26 characters
TimestampYesYes
SortableApproximatelyYes
MongoDB nativeYesNo
EncodingHexadecimalCrockford Base32

ObjectId Sorting

ObjectIds have a useful ordering property because their timestamp component appears at the beginning of the binary value. In many practical cases, sorting ObjectIds gives an approximate ordering by generation time.

db.users.find().sort({ _id: 1 });

However, this should not be treated as a perfect substitute for sorting by an explicit creation timestamp. Multiple ObjectIds generated during the same second can have different counter and generator components.

ObjectId and Creation Time

Developers sometimes use the ObjectId timestamp to estimate when a document was created. This can be useful for diagnostics and simple queries, but it has important limitations.

  • The timestamp has one-second resolution.
  • The ObjectId may have been generated before the document was inserted.
  • An application can provide its own _id.
  • The ObjectId timestamp is not an explicit application-level createdAt field.

Can ObjectId Be Used Outside MongoDB?

Yes. ObjectId is a BSON type associated with MongoDB, but an application can use ObjectId values as identifiers in other systems if the format is useful. However, doing so introduces a dependency on a MongoDB-specific identifier format.

If an identifier needs to be shared widely across unrelated systems, UUID or another standardized identifier may be a better choice.

ObjectId in URLs

The 24-character hexadecimal representation is frequently used directly in MongoDB-backed URLs.

https://example.com/users/507f1f77bcf86cd799439011

This is convenient because the value can be passed directly to the backend and converted into an ObjectId for a MongoDB query.

Are ObjectIds Predictable?

ObjectIds contain a timestamp and structured generation information, so they should not be considered completely opaque random values. An observer may be able to extract or infer approximate generation time from an ObjectId.

The unique portion makes blindly guessing a specific ObjectId difficult in normal circumstances, but ObjectId should still be treated as an identifier rather than a security mechanism.

⚠️ Do not use ObjectId as a password, API secret or authorization token. If a resource must be protected from enumeration or guessing, use proper authentication and authorization and consider separate security-sensitive tokens where appropriate.

ObjectId Validation

A standard hexadecimal ObjectId string contains 24 hexadecimal characters. MongoDB drivers provide validation mechanisms for determining whether a value can be interpreted as an ObjectId.

ObjectId.isValid("507f1f77bcf86cd799439011");

Validation is important when an ObjectId is received from a URL, query parameter or API request. Invalid values should be handled before attempting a MongoDB query.

ObjectId Validation Does Not Mean Authorization

Checking whether a string is a valid ObjectId only verifies that the value has an acceptable identifier format. It does not prove that the requested document exists or that the current user is allowed to access it.

Valid ObjectId
      ↓
Does the document exist?
      ↓
Is the requester authorized?
      ↓
Return the document

Common ObjectId Mistakes

  • Treating ObjectId as a secure random token.
  • Assuming its timestamp is the exact document creation time.
  • Using the ObjectId timestamp instead of an explicit createdAt field for precise business logic.
  • Passing arbitrary strings directly into ObjectId queries without validation.
  • Assuming every 24-character hexadecimal string represents a meaningful existing document.
  • Converting ObjectIds to strings unnecessarily and losing the native BSON type inside the database model.
  • Assuming ObjectId is always better than UUID for cross-service architectures.
  • Exposing ObjectIds publicly without considering whether their time-related information is acceptable.

ObjectId Best Practices

  • Use the official MongoDB driver or a trusted library to generate ObjectIds.
  • Keep _id values as native ObjectId values when using them as MongoDB identifiers.
  • Validate user-provided ObjectId strings before querying.
  • Store explicit createdAt and updatedAt fields when application-level timestamps matter.
  • Do not use ObjectId as an authentication credential.
  • Use UUID when cross-database interoperability is a stronger requirement.
  • Consider the information exposed by ObjectId when using it in public URLs.
  • Use the native ObjectId type consistently throughout the application's data layer.

ObjectId and JSON

ObjectId is a BSON type rather than a native JSON type. When MongoDB documents are converted to JSON, ObjectId values are commonly represented using an extended JSON form or converted into strings depending on the application and serialization settings.

{
  "_id": {
    "$oid": "507f1f77bcf86cd799439011"
  }
}

This distinction matters when sending MongoDB documents through APIs. Developers should decide deliberately whether clients should receive ObjectId values as strings, extended JSON or another application-specific representation.

ObjectId and Mongoose

Mongoose commonly uses ObjectId as the default type for MongoDB document references. For example, a user document can contain an ObjectId referencing another collection.

const schema = new Schema({
  userId: {
    type: Schema.Types.ObjectId,
    ref: "User",
  },
});

This makes ObjectId particularly common in Node.js applications that use MongoDB through Mongoose.

ObjectId References

ObjectIds are frequently used to connect documents across collections. A document can store another document's ObjectId as a reference instead of duplicating the complete related object.

{
  "_id": "507f1f77bcf86cd799439011",
  "name": "Order",
  "userId": "507f191e810c19729de860ea"
}

The actual BSON values in MongoDB would be ObjectId values even though examples are often displayed as hexadecimal strings.

ObjectId Performance

ObjectId is compact enough to be practical for MongoDB indexes and primary keys. Its fixed 12-byte binary representation also avoids the larger storage requirements of many textual identifier formats.

Because ObjectIds include a timestamp component, newly generated values tend to have useful locality when indexed. Nevertheless, database performance should be evaluated using the actual workload rather than assuming that one identifier format is universally faster.

When Should You Use MongoDB ObjectId?

  • MongoDB is the primary database.
  • You want to use MongoDB's conventional _id behavior.
  • You need compact distributed identifiers.
  • Approximate generation-time information is useful.
  • Your application does not require a database-independent identifier standard.
  • You want straightforward integration with MongoDB drivers and tooling.

When Should You Use UUID Instead?

  • The same identifiers are shared across multiple databases.
  • External APIs already use UUID.
  • Your architecture is database-independent.
  • You need a standardized identifier family.
  • You want to use UUID v7 for standardized time ordering.
  • Your team already has strong UUID tooling and conventions.

ObjectId Decision Guide

RequirementGood Choice
MongoDB-native document IDsObjectId
Standard random identifierUUID v4
Standard time-sortable identifierUUID v7
Time-sortable textual identifierULID
Time-sortable identifier with large random payloadKSUID
Compact distributed numeric identifierSnowflake ID
Short configurable random IDNano ID

Frequently Asked Questions

What is MongoDB ObjectId?

ObjectId is a 12-byte BSON identifier commonly used as MongoDB's default _id value. Its standard textual representation is a 24-character hexadecimal string.

How does MongoDB ObjectId work?

An ObjectId combines a timestamp with additional generator-specific and counter information to produce identifiers that are compact, distributed, and highly unlikely to collide.

How long is a MongoDB ObjectId?

An ObjectId is 12 bytes, or 96 bits. Its standard hexadecimal representation contains 24 characters.

Does MongoDB ObjectId contain a timestamp?

Yes. The first four bytes contain a timestamp measured in seconds since the Unix epoch. This allows the approximate generation time of an ObjectId to be determined.

Can you get the date from an ObjectId?

Yes. MongoDB drivers can extract the timestamp from an ObjectId. It represents the identifier's generation time and should not be treated as the exact document creation timestamp.

Is MongoDB ObjectId unique?

ObjectId is designed to make accidental collisions extremely unlikely by combining timestamp information with generator-specific data and a counter. It is intended to provide unique identifiers without requiring a centralized sequence.

Can I use a UUID instead of ObjectId in MongoDB?

Yes. MongoDB supports UUID and other BSON types as _id values. ObjectId is simply the conventional default for many MongoDB applications.

Is ObjectId better than UUID?

Neither is universally better. ObjectId is compact and closely integrated with MongoDB, while UUID is a standardized 128-bit identifier that can be convenient when the same identifier format is shared across different systems.

Helpful Identifier and JSON Tools

A Mongo ObjectId Generator can create ObjectId values for development and testing. A UUID Generator and UUID Validator are useful when comparing or validating alternative identifiers. JSON Formatter and JSON Validator can help inspect MongoDB document structures and validate JSON data used with APIs.

Conclusion

MongoDB ObjectId is a compact 12-byte identifier designed for distributed document generation. Its structure combines a timestamp with generator-specific data and a counter, allowing applications to create unique document IDs without relying on a centralized numeric sequence.

ObjectId's timestamp also makes it useful for approximate chronological ordering and diagnostics. However, it should not be treated as an exact creation timestamp or as a security mechanism.

For MongoDB-native applications, ObjectId is often the simplest and most natural identifier choice. For systems that need database-independent identifiers, standardized UUIDs, UUID v7, ULID, KSUID or Snowflake IDs may be better depending on the requirements for size, ordering, interoperability and generation strategy.

Found an issue?

Found an error, outdated information, or something missing from this article? Let me know through the Contact page.

Your feedback helps improve our articles and keep them accurate and useful.