Introduction to the PostgreSQL UUID data type
UUID stands for Universally Unique Identifier, defined by RFC 4122. A UUID is a 128-bit value represented as 32 hexadecimal digits in five groups separated by hyphens:
40e6215d-b5c6-4896-987c-f30f3678f608
6ecd8c99-4036-403d-bf84-cf8400f67836
PostgreSQL stores UUID values in 16 bytes (binary) and displays them in the standard hyphenated format. Unlike SERIAL, which generates unique values only within a single database, a UUID is globally unique — making it ideal for distributed systems, multi-database architectures, and public-facing identifiers.
Generating UUID values
PostgreSQL provides gen_random_uuid() as a built-in function that generates a version 4 (random) UUID:
SELECT gen_random_uuid();
-- Output:
-- gen_random_uuid
-- --------------------------------------
-- d6eb621f-6dd0-4cdc-93f5-07f51b249b51
For PostgreSQL versions older than 13, install the uuid-ossp extension:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
SELECT uuid_generate_v4();
-- 351c1afe-21b2-486c-951b-66bc9e852530
Creating a table with a UUID primary key
Define a UUID column with DEFAULT gen_random_uuid() so PostgreSQL auto-generates IDs on insert:
CREATE TABLE contacts (
contact_id UUID DEFAULT gen_random_uuid(),
first_name VARCHAR NOT NULL,
last_name VARCHAR NOT NULL,
email VARCHAR NOT NULL,
phone VARCHAR,
PRIMARY KEY (contact_id)
);
Inserting and querying UUID data
INSERT INTO contacts (first_name, last_name, email, phone)
VALUES
('John', 'Smith', '[email protected]', '408-237-2345'),
('Jane', 'Smith', '[email protected]', '408-237-2344'),
('Alex', 'Smith', '[email protected]', '408-237-2343')
RETURNING *;
-- Output:
-- contact_id | first_name | last_name | email
-- -------------------------------------+------------+-----------+-----------------------
-- ca61da8c-938a-48a6-8eb6-55aa08cd1b08 | John | Smith | [email protected]
-- fe2af584-8576-4d0e-b10d-6ec970732f8e | Jane | Smith | [email protected]
-- 141aefe8-f553-43b9-bfbf-91361e83b15e | Alex | Smith | [email protected]
Production tips
- Always use
DEFAULT gen_random_uuid()on UUID primary key columns so the database — not the application — is responsible for ID generation. - For high-throughput write tables, consider time-ordered UUID variants (UUIDv7 or ULID) to reduce B-tree index fragmentation from random insertion order.
- UUID primary keys prevent sequential ID enumeration in public APIs — an attacker cannot guess adjacent resource IDs.
- Index UUID columns with a standard B-tree index. For large tables with low selectivity UUID lookups, a hash index may be faster for equality queries.
Reference: PostgreSQL documentation — UUID type.