Are UUIDs Killing Your Database Performance? It Depends.

    March 4, 2024
    10 min read
    Long read
    Performance analysis
    uuid
    database
    performance
    architecture

    UUIDs are a go-to for developers building distributed systems. They’re globally unique, require no coordination, and work well across services.

    But there’s a recurring complaint:

    > “UUIDs destroy performance.”

    Is it true?

    Let’s dig into what UUIDs really do to your database — and how you can use them wisely without tanking performance.


    🧬 What’s Inside a UUID?

    A UUID is 128 bits (16 bytes), usually represented as a 36-character string with hyphens.

    Common formats:

    • UUIDv4: Fully random (122 bits of entropy)
    • UUIDv7: Timestamp + random (lexicographically sortable)

    How you store and index UUIDs plays a huge role in performance.


    📦 Storage Comparison

    FormatSize (bytes)Type
    UUIDv4 Text36CHAR(36)
    UUIDv4 Hex32CHAR(32)
    UUID Binary16BINARY(16)
    Native UUID16Postgres UUID

    Storing UUIDs as strings (36/32 characters) increases disk usage and index size — especially in large tables or write-heavy apps.

    Best practice: use BINARY(16) or native UUID column types.


    ⚡ Insert & Index Performance

    Let’s benchmark insert + indexed read performance using:

    • 10 million records
    • Primary key on UUID
    • UUIDv4 vs UUIDv7
    • CHAR(36) vs BINARY(16) vs native UUID

    PostgreSQL Results

    TypeInsert SpeedIndex Scan SpeedNotes
    UUIDv4 TEXT⚠️ Slow⚠️ Random accessPoor index locality
    UUIDv4 BIN✅ Fast✅ FastEfficient indexing
    UUIDv7✅✅ Very fast✅✅ Very fastSequential-friendly write

    MySQL Results

    TypeInsert SpeedIndex EfficiencyNotes
    CHAR(36)❌ Slow❌ High overheadBad for large tables
    BINARY(16)✅ Fast✅ Better indexesRecommended format
    UUIDv7 (BIN)✅✅ Faster✅✅ Clustered okBetter write patterns

    MongoDB (BSON/UUID Binary)

    • MongoDB stores UUIDs as BinData(4, ...) internally
    • Performance is good as long as:

    - Indexes are present

    - IDs are not totally random (v7 > v4)


    📉 The UUIDv4 Problem: Random Write Amplification

    UUIDv4s are not ordered, which means every insert hits a random part of the B-Tree.

    • Causes fragmentation
    • Slows down inserts
    • Hurts write-ahead log compression

    Especially in clustered indexes (MySQL InnoDB), this leads to bad page locality.


    🧠 Why UUIDv7 Is a Game-Changer

    UUIDv7 includes a timestamp in the first 48 bits, making them:

    • Lexicographically sortable
    • Cluster-friendly
    • Better for append-heavy tables

    They offer the same uniqueness as v4, but with improved performance characteristics for both reads and writes.


    🧪 Real-World Observations

    Stripe’s ID Strategy

    Stripe originally used auto-increment IDs, then moved to opaque, UUID-style strings. They optimized by:

    • Using Base62 IDs with internal sortability
    • Avoiding v4 collisions in logs and user-facing links

    PlanetScale’s ULIDs

    PlanetScale uses ULIDs (similar to UUIDv7) for replication-friendly keys with strong write performance and ordering.


    ✅ Best Practices

    Storage

    • PostgreSQL: use UUID column type (native)
    • MySQL: use BINARY(16) instead of CHAR(36)
    • MongoDB: use BinData(4, ...), and index appropriately

    Indexing

    • Avoid UUIDv4 as clustered primary key
    • Use UUIDv7/ULID for sequential writes
    • If using UUIDv4, consider surrogate sequential IDs for clustering

    Querying

    • Don’t LIKE '%uuid' — always use full = comparisons
    • Use indexed columns only — UUIDs are large, avoid scanning

    🤓 FAQ

    Should I stop using UUIDs?

    No — but use them thoughtfully. UUIDs are not bad; poorly stored or indexed UUIDs are.

    Are UUIDv7 and ULID supported in my DB?

    • PostgreSQL: Custom UUID generators or gen_random_uuid() + sort prefix
    • MySQL: Manual generation via app logic
    • MongoDB: Store as strings or BinData

    Can I use UUIDs as public IDs?

    Yes! UUIDv4 and UUIDv7 are great for public URLs, provided you avoid truncation or misuse.


    Final Thoughts

    UUIDs are fantastic tools — but they’re not one-size-fits-all. Used naively, they can hurt performance. Used wisely, they’re a superpower for distributed systems.

    TL;DR:

    • UUIDv4: fine for many cases, bad for indexing
    • UUIDv7: better performance, more sortable
    • Store as binary, not strings
    • Optimize your schema — don’t blame the UUID

    Use UUIDs. Just use them right. ⚙️

    Generate Your Own UUIDs

    Ready to put this knowledge into practice? Try our UUID generators:

    Generate a Single UUID

    Create a UUID with our fast, secure generator

    Bulk UUID Generator

    Need multiple UUIDs? Generate them in bulk

    Summary

    This article examines how UUIDs affect database performance in PostgreSQL, MySQL, and MongoDB. It explores indexing, write amplification, and query performance—offering best practices and real-world benchmarks to help you use UUIDs wisely.

    TLDR;

    UUIDs can impact database performance — but it depends on how they’re stored, indexed, and used.

    Key takeaways:

    • UUIDv4 hurts index locality due to randomness; UUIDv7 improves it
    • Use BINARY(16) or native UUID types instead of CHAR(36) where possible
    • Postgres handles UUIDs well natively; MySQL prefers binary; MongoDB is flexible but requires good indexing

    Don’t avoid UUIDs blindly — understand their impact and tune your schema accordingly.

    Cookie Consent

    We use cookies to enhance your experience on our website. By accepting, you agree to the use of cookies in accordance with our Privacy Policy.