Generate a UUID in PostgreSQL

How to generate a UUID in PostgreSQL: gen_random_uuid for v4 on 13+, uuidv7 on PostgreSQL 18, uuid-ossp for v1 and v5, a uuid primary key with a default, reading the timestamp back, and why to use the uuid type not text.

Try it here

Generate a UUID to paste into your PostgreSQL code, in any version and format.

Format

Your UUIDs

Copy one, copy them all, or download the list. The format options above apply to everything shown here.

    Random v4: gen_random_uuid

    SELECT gen_random_uuid();
    -- f47ac10b-58cc-4372-a567-0e02b2c3d479
    
    CREATE TABLE orders (
        id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        status text NOT NULL
    );

    gen_random_uuid() is built into PostgreSQL 13 and newer, no extension needed. Before 13 it came from the pgcrypto extension.

    Time ordered v7: uuidv7 on PostgreSQL 18

    SELECT uuidv7();
    SELECT uuidv4();                          -- alias for gen_random_uuid, also new in 18
    
    CREATE TABLE events (
        id uuid PRIMARY KEY DEFAULT uuidv7(),
        payload jsonb
    );
    
    SELECT uuid_extract_timestamp(id) FROM events;   -- the creation time, from v1 or v7
    SELECT uuid_extract_version(id) FROM events;      -- 7

    PostgreSQL 18, released in September 2025, added native v7 generation. Rows inserted later get larger ids, so the primary key index grows at one end instead of everywhere, the same benefit a bigserial has. If you are on 17 or older, either generate v7 in the application, see our Python, Go and Java pages, or install the pg_uuidv7 extension. A plain SQL function also works:

    -- v7 for PostgreSQL 13 to 17, no extension
    CREATE FUNCTION uuid_v7() RETURNS uuid LANGUAGE sql VOLATILE AS $$
      SELECT encode(
        set_bit(set_bit(
          overlay(uuid_send(gen_random_uuid()) placing
            substring(int8send((extract(epoch FROM clock_timestamp()) * 1000)::bigint) FROM 3)
            FROM 1 FOR 6),
          52, 1), 53, 1),
        'hex')::uuid;
    $$;

    v1, v3 and v5: the uuid-ossp extension

    CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
    
    SELECT uuid_generate_v1();                              -- time based
    SELECT uuid_generate_v4();                              -- same as gen_random_uuid
    SELECT uuid_generate_v5(uuid_ns_dns(), 'example.com');  -- name based, deterministic
    SELECT uuid_nil();

    Validate and cast

    SELECT 'f47ac10b-58cc-4372-a567-0e02b2c3d479'::uuid;   -- ok
    SELECT 'not-a-uuid'::uuid;                               -- ERROR: invalid input syntax for type uuid
    
    -- uppercase, braces and no hyphens are all accepted on input
    SELECT '{F47AC10B-58CC-4372-A567-0E02B2C3D479}'::uuid;
    
    -- check without raising, PostgreSQL 16+
    SELECT pg_input_is_valid('not-a-uuid', 'uuid');   -- false

    Use the uuid type, not text

    A uuid column is 16 bytes. The same value as text or varchar(36) is 37 bytes plus overhead, indexes are more than twice as large, and comparisons are slower because they go character by character. The uuid type also validates on write, so junk never gets in. Every driver maps it to the language's native type: uuid.UUID in Python, UUID in Java, uuid.UUID in Go, Guid in .NET.

    Mistakes to avoid

    • Random v4 keys on very large, write heavy tables. Works, but v7 keeps the index and the cache far healthier. The primary key post has numbers.
    • ORDER BY id expecting creation order. Only true for v7 or v6. With v4, order by a timestamp column.
    • md5(random()::text)::uuid. An old trick from before gen_random_uuid. The version bits are wrong and the randomness is weak.

    Frequently asked questions

    Does PostgreSQL have a built in UUID generator?

    Yes. gen_random_uuid() for v4 since PostgreSQL 13, and uuidv7() plus uuidv4() since PostgreSQL 18. Older versions need pgcrypto or uuid-ossp.

    How do I generate UUID v7 in PostgreSQL before version 18?

    Generate in the application, install the pg_uuidv7 extension, or create the small SQL function shown above, which builds a v7 from clock_timestamp and gen_random_uuid.

    Should the primary key be uuid or bigserial?

    bigserial is smaller and faster if ids never leave the database and there is one writer. uuid is better when ids are created by clients, exposed in URLs, or merged from several sources. With v7 the performance gap is small.

    ↑ Top
    Copied!