GUID/UUID vs ULID - Which Identifier Should You Use?

GUIDs / UUIDs are the most widely supported identifiers across databases, APIs and programming languages. However, many systems also use ULID (Universally Unique Lexicographically Sortable Identifier) as an alternative to achieve better time-ordering, improved database index locality and a more human-friendly encoding.

Quick recommendation: For the safest, standards-based choice, use GUID / UUID v4 (fully random) or GUID / UUID v7 (time-ordered for databases). Consider ULID only when you explicitly need its Base32 encoding and your ecosystem supports it.

Universally Unique Lexicographically Sortable Identifier (ULID) - github.com

Overview

Cloud platforms like AWS typically do not introduce their own GUID / UUID versions. Instead, they use standard IDs like ARNs and service-specific IDs, and sometimes standard GUIDs / UUIDs (often v4) for request/event IDs.

When choosing an identifier for your application or database schema, you're usually deciding between standard GUIDs / UUIDs (governed by RFC 9562) and ULID, a non-standard but popular GUID/UUID-like format.

Comparison table

PropertyGUID / UUID v4GUID / UUID v7 ULID
Size128-bit128-bit128-bit
EncodingHex (8-4-4-4-12)Hex (8-4-4-4-12)Base32 (26 chars)
Time-sortable No Yes (millisecond) Yes (millisecond)
StandardRFC 4122 and RFC 9562RFC 4122 and RFC 9562 No RFC
Human-readableModerate
Hex with hyphens
Moderate
Hex with hyphens
Good
Base32, case-insensitive
Database-friendlyGood
Native UUID support, but random
Excellent
Native support + sortable
Good
Often stored as text/binary
Collision resistantExcellent
122 bits random
Excellent
74 bits random
Excellent
80 bits random
Best forGeneral-purpose IDs, privacy-friendly identifiers (no embedded data) and fully randomDatabase primary keys, event ordering, time-correlated IDsHuman-friendly sortable IDs, systems already using ULIDs

Detailed comparison

GUID / UUID v4 (Random)

Structure: 128 bits with 122 bits of randomness. No timestamp information.

  • Pros: Universally supported, RFC standard, no time leakage and simple generation
  • Cons: Random insertion pattern can cause index fragmentation in some databases
  • Use when: You want maximum compatibility and don't need time-ordering

Example: 550e8400-e29b-41d4-a716-446655440000

GUID / UUID v7 (Time-ordered)

Structure: 128 bits with 48-bit Unix millisecond timestamp prefix + 74 bits randomness.

  • Pros: RFC standard, time-ordered, database-friendly and widely supported
  • Cons: Reveals creation timestamp (millisecond precision)
  • Use when: You want time-ordering with RFC compliance for database primary keys

Example: 018f3f5e-1c2d-7a9b-8f10-3c4d5e6f7a8b

ULID (Universally Unique Lexicographically Sortable Identifier)

Structure: 128 bits with 48-bit Unix millisecond timestamp + 80 bits randomness, encoded in Base32.

  • Pros: Compact representation (26 chars), case-insensitive, time-ordered and URL-safe
  • Cons: Not RFC GUID / UUID standard, requires library support and less universal than a GUID / UUID
  • Use when: You need human-friendly, sortable IDs and your stack supports ULID

Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Which one should you use?

  • Choose GUID / UUID v4 if you want the safest default: widely supported, easy to store, no embedded metadata and simple generation.
  • Choose GUID / UUID v7 if you want a standards-based ID that is time-ordered and typically behaves better as a database primary key than random GUIDs / UUIDs.
  • Choose ULID if you want time-sortable IDs and prefer a compact, human-friendly Base32 string representation and your stack already supports it.

Practical guidance for databases

If your main concern is database performance and index locality, you usually want identifiers that don't insert randomly across the index. That's the most common reason developers compare GUID / UUID v7 and ULID.

  • Most compatible: GUID / UUID v4 (works everywhere, but can be random for indexes)
  • Best "standard + sortable" combo: GUID / UUID v7 (time-ordered while staying a real GUID / UUID)
  • Non-standard but popular: ULID (sortable, but may require extra tooling and conventions)

Performance considerations

  • B-tree indexes: Time-ordered IDs (v7, ULID) reduce page splits and improve insert performance in databases using B-tree indexes (PostgreSQL, MySQL, etc.).
  • LSM-tree databases: Random IDs (v4) may perform better in some LSM-tree databases (Cassandra, ScyllaDB), but this depends on partitioning strategy.
  • Storage overhead: Both UUIDs and ULIDs are 128 bits (16 bytes), making storage comparable.

Interoperability and ecosystem support

GUID / UUID has the broadest support across programming languages, databases, and frameworks:

  • Databases: Native GUID / UUID types in PostgreSQL, MySQL, SQL Server, Oracle, etc.
  • Languages: Built-in support in Java, C#, Python, Go, Ruby, JavaScript, and many more
  • APIs: JSON, REST, GraphQL commonly use GUID / UUID for resource identifiers
  • ORMs: Entity Framework, Hibernate, Django ORM, and many others natively handle GUIDs / UUIDs

ULID requires library support and custom handling in many systems:

  • Often stored as strings or binary blobs in databases
  • Requires third-party libraries for generation and parsing
  • May need custom converters for ORMs and serialization frameworks

Other identifier formats

Beyond GUIDs / UUIDs and ULID, there are many other identifier formats each with their own trade-offs. For a comprehensive comparison of all popular identifier formats, see our complete identifier comparison guide.

For most applications requiring broad compatibility and standards compliance, standard GUIDs / UUIDs remain the recommended choice.

Warnings and trade-offs

  • Identifiers are not secrets: GUID / UUID v4 / v7 and ULID are identifiers, not security tokens. Do not use them as access tokens or authentication secrets.
  • Sorting depends on representation: "time-sortable" usually means the string form sorts by time, but database storage/byte-order can change behavior (varies by database/driver).
  • Non-standard formats: ULID is not an RFC UUID. Some APIs, ORMs, and databases assume GUID / UUID formatting and won't accept it without custom handling.
  • Time leakage: time-ordered IDs can reveal approximate creation time. If that matters, prefer GUID / UUID v4 or treat IDs as private/internal.
  • Interoperability matters: if you work across many systems or languages, GUIDs / UUIDs typically win due to universal support.
  • Migration complexity: switching from one identifier format to another in an existing system can be challenging and may require data migration.

Frequently Asked Questions

No. ULID is a GUID/UUID-like identifier (128-bit) with a different text encoding (Base32 instead of hex) and different standardization. It's not governed by RFC 9562. If you need a standards-based GUID / UUID, prefer v4 or v7.

A common modern choice is GUID / UUID v7 because it remains a real GUID / UUID while offering time-ordered behavior, which reduces index fragmentation in B-tree databases. GUID / UUID v4 is the simplest universal option, but can cause more random insert patterns in some index designs. ULID offers similar benefits to v7 but sacrifices RFC compliance.

AWS primarily uses service-specific identifiers (like ARNs, instance IDs, etc.) rather than standard GUIDs / UUIDs. Some AWS services emit standard GUIDs / UUIDs (often v4) for request IDs or event IDs (e.g., X-Amzn-RequestId headers). But AWS does not define a custom GUID / UUID version or use ULID in public APIs.

Not directly. While GUID / UUID and ULID are both 128 bits, their internal structures differ significantly (different timestamp encodings, different random bit layouts). You can store them as equivalent binary blobs in databases, but you cannot meaningfully convert one format to another without losing semantic information. Choose one format and stick with it for consistency.

ULID is often considered more human-readable due to Base32 encoding (all uppercase, no special characters, case-insensitive). Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV. GUIDs / UUIDs use hex with hyphens: 550e8400-e29b-41d4-a716-446655440000. For most purposes, GUIDs / UUIDs are "readable enough" and offer better ecosystem support.

Extremely low, similar to GUIDs / UUIDs. ULID has 80 bits of randomness per millisecond, providing sufficient entropy to make collisions negligible in practical scenarios. However, ensure your random number generator is cryptographically secure. Poor implementations can increase collision risk.

Possible with conversion. Since ULID is 128 bits, you can convert it to a UUID binary representation and store it in PostgreSQL's uuid type, but you'll lose the Base32 string representation. You may need to store ULID as text or bytea to preserve the original encoding. For native PostgreSQL support and broad compatibility, use standard GUIDs / UUIDs.

GUID / UUID v7 is an excellent choice for microservices. It provides time-ordering (useful for tracing and debugging), RFC compliance (works with standard libraries), and decentralized generation (no coordination needed). If you need correlation IDs for distributed tracing, v7's timestamp prefix makes it easy to correlate events chronologically across services.

Conclusion

For broad interoperability and standards compliance, choose a standard GUID / UUID: v4 for general-purpose fully random IDs or v7 for time-ordered database-friendly identifiers.

Choose ULID when your ecosystem already uses it, when you need its specific Base32 encoding benefits or when its operational trade-offs are a deliberate fit for your system. However, be aware of the interoperability costs and library support requirements.

Disclaimer: All information is provided for general educational and technical reference only. While we aim to keep the content accurate, current and aligned with published standards. No guarantees are made regarding completeness, correctness or suitability for any specific use case.
GUID / UUID specifications, RFCs, best practices, security guidance, database behavior and ecosystem conventions (including cloud platforms and third-party identifier formats) may change over time or differ by implementation. Examples, recommendations, and comparisons are illustrative and may not apply universally.
This content should not be considered legal, security, compliance or architectural advice. Before making critical design, security, or production decisions, always consult the latest official standards and documentation (such as RFC 4122, RFC 9562 and vendor-specific references).
Always evaluate behavior in your own environment.