UUIDs Explained: Versions, Use Cases, and When to Use Auto-Increment Instead

5 66
calendar_today agoschedule4 min read

UUIDs (Universally Unique Identifiers) appear in virtually every modern application — database primary keys, API resource IDs, session tokens, file names, correlation IDs. But there are several UUID versions, they have different tradeoffs, and auto-increment integers are often the better choice. Here is a practical breakdown.

What Is a UUID?

A UUID is a 128-bit identifier represented as 32 hexadecimal digits in 5 groups separated by hyphens:

``

550e8400-e29b-41d4-a716-446655440000

`

The format is 8-4-4-4-12 characters. The third group's first digit indicates the version (above: 4). The fourth group's first digit indicates the variant.

The mathematical probability of two UUIDs colliding when generated properly is so low that it is treated as impossible in practice.

UUID Versions

UUID v1 — time-based + MAC address

Generated from the current timestamp and the machine's MAC address. Sortable by time. The downside: it embeds the MAC address, which is a privacy concern. Rarely used in new applications.

UUID v4 — random

122 bits of cryptographic randomness. The most widely used version. No sequential ordering — each UUID is completely random. Use this as the default when you need a unique ID and don't need sort order.

UUID v5 — name-based (SHA-1)

Deterministic: given the same namespace and name, v5 always generates the same UUID. Useful for stable IDs derived from content — for example, always generating the same UUID for a given URL or email address.

UUID v7 — time-ordered random (newest)

Combines a Unix timestamp prefix with random bits. The result is time-sortable (newer UUIDs sort after older ones) while still being globally unique. This is the version to prefer for database primary keys because it does not fragment B-tree indexes. Supported natively in PostgreSQL 17+, and available via libraries in most languages.

UUID v4 in Code

JavaScript (browser / Node.js, modern):
<code>javascript <p>const id = crypto.randomUUID(); // native, no library needed</p> </code>

Node.js (with uuid package):
<code>javascript <p>import { v4 as uuidv4 } from 'uuid';</p> <p>const id = uuidv4();</p> </code>

Python:
<code>python <p>import uuid</p> <p>id = str(uuid.uuid4())</p> </code>

Go:
<code>go <p>import "github.com/google/uuid"</p> <p>id := uuid.New().String()</p> </code>

Ruby:
<code>ruby <p>require 'securerandom'</p> <p>id = SecureRandom.uuid</p> </code>

PostgreSQL:
<code>sql <p>SELECT gen_random_uuid(); -- PostgreSQL 13+</p> </code>

UUID v7 in Code (time-ordered)

UUID v7 is newer and not universally supported yet, but is available via libraries:

JavaScript:
<code>javascript <p>import { v7 as uuidv7 } from 'uuid'; // uuid package v9+</p> <p>const id = uuidv7();</p> </code>

Python:
<code>python <p>import uuid</p> <p>id = str(uuid.uuid7()) # Python 3.13+</p> </code>

Java:
<code>java <p>// JUG library</p> <p>UUID id = Generators.timeBasedEpochGenerator().generate();</p> </code>

.NET 9+:
<code>csharp <p>Guid id = Guid.CreateVersion7();</p> </code>`

UUID vs Auto-Increment: When to Use Each

This is the most important practical question, and the answer depends on your use case.

Use auto-increment integers when:

  • The ID is internal only — users never see it, it never appears in URLs
  • You need the most compact storage (4 or 8 bytes vs 16 bytes for UUID)
  • Sequential ordering of IDs is meaningful (you want to know that row 1001 was inserted after row 1000)
  • You are on a single database server with no replication or merging concerns

Use UUIDs when:
  • IDs appear in URLs, APIs, or client-side code (UUIDs don't reveal count or sequence)
  • You are generating IDs on the client before writing to the database (mobile, offline-first apps)
  • You have multiple database nodes, replicas, or data that needs to merge without ID conflicts
  • You are building a microservices architecture where services create records independently

Prefer UUID v7 over v4 for database primary keys — random v4 UUIDs cause index fragmentation because each new row inserts into a random position in the B-tree index. UUID v7's time-ordered prefix means new rows append near the end, like auto-increment, but with global uniqueness.

Common Mistakes

Storing UUIDs as VARCHAR. UUIDs should be stored as the native UUID type in PostgreSQL (16 bytes) or as BINARY(16) in MySQL. Storing as CHAR(36) or VARCHAR(36) triples the storage and slows index operations.

Using UUID v4 for high-volume database tables. For tables with millions of rows, use v7 or ulid instead of v4 to avoid index fragmentation.

Trusting client-generated UUIDs without validation. Always validate that a UUID is well-formed before using it in a query. A malformed UUID from a client can cause parse errors or, worse, inject unexpected characters.

Quick Generator

For generating test UUIDs, one-off IDs during development, or batch ID lists, the SnappyTools UUID Generator generates v4 UUIDs in-browser with no server round-trip.


UUIDs solve a real problem — globally unique identifiers without coordination. UUID v4 is the safe default; UUID v7 is the better choice for database primary keys. Auto-increment remains the right answer when IDs are purely internal and sequential ordering matters.

2k Points71 Badges5 66
81Posts
0Comments
SnappyTools builds free, fast, browser-based tools for developers, writers, and designers. No signup required, no data uploaded, no nonsense — just clean tools that work instantly ... Show more
Build your own developer journey
Track progress. Share learning. Stay consistent.
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

TypeScript Complexity Has Finally Reached the Point of Total Absurdity

Karol Modelskiverified - Apr 23

Sovereign Intelligence: The Complete 25,000 Word Blueprint (Download)

Pocket Portfolio - Apr 1

Just completed another large-scale WordPress migration — and the client left this

saqib_devmorph - Apr 7

Base64 Encoding Explained: What It Is, Why It Exists, and When to Use It

SnappyTools - Jun 9
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

2 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!