Java UUID vs MongoDB UUID conversion guide - cover art

MongoDB and UUID 15 min read

Java UUID and MongoDB conversion: subtype 3, subtype 4, and drivers

July 17, 2026 · 15 min read

Java’s java.util.UUID is the reference implementation most developers trust for canonical string form - lowercase hex with hyphens, version nibble in the right place, variant bits set correctly. MongoDB, however, does not store “a Java UUID”; it stores BSON Binary with a subtype that declares byte order. The Java driver’s UuidRepresentation setting decides whether those sixteen bytes match RFC 4122 (subtype 04) or legacy GUID layout (subtype 03). Misconfigure it once and every other language in your architecture will think Java is generating “different” identifiers.

What Java gives you for free

UUID.fromString parses canonical input strictly in most versions; UUID.randomUUID() generates version 4 values suitable for primary keys when collision resistance and random distribution meet your requirements. getMostSignificantBits and getLeastSignificantBits expose the 128-bit value as two longs, which some older codecs used to build BSON payloads manually - avoid new code that does this unless you are implementing a vetted conversion routine.

Java 8+ also offers name-based UUIDs and, in newer releases, additional standards - still map them to the same BSON rules: sixteen bytes plus correct subtype.

MongoDB Java driver BSON mapping

Modern MongoDB Java drivers expose UuidRepresentation.STANDARD for subtype 04 and legacy modes for compatibility. Connection string parameters and MongoClientSettings builder methods set the default for encode and decode. Changing representation on an existing database without migration permutes bytes relative to other services still on the old setting.

MongoClientSettings settings = MongoClientSettings.builder()
    .uuidRepresentation(UuidRepresentation.STANDARD)
    .applyConnectionString(new ConnectionString(uri))
    .build();
MongoClient client = MongoClients.create(settings);

UUID id = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");
collection.insertOne(new Document("_id", id));

Document _id fields typed as UUID in POJOs rely on the same codec pipeline. If only some fields use UUID while others use String, you will see the classic string-versus-binary query miss forever.

Spring Data MongoDB considerations

Spring Data maps @Id UUID fields through the underlying driver configuration. Ensure your MongoCustomConversions do not register duplicate converters that fight the global UUID representation. Multi-tenant apps that clone MongoTemplate instances must propagate UUID settings to each factory bean, not only the primary datasource.

Repository query methods accept UUID parameters when the stored BSON type matches. Integration tests using embedded Mongo or Testcontainers should assert raw BSON with a small helper that reads subtype from the document, not only assert string equality on returned entities.

Interop with Node, Python, and .NET services

When Java emits subtype 04 and Node reads with standard UUID class, round-trip is painless. When a legacy .NET API still writes subtype 03, Java must either read with legacy representation or convert at the anti-corruption layer. Do not rely on string IDs passed between services as proof of binary equality - always verify bytes in contract tests.

Kafka Avro or Protobuf schemas often carry UUID as string. Consumers that write to MongoDB should parse to UUID in Java once, then persist binary - duplicating string and binary in the same document is a maintenance tax unless analytics explicitly needs both.

Testing and CI guards for Java teams

Add unit tests with fixed vectors: known canonical string, expected subtype 04 hex, and (if you support legacy) expected subtype 03 hex. Run them in CI whenever the MongoDB driver or Spring BOM version bumps. Failing early prevents week-long hunts for “Java broke UUIDs.”

For local debugging, log canonical string and base64 payload together in structured JSON logs - but redact in production if IDs are sensitive. Developers can paste either form into conversion tools without shell access to prod.

If you run GraalVM native images or modular JPMS layouts, verify UUID codecs still load from the same service loader paths as your JVM dev environment - subtle packaging bugs have shipped apps that wrote strings while integration tests used binary.

Align with your security team on whether UUID primary keys are considered opaque secrets; they are not sequential like integers, but they still identify rows in URLs. Binary storage does not change exposure if logs print canonical strings everywhere.

Record the driver and Spring Data versions in your service catalog entry for each MongoDB consumer. When platform teams bump BOMs centrally, UUID regression tests should run automatically in each service’s pipeline - not only in the shared library that wraps the driver.

For virtual threads and reactive stacks, ensure UUID codecs remain thread-safe and stateless; representation is configured once per client, not per request, and sharing a misconfigured client bean across modules amplifies bugs quickly.

FAQ

Should Java apps use STANDARD or LEGACY UUID representation?
Use STANDARD (subtype 04) for new systems. Use LEGACY only when reading existing subtype-03 data without migration yet.
Does java.util.UUID match MongoDB subtype 04 bytes?
When the driver is configured for STANDARD representation, yes - the sixteen-byte payload matches RFC 4122 order.
Can I store UUID as String in MongoDB from Java?
Yes, but you lose compact indexes and risk case and hyphen inconsistencies. Binary UUID is preferred for _id fields.
How do I migrate Java-written subtype 03 to 04?
Run a batch permutation on the first twelve bytes, update subtype to 04, and upgrade driver settings in the same release window with verification.

Related: Subtype 03 vs 04 · Fix endianness · Binary to string · MongoDB UUID converter

Browse all tools