In modern applications, unique identifiers play a critical role. Whether you are building distributed systems, microservices, multi-region applications, or simply want safer primary keys, UUIDs (Universally Unique Identifiers) are one of the most reliable ways to generate identifiers that never collide.
PostgreSQL provides powerful built-in support for UUIDs, but many developers still rely on the popular uuid-ossp extension to generate UUID values from inside the database. This article explains the purpose of this extension, how to use all its functions, and what changed with the introduction of PostgreSQL 18.
What is the purpose of the uuid-ossp extension in PostgreSQL?
The uuid-ossp extension adds a set of functions to PostgreSQL that allow you to generate UUIDs directly within SQL. This is especially useful when:
- You want PostgreSQL itself to generate unique IDs
- You need specific UUID versions such as v1, v3, v5
- Your application requires identifier uniqueness across servers, regions, or environments
Without this extension, PostgreSQL only supports UUID types but does not generate them automatically. uuid-ossp fills that gap.
Difference Between UUID v1, v3, and v5 in PostgreSQL
UUIDs are generated in multiple ways depending on the version. The most commonly compared ones are v1 (time-based), v3 (name-based + MD5), and v5 (name-based + SHA-1).
Below is the exact difference in purpose, input, and output behavior.
UUID v1: Time-based UUID
How it works:
- Uses timestamp + MAC address + sequence number
- Generated based on the system clock
- Produces a nearly sortable UUID
Key points:
- Not deterministic (output changes every time)
- Slightly exposes machine MAC address
- Good when you need ordering by creation time
Example use case:
- Logging systems
- Order-creation sequences
- Large distributed databases where ordering helps
UUID v3: Name-based UUID (Deterministic using MD5)
How it works:
- A namespace UUID
- A name (string)
- Applies MD5 hash, then converts to UUID format
Key points:
Example use case:
- Generating the same UUID for the same email, username, or URL
- Configuration keys
- Cache keys
UUID v5: Name-based UUID (Deterministic using SHA-1)
How it works:
- Namespace UUID
- Name string
- Uses SHA-1 hashing instead of MD5
Key points:
- Also deterministic
- More secure and preferred over v3
- Same input gives same output every time
Example use case:
- API keys
- URL-based keys
- Deterministic user identifiers
Difference Between MD5 and SHA-1
MD5 and SHA-1 are both hashing algorithms used to generate fixed-length hash values from input data. They are commonly used for checksums, signatures, and cryptographic operations—but SHA-1 is stronger than MD5.
Here is the exact difference:
1. Hash Length
- MD5> 128-bit hash (32 characters in hex)
- SHA-1> 160-bit hash (40 characters in hex)
Longer hash > more possible combinations > harder to break.
2. Security
- MD5 is weaker
- High chance of collisions
- Not recommended for any secure system
- SHA-1 is stronger than MD5, but
- Also considered weak today
- Collisions have been demonstrated
Both are considered cryptographically broken, but SHA-1 is harder to break than MD5.
3. Collision Resistance
A collision happens when two different inputs produce the same hash.
- MD5 > Very high collision vulnerability
- SHA-1> Less vulnerable but still breakable
This is why modern security systems use SHA-256 or stronger algorithms.
4. Speed
- MD5 is faster
- SHA-1 is slightly slower (still very fast)
The speed difference is small in modern systems.
5. Use in UUIDs
In PostgreSQL:
- UUID v3 uses MD5
- UUID v5 uses SHA-1
Which means:
- v3 > faster, weaker deterministic UUID
- v5> stronger, safer deterministic UUID
That is why UUID v5 is preferred over UUID v3 in modern applications.
How to Enable the uuid-ossp Extension
Before using the functions, enable the extension in your database:
CREATE EXTENSION "uuid-ossp";
You can confirm that the extension is available using:
SELECT * FROM pg_available_extensions WHERE name = 'uuid-ossp';
And list all functions:
\dx+ uuid-ossp
Why Use UUIDs Instead of Serial or Bigserial?
Traditional integer primary keys (SERIAL, BIGSERIAL) are simple and fast, but they reveal system behavior:
- Predictable and sequential
- Expose information such as number of records
- Not ideal for distributed writes
- Harder to merge data between systems
UUIDs solve these problems:
- Virtually impossible to guess
- Safe for public URLs
- Can be generated anywhere
- Work well in distributed environments
- No risk of collisions
All Functions Provided by uuid-ossp and Their Purpose
The extension gives you multiple UUID generation methods. Each method has a specific use case.
1. uuid_generate_v1()
Generates a Version 1 UUID, based on:
- Timestamp
- MAC address of the machine
Example:
SELECT uuid_generate_v1();
Use case:
Systems that require sortable UUIDs and are comfortable with MAC-address-based generation.
2. uuid_generate_v1mc()
Similar to v1 but uses a random multicast MAC instead of the hardware MAC.
Example:
SELECT uuid_generate_v1mc();
Use case:
When you want v1 UUID ordering advantage but want to avoid exposing real MAC addresses.
3. uuid_generate_v4()
Generates a Version 4 UUID, completely random.
Example:
SELECT uuid_generate_v4();
Use case:
Most common for modern applications. Provides strong randomness and avoids machine-identifying data.
4. uuid_nil()
Returns a UUID filled with all zeros:
00000000-0000-0000-0000-000000000000
Example:
SELECT uuid_nil();
Use case:
A standard “empty value” for UUID fields.
5. Namespace UUID Functions
These UUIDs act as predefined namespaces for name-based UUID generation.
- uuid_ns_dns()
- uuid_ns_oid()
- uuid_ns_url()
- uuid_ns_x500()
These return constant UUIDs defined in RFC 4122.
Example:
SELECT uuid_ns_dns();
Use case:
Used with v3 and v5 UUIDs to create namespaced identifiers.
6. uuid_generate_v3(namespace_uuid, name_text)
Generates a Version 3 UUID using:
- MD5 hashing
- Namespace UUID
- A text value
Example:
SELECT uuid_generate_v3(uuid_ns_dns(), 'example.com');
Use case:
Use when you want deterministic UUIDs. The same input always produces the same UUID.
Common in:
- URL hashing
- DNS-based identities
- Reproducible identifiers across environments
7. uuid_generate_v5(namespace_uuid, name_text)
Similar to v3 but uses SHA-1 hashing instead of MD5.
Example:
SELECT uuid_generate_v5(uuid_ns_url(), 'https://myapp.com/users');
Use case:
Safer deterministic UUIDs than v3. Useful for stable, repeatable keys in distributed systems.
When Should You Use v3 or v5 UUIDs?
Choose v3/v5 UUIDs when:
- You need the same UUID every time for the same input
- You want stable identifiers
- Perfect for caching, URLs, integration, configuration keys
Never use them when you need randomness.
What’s New in PostgreSQL 18 Related to UUID?
Starting from PostgreSQL 13 onward, PostgreSQL has supported the built-in function:
gen_random_uuid()
In PostgreSQL 18, this remained the recommended way for modern projects.
gen_random_uuid() belongs to the pgcrypto extension:
CREATE EXTENSION pgcrypto;
SELECT gen_random_uuid();
Why is it recommended?
- Faster
- More secure
- Does not require OSSP library installation
- Purely random UUID v4
This means, for most modern uses, pgcrypto’s gen_random_uuid() is preferred over uuid_generate_v4().
However, uuid-ossp is still useful because:
- It provides v1 UUID generation
- It provides v3/v5 deterministic UUIDs
- It provides namespace UUIDs
- It is necessary when you need backwards compatibility
Which UUID Method Should You Use?
Here is a simple guidance:
- Use v4 for most applications.
- Use v1 when you need time-sortable UUIDs.
- Use v1mc to avoid MAC exposure.
- Use v3 or v5 when you need deterministic UUIDs
- Use gen_random_uuid() on modern PostgreSQL instead of uuid_generate_v4()
Conclusion
The uuid-ossp extension in PostgreSQL is a versatile and reliable solution for generating multiple types of UUIDs directly inside the database. It supports time-based UUIDs, name-based deterministic UUIDs, namespace-based identifiers, and more—making it suitable for a wide range of system architectures and data requirements.
While PostgreSQL 18 continues to support this extension, the preferred method for generating modern random UUIDs is gen_random_uuid() from the pgcrypto extension due to its speed, security, and simplicity. However, uuid-ossp remains essential when you need features that pgcrypto does not provide, such as:
- Time-based UUIDs (v1, v1mc)
- Namespaced UUIDs (v3 and v5)
- Deterministic and reproducible UUID generation
In scenarios where predictable or namespace-driven UUIDs are required, uuid-ossp is still the best choice.