COMB GUIDs: The Hybrid Approach That Gives You the Best of Both Worlds

    March 25, 2024
    9 min read
    Technical explainer
    Tutorial
    uuid
    database
    performance
    innovation

    UUIDs are fantastic for generating globally unique identifiers. But they’re terrible for databases when it comes to index locality and write performance — especially UUIDv4, which is fully random.

    So what if we could combine the best of both worlds — randomness and sortability?

    Meet COMB GUIDs — a clever hybrid used in enterprise systems to tame UUIDs without sacrificing performance.


    🧬 What Is a COMB GUID?

    COMB stands for Combined GUID (or "Combined Ordered GUID").

    A COMB GUID is a UUID that embeds a timestamp — typically in the last few bytes — while keeping the rest of the identifier random.

    > 📌 Origin: COMB was introduced by Jimmy Nilsson in 2004 to improve clustered index performance in SQL Server when using GUIDs.


    ⚙️ Why COMB GUIDs Matter

    Traditional UUIDv4s are completely random. When used as a primary key:

    • Index inserts are non-sequential
    • Fragmentation increases
    • Write performance drops (especially on clustered indexes)

    COMB GUIDs solve this by:

    • Keeping the randomness (for uniqueness)
    • Injecting time information (for order-preserving inserts)

    You get better B-tree locality and faster write performance, especially in relational databases like SQL Server, PostgreSQL, and MySQL.


    🔢 COMB GUID Structure (Simplified)

    UUID SegmentPurpose
    First 10–12 bytesRandom
    Last 4–6 bytesEncoded timestamp

    The exact layout varies, but the general idea is:

    1. Generate a UUIDv4 or v1

    2. Replace part of it (typically the tail) with a timestamp

    3. Store it as a standard UUID

    Because it’s still 128 bits, COMB GUIDs are fully UUID-compatible.


    🧪 Implementing COMB GUIDs

    🧠 Strategy:

    1. Generate a UUIDv4

    2. Get a timestamp (e.g. Unix time in milliseconds)

    3. Inject the timestamp bytes into the UUID (tail or middle)

    4. Return as a standard UUID object

    Let’s look at language-specific implementations.


    💻 C# Example (SQL Server + EF Core)

    Entity Framework Core supports COMB GUIDs natively through value generation.

    csharp
    public class CombGuidGenerator
    {
        public static Guid NewComb()
        {
            var guidArray = Guid.NewGuid().ToByteArray();
            var timestamp = BitConverter.GetBytes(DateTime.UtcNow.Ticks);
    
            // Overwrite last 6 bytes with timestamp (little-endian safe)
            Array.Copy(timestamp, 2, guidArray, 10, 6);
            return new Guid(guidArray);
        }
    }

    Use in Entity Framework:

    csharp
    builder.Property(x => x.Id)
        .HasDefaultValueSql("NEWSEQUENTIALID()");

    > SQL Server's NEWSEQUENTIALID() is similar to COMB — with time-based ordering for clustered indexes.


    🐍 Python Example

    python
    import uuid
    import time
    
    def new_comb_uuid():
        u = uuid.uuid4()
        now = int(time.time() * 1000)
        ts_bytes = now.to_bytes(6, byteorder='big')
        comb_bytes = u.bytes[:10] + ts_bytes
        return uuid.UUID(bytes=comb_bytes)
    
    # Example
    print(new_comb_uuid())

    > Modify the number of timestamp bytes depending on resolution needed (millis, micros, etc.)


    ☕ Java Example

    java
    import java.nio.ByteBuffer;
    import java.util.UUID;
    
    public class CombUuid {
        public static UUID generate() {
            UUID base = UUID.randomUUID();
            long timeMillis = System.currentTimeMillis();
    
            ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
            bb.putLong(base.getMostSignificantBits());
            bb.putInt((int) (timeMillis >> 16));
            bb.putShort((short) timeMillis); // Lower 2 bytes
    
            bb.rewind();
            long msb = bb.getLong();
            long lsb = bb.getLong();
            return new UUID(msb, lsb);
        }
    }

    🧠 COMB vs UUIDv7

    FeatureCOMB GUIDUUIDv7
    TimestampEmbedded manuallyBuilt-in (RFC 9562)
    RandomnessPartialHigh (74 bits)
    Standard-compliant✅ (RFC 4122)✅ (RFC 9562)
    Sortable
    DB compatibility✅ (where supported)

    Summary:

    • COMB: Custom hybrid, widely used in SQL Server, flexible placement
    • UUIDv7: Modern, standardized, gaining adoption

    🧰 When Should You Use COMB GUIDs?

    ✅ Use COMB GUIDs if:

    • You’re using SQL Server, MySQL, or PostgreSQL with clustered indexes
    • You need insert-time sortability
    • You want UUID compatibility but better write performance

    🚫 Avoid COMB GUIDs if:

    • You need cryptographic or untraceable identifiers (timestamp leaks info)
    • You’re in a system that already supports UUIDv7

    🔐 Security Considerations

    Because part of a COMB GUID is a timestamp:

    • IDs can be sorted chronologically
    • They may reveal timing patterns (e.g. user signups)

    This is usually fine for internal use, but not ideal for public identifiers.


    Final Thoughts

    COMB GUIDs are a brilliant compromise — the randomness of UUIDs with the sortability of sequential keys.

    They’re battle-tested in enterprise systems, help avoid index fragmentation, and slot neatly into existing UUID workflows.

    If you’re struggling with UUIDv4 and database performance, COMB GUIDs might be the fix you didn’t know you needed.

    ⚙️ Hybrid identifiers: powered by math, optimized by time.

    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 explains COMB GUIDs — a hybrid identifier that blends UUID randomness with timestamp ordering for improved database performance. Learn how they work, why they matter, and how to implement them across languages like C#, Java, and Python.

    TLDR;

    COMB GUIDs blend randomness and time-ordering to improve insert and indexing performance in databases.

    Key takeaways:

    • COMB = “Combined” GUID: a UUID where part of the bits are timestamp-based
    • It keeps global uniqueness while improving index locality (vs UUIDv4)
    • Popular in ORMs like NHibernate and EF Core, especially for SQL Server

    Use COMB GUIDs when you want uniqueness and performance — especially for clustered indexes.

    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.