PostgreSQL · gen_random_uuid() · Database Reference

Generate a UUID in PostgreSQL

Complete reference for the native uuid type, gen_random_uuid(), the uuid-ossp extension, and UUID v7 support in PostgreSQL 18 — plus indexing considerations for UUID primary keys.

Quick Start

Generate a Random UUID (v4) with gen_random_uuid()

PostgreSQL 13+ includes gen_random_uuid() built into core — no extension required:

SQL
SELECT gen_random_uuid(); — gen_random_uuid — ————————————– — 550e8400-e29b-41d4-a716-446655440000
💡

No extension needed since PostgreSQL 13

Older tutorials show uuid_generate_v4() from the uuid-ossp extension. Since PostgreSQL 13, gen_random_uuid() is built into core (via pgcrypto internals) and needs no CREATE EXTENSION statement at all.

Native Type

The Native uuid Column Type

PostgreSQL has a dedicated 16-byte uuid type — use it instead of VARCHAR(36) for both storage efficiency and built-in format validation:

SQL — table with UUID primary key
CREATE TABLE orders ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), customer_name TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() );
Storage TypeSizeValidates Format
UUID (native)16 bytesYes — rejects malformed input at insert time
VARCHAR(36)36+ bytesNo — accepts any string
CHAR(32) (no hyphens)32 bytesNo — accepts any string

UUID v7

UUID v7 in PostgreSQL 18

PostgreSQL 18 (released 2026) added native uuidv7() support — time-ordered UUIDs that solve the index fragmentation problem of random v4 keys:

SQL — PostgreSQL 18+
CREATE TABLE events ( id UUID PRIMARY KEY DEFAULT uuidv7(), payload JSONB, created_at TIMESTAMPTZ DEFAULT NOW() );

Why v7 matters for PostgreSQL primary keys

B-tree indexes perform best with roughly ascending insert order. Random UUID v4 causes page splits and index bloat at scale. UUID v7’s timestamp prefix keeps new rows clustered together in the index — matching the performance profile of a SERIAL column while keeping UUID’s distributed-generation benefits.

⚠️

Check your PostgreSQL version first

uuidv7() requires PostgreSQL 18 or later. On older versions, use the pg_uuidv7 extension, or generate v7 UUIDs in your application code (see our Python or JavaScript guides) and insert them as regular UUID values.

Legacy Extension

uuid-ossp Extension (Pre-PostgreSQL 13)

If you’re on an older PostgreSQL version, install the uuid-ossp extension for UUID generation functions:

SQL
CREATE EXTENSION IF NOT EXISTS “uuid-ossp”; SELECT uuid_generate_v4(); — random UUID SELECT uuid_generate_v1(); — time-based UUID SELECT uuid_generate_v5(uuid_ns_dns(), ‘example.com’); — deterministic

Validation & Bulk

Validating and Bulk-Generating UUIDs

SQL — validate a UUID string
— Casting to uuid validates automatically SELECT ‘550e8400-e29b-41d4-a716-446655440000’::uuid; — OK SELECT ‘not-a-uuid’::uuid; — ERROR: invalid input syntax for type uuid
SQL — safe validation function
CREATE OR REPLACE FUNCTION is_valid_uuid(val TEXT) RETURNS BOOLEAN AS $$ BEGIN PERFORM val::uuid; RETURN TRUE; EXCEPTION WHEN invalid_text_representation THEN RETURN FALSE; END; $$ LANGUAGE plpgsql;
SQL — bulk generate 10,000 rows
INSERT INTO orders (id, customer_name) SELECT gen_random_uuid(), ‘Test Customer ‘ || n FROM generate_series(1, 10000) n;

FAQ

PostgreSQL UUID FAQ

No, not since PostgreSQL 13. The gen_random_uuid() function is built into core and requires no CREATE EXTENSION statement. Only older PostgreSQL versions (12 and earlier) need the uuid-ossp extension installed for UUID generation functions like uuid_generate_v4().
Use UUID v7 (via uuidv7() in PostgreSQL 18+) if you need distributed generation across multiple servers without coordination, or want to avoid exposing row counts. Use SERIAL/BIGSERIAL if you only need a single-database auto-increment and want the smallest possible index size. Avoid random UUID v4 as a primary key at scale, since it causes B-tree index fragmentation — v7 solves this by being time-ordered.
PostgreSQL 18, released in 2026, added the native uuidv7() function. For earlier versions, you can use the third-party pg_uuidv7 extension, or generate UUID v7 values in your application code and insert them as regular UUID column values.
Yes. Casting any string to the uuid type, such as ‘value’::uuid, validates the format immediately and raises an invalid_text_representation error if it does not match the RFC 4122/9562 pattern. This is a key advantage over storing UUIDs as VARCHAR, which accepts any string without validation.

Need to Generate a UUID Right Now?

Skip the SQL — use our free browser-based generator for all 8 UUID versions.

Open UUID Generator