UUID

How to use the PostgreSQL UUID data type as a primary key: generating UUIDs with gen_random_uuid(), creating tables, and when to prefer UUID over SERIAL.

4 min read · Last updated: March 2026 · Back to overview

Quick Answer

The PostgreSQL UUID data type stores a 128-bit universally unique identifier as a 32-character hexadecimal string. Use gen_random_uuid() to generate version 4 (random) UUIDs. UUID primary keys are preferred in distributed systems because they are globally unique without coordination.

Spin up a Postgres database in 20 seconds with Vela.

Try Vela Sandbox

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.

Continue in PostgreSQL Data Types: JSON.

Related in this section: Boolean · CHAR, VARCHAR, and TEXT · NUMERIC

Frequently Asked Questions

What is a UUID in PostgreSQL?

UUID (Universally Unique Identifier) is a 128-bit value defined by RFC 4122. PostgreSQL stores it as a 32-digit hexadecimal string in groups separated by hyphens, e.g. 40e6215d-b5c6-4896-987c-f30f3678f608. The UUID data type stores these values efficiently in binary form (16 bytes) while displaying them in the standard hyphenated format.

How do you generate a UUID in PostgreSQL?

PostgreSQL includes gen_random_uuid() as a built-in function (since PostgreSQL 13) that returns a version 4 random UUID: SELECT gen_random_uuid(); — returns e.g. d6eb621f-6dd0-4cdc-93f5-07f51b249b51. For older versions, install the uuid-ossp extension with CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; then use uuid_generate_v4().

How do you use UUID as a primary key?

Define the primary key column as UUID with a default of gen_random_uuid(): CREATE TABLE contacts (contact_id UUID DEFAULT gen_random_uuid() PRIMARY KEY, name VARCHAR NOT NULL); When inserting rows without specifying contact_id, PostgreSQL automatically calls gen_random_uuid() to populate it.

When should I use UUID instead of SERIAL for primary keys?

Use UUID when you need globally unique IDs across multiple databases, services, or servers — for example in distributed systems, microservices, or when merging data from separate databases. SERIAL generates unique values only within a single database sequence, so two separate databases can produce the same integer ID for different rows. UUID also prevents ID enumeration attacks in public-facing APIs.

What are the downsides of UUID primary keys?

UUID primary keys use more storage (16 bytes vs 4–8 bytes for integers) and can cause index fragmentation because random UUIDs are inserted in random order, leading to page splits in B-tree indexes. For write-heavy tables, consider using UUIDv7 (time-ordered) or ULID generators that produce monotonically increasing values to reduce fragmentation.