{"id":10348,"date":"2025-12-05T12:43:58","date_gmt":"2025-12-05T11:43:58","guid":{"rendered":"https:\/\/www.credativ.de\/?p=10348"},"modified":"2025-12-05T12:53:46","modified_gmt":"2025-12-05T11:53:46","slug":"a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18","status":"publish","type":"post","link":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/","title":{"rendered":"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18"},"content":{"rendered":"\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\n<p>In the past there have been many discussions about using UUID as a primary key in <a href=\"https:\/\/www.credativ.de\/en\/portfolio\/support\/postgresql-competence-center\/\">PostgreSQL<\/a>. For some applications, even a BIGINT column does not have sufficient range: it is a signed 8\u2011byte integer with range \u22129,223,372,036,854,775,808 to +9,223,372,036,854,775,807. Although these values look big enough, if we think about web services that collect billions or more records daily, this number becomes less impressive. Simple integer values can also cause conflicts of values in distributed system, in Data Lakehouses when combining data from multiple source databases etc.<\/p>\n<\/div>\n\n\n\n<p>However, the main practical problem with UUIDv4 as a primary key in PostgreSQL was not lack of range, but the complete randomness of the values. This randomness causes frequent B\u2011tree page splits, a highly fragmented primary key index, and therefore a lot of random disk I\/O. There have already been many articles and conference talks describing this problem. What many of these resources did not do, however, was dive deep into the on\u2011disk structures. That\u2019s what I wanted to explore here.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1024\" src=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/cyberpunk-key-768x1024.png\" alt=\"\" class=\"wp-image-10405\" style=\"aspect-ratio:0.7500060158336742;width:386px;height:auto\" srcset=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/cyberpunk-key-768x1024.png 768w, https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/cyberpunk-key-225x300.png 225w, https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/cyberpunk-key-600x800.png 600w, https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/cyberpunk-key-180x240.png 180w, https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/cyberpunk-key.png 864w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-what-are-uuids\">What are UUIDs<\/h4>\n\n\n\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\n<p>UUID (Universally Unique Identifier) is a 16\u2011byte integer value (128 bits), which has 2^128 possible combinations (approximately 3.4 \u00d7 10^38). This range is so large that, for most applications, the probability of a duplicate UUID is practically zero. Wikipedia shows a calculation demonstrating that the probability to find a duplicate within 103 trillion version\u20114 UUIDs is about one in a billion. Another often\u2011quoted rule of thumb is that to get a 50% chance of one collision, you\u2019d have to generate roughly 1 billion UUIDs every second for about 86 years.<\/p>\n<\/div>\n\n\n\n<p>Values are usually represented as a 36\u2011character string with hexadecimal digits and hyphens, for example: <strong>f47ac10b-58cc-4372-a567-0e02b2c3d479<\/strong>. The canonical layout is 8\u20114\u20114\u20114\u201112 characters. The first character in the third block and the first character in the fourth block have special meaning: <strong>xxxxxxxx-xxxx-Vxxx-Wxxx-xxxxxxxxxxxx<\/strong> &#8211; <strong>V<\/strong> marks UUID version (4 for UUIDv4, 7 for UUIDv7, etc.), <strong>W<\/strong> encodes the variant in its upper 2 or 3 bits (the layout family of the UUID).<\/p>\n\n\n\n<p>Until PostgreSQL 18, the common way to generate UUIDs in PostgreSQL was to use version\u20114 (for example via gen_random_uuid() or uuid_generate_v4() from extensions). PostgreSQL 18 introduces native support for the new time\u2011ordered UUIDv7 via uuidv7() function, and also adds uuidv4() as a built\u2011in alias for older gen_random_uuid() function. UUID version 4 is generated completely randomly (except for the fixed version and variant bits), so there is no inherent sequence in the values. UUID version 7 generates values that are time\u2011ordered, because the first 48 bits contain a big\u2011endian Unix epoch timestamp with roughly millisecond granularity, followed by additional sub\u2011millisecond bits and randomness.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"540\" height=\"557\" src=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/elephant.png\" alt=\"Slonik, the PostgreSQL elephant logo\" class=\"wp-image-10407\" style=\"width:294px;height:auto\" srcset=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/elephant.png 540w, https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/elephant-291x300.png 291w, https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/elephant-180x186.png 180w\" sizes=\"auto, (max-width: 540px) 100vw, 540px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-test-setup-in-postgresql-18\">Test setup in PostgreSQL 18<\/h4>\n\n\n\n<p>I will show concrete results using a simple test setup &#8211; 2 different tables with column &#8220;id&#8221; containing generated UUID value (either v4 or v7), used as primary key, column &#8220;ord&#8221; with sequentially generated bigint, preserving the row creation order.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">-- UUIDv4 (completely random keys)\nCREATE TABLE uuidv4_demo (\n    id uuid PRIMARY KEY DEFAULT uuidv4(), -- alias of gen_random_uuid()\n    ord bigint GENERATED ALWAYS AS IDENTITY\n);\n\n-- UUIDv7 (time-ordered keys)\nCREATE TABLE uuidv7_demo (\n    id uuid PRIMARY KEY DEFAULT uuidv7(),\n    ord bigint GENERATED ALWAYS AS IDENTITY\n);\n\n-- 1M rows with UUIDv4\nINSERT INTO uuidv4_demo (id) SELECT uuidv4() FROM generate_series(1, 1000000);\n\n-- 1M rows with UUIDv7\nINSERT INTO uuidv7_demo (id) SELECT uuidv7() FROM generate_series(1, 1000000);\n\nVACUUM ANALYZE uuidv4_demo;\nVACUUM ANALYZE uuidv7_demo;<\/pre>\n<\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-query-level-performance-explain-analyze\">Query\u2011level performance: EXPLAIN ANALYZE<\/h4>\n\n\n\n<p>As the first step, let&#8217;s compare the costs of ordering by UUID for the two tables:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">-- UUIDv4\nEXPLAIN (ANALYZE, BUFFERS) SELECT * FROM uuidv4_demo ORDER BY id;\n\nIndex Scan using uuidv4_demo_pkey on uuidv4_demo (cost=0.42..60024.31 rows=1000000 width=24) (actual time=0.031..301.163 rows=1000000.00 loops=1)\n  Index Searches: 1\n  Buffers: shared hit=1004700 read=30\nPlanning Time: 0.109 ms\nExecution Time: 318.005 ms\n\n-- UUIDv7\nEXPLAIN (ANALYZE, BUFFERS) SELECT * FROM uuidv7_demo ORDER BY id;\n\nIndex Scan using uuidv7_demo_pkey on uuidv7_demo (cost=0.42..36785.43 rows=1000000 width=24) (actual time=0.013..96.177 rows=1000000.00 loops=1)\n  Index Searches: 1\n  Buffers: shared hit=2821 read=7383\nPlanning Time: 0.040 ms\nExecution Time: 113.305 ms<\/pre>\n<\/blockquote>\n\n\n\n<p>The exact buffer numbers depend on caching effects, but one thing is clear in this run: the index scan over UUIDv7 needs roughly 100 times less buffer hits and is around three times faster (113 ms vs 318 ms) for the same million\u2011row ORDER BY id. This is the first sign that UUIDv7 is a very viable solution for a primary key when we need to replace a BIGINT column with something that has a much larger space and uniqueness, while still behaving like a sequential key from the point of view of the index.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-speed-of-inserts-simple-benchmarking\">Speed of Inserts &#8211; simple benchmarking<\/h4>\n\n\n\n<p>Originally I wanted to make more sophisticated tests, but even very basic naive benchmark showed huge difference in speed of inserts. I compared time taken to insert 50 million rows into empty table, then again, into the table with 50 million existing rows.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">INSERT INTO uuidv4_demo (id) SELECT uuidv4() FROM generate_series(1, 50000000);\nINSERT INTO uuidv7_demo (id) SELECT uuidv7() FROM generate_series(1, 50000000);\n\n-- UUID v4                                 -- UUID v7\n                                Empty table\nInsert time: 1239839.702 ms (20:39.840)    Insert time: 106343.314 ms (01:46.343)\nTable size: 2489 MB                        Table size: 2489 MB\nIndex size: 1981 MB                        Index size: 1504 MB\n\n                            Table with 50M rows\nInsert time: 2776880.790 ms (46:16.881)    Insert time: 100354.087 ms (01:40.354)\nTable size: 4978 MB                        Table size: 4978 MB\nIndex size: 3956 MB                        Index size: 3008 MB<\/pre>\n<\/blockquote>\n\n\n\n<p>As we can see, speed of inserts is radically different. Insertion of the first 50 million rows into empty table took only 1:46 minutes for UUIDv7, but already 20 minutes for UUIDv4. Second batch showed even 2 times bigger difference.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-how-values-are-distributed-in-the-table\">How values are distributed in the table<\/h4>\n\n\n\n<p>These results indicate huge differences in indexes. So let&#8217;s analyze it. First we will check how the values are distributed in the table, I use the following query for both tables (just switching the table name):<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">SELECT\n    row_number() OVER () AS seq_in_uuid_order,\n    id,\n    ord,\n    ctid\nFROM uuidv4_demo\nORDER BY id\nLIMIT 20;<\/pre>\n<\/blockquote>\n\n\n\n<p>Column seq_in_uuid_order is just the row number in UUID order,&nbsp;ord is the insertion order,&nbsp;ctid shows the physical location of each tuple in the heap: (block_number, offset_in_block).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-uuidv4-random-uuid-order-random-heap-access\">UUIDv4: random UUID order \u21d2 random heap access<\/h4>\n\n\n\n<p>How do the results look for UUIDv4?<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\"> seq_in_uuid_order |                 id                   |   ord  |    ctid \n-------------------+--------------------------------------+--------+------------\n                 1 | 00000abf-cc8e-4cb2-a91a-701a3c96bd36 | 673969 | (4292,125)\n                 2 | 00001827-16fe-4aee-9bce-d30ca49ceb1d | 477118 | (3038,152)\n                 3 | 00001a84-6d30-492f-866d-72c3b4e1edff | 815025 | (5191,38)\n                 4 | 00002759-21d1-4889-9874-4a0099c75286 | 879671 | (5602,157)\n                 5 | 00002b44-b1b5-473f-b63f-7554fa88018d | 729197 | (4644,89)\n                 6 | 00002ceb-5332-44f4-a83b-fb8e9ba73599 | 797950 | (5082,76)\n                 7 | 000040e2-f6ac-4b5e-870a-63ab04a5fa39 | 160314 | (1021,17)\n                 8 | 000053d7-8450-4255-b320-fee8d6246c5b | 369644 | (2354,66)\n                 9 | 00009c78-6eac-4210-baa9-45b835749838 | 463430 | (2951,123)\n                10 | 0000a118-f98e-4e4a-acb3-392006bcabb8 |  96325 | (613,84)\n                11 | 0000be99-344b-4529-aa4c-579104439b38 | 454804 | (2896,132)\n                12 | 00010300-fcc1-4ec4-ae16-110f93023068 |  52423 | (333,142)\n                13 | 00010c33-a4c9-4612-ba9a-6c5612fe44e6 |  82935 | (528,39)\n                14 | 00011fa2-32ce-4ee0-904a-13991d451934 | 988370 | (6295,55)\n                15 | 00012920-38c7-4371-bd15-72e2996af84d | 960556 | (6118,30)\n                16 | 00014240-7228-4998-87c1-e8b23b01194a |  66048 | (420,108)\n                17 | 00014423-15fc-42ca-89bd-1d0acf3e5ad2 | 250698 | (1596,126)\n                18 | 000160b9-a1d8-4ef0-8979-8640025c0406 | 106463 | (678,17)\n                19 | 0001711a-9656-4628-9d0c-1fb40620ba41 | 920459 | (5862,125)\n                20 | 000181d5-ee13-42c7-a9e7-0f2c52faeadb | 513817 | (3272,113)<\/pre>\n<\/blockquote>\n\n\n\n<p>Values are distributed completely randomly. Reading rows in UUID order practically does not make sense here and leads directly into random heap access for queries that use the primary key index.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-uuidv7-uuid-order-follows-insertion-order\">UUIDv7: UUID order follows insertion order<\/h4>\n\n\n\n<p>On the other hand, UUIDv7 values are generated in a clear sequence:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\"> seq_in_uuid_order |                  id                  | ord | ctid \n-------------------+--------------------------------------+-----+--------\n                 1 | 019ad94d-0127-7aba-b9f6-18620afdea4a |   1 | (0,1)\n                 2 | 019ad94d-0131-72b9-823e-89e41d1fad73 |   2 | (0,2)\n                 3 | 019ad94d-0131-7384-b03d-8820be60f88e |   3 | (0,3)\n                 4 | 019ad94d-0131-738b-b3c0-3f91a0b223a8 |   4 | (0,4)\n                 5 | 019ad94d-0131-7391-ab84-a719ca98accf |   5 | (0,5)\n                 6 | 019ad94d-0131-7396-b41d-7f9f27a179c4 |   6 | (0,6)\n                 7 | 019ad94d-0131-739b-bdb3-4659aeaafbdd |   7 | (0,7)\n                 8 | 019ad94d-0131-73a0-b271-7dba06512231 |   8 | (0,8)\n                 9 | 019ad94d-0131-73a5-8911-5ec5d446c8a9 |   9 | (0,9)\n                10 | 019ad94d-0131-73aa-a4a3-0e5c14f09374 |  10 | (0,10)\n                11 | 019ad94d-0131-73af-ac4b-3710e221390e |  11 | (0,11)\n                12 | 019ad94d-0131-73b4-85d6-ed575d11e9cf |  12 | (0,12)\n                13 | 019ad94d-0131-73b9-b802-d5695f5bf781 |  13 | (0,13)\n                14 | 019ad94d-0131-73be-bcb0-b0775dab6dd4 |  14 | (0,14)\n                15 | 019ad94d-0131-73c3-9ec8-c7400b5c8983 |  15 | (0,15)\n                16 | 019ad94d-0131-73c8-b067-435258087b3a |  16 | (0,16)\n                17 | 019ad94d-0131-73cd-a03f-a28092604fb1 |  17 | (0,17)\n                18 | 019ad94d-0131-73d3-b4d5-02516d5667b5 |  18 | (0,18)\n                19 | 019ad94d-0131-73d8-9c41-86fa79f74673 |  19 | (0,19)\n                20 | 019ad94d-0131-73dd-b9f1-dcd07598c35d |  20 | (0,20)<\/pre>\n<\/blockquote>\n\n\n\n<p>Here, seq_in_uuid_order, ord, and ctid all follow each other nicely &#8211;&nbsp;ord increases by 1 for each row,&nbsp;ctid moves sequentially through the first heap page, and&nbsp;UUIDs themselves are monotonic because of the timestamp prefix.&nbsp;For index scans on the primary key, this means Postgres can walk the heap in a much more sequential way than with UUIDv4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-how-sequential-are-these-values-statistically\">How sequential are these values statistically?<\/h4>\n\n\n\n<p>After VACUUM ANALYZE, I ask the planner what it thinks about the correlation between id and the physical order:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">SELECT\n    tablename,\n    attname,\n    correlation\nFROM pg_stats\nWHERE tablename IN ('uuidv4_demo', 'uuidv7_demo')\nAND attname = 'id'\nORDER BY tablename, attname;<\/pre>\n<\/blockquote>\n\n\n\n<p>Result:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">   tablename | attname | correlation \n-------------+---------+---------------\n uuidv4_demo |      id | -0.0024808696\n uuidv7_demo |      id |             1<\/pre>\n<\/blockquote>\n\n\n\n<p>The statistics confirm what we just saw:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>For uuidv4_demo.id, the correlation is essentially 0 \u21d2 values are random with respect to heap order.<\/li>\n\n\n\n<li>For uuidv7_demo.id, the correlation is 1 \u21d2 perfect alignment between UUID order and physical row order in this test run.<\/li>\n<\/ul>\n\n\n\n<p>That high correlation is exactly why UUIDv7 is so attractive as a primary key for B\u2011tree indexes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-primary-key-indexes-size-leaf-pages-density-fragmentation\">Primary key indexes: size, leaf pages, density, fragmentation<\/h4>\n\n\n\n<p>Next I look at the primary key indexes \u2013 their size, number of leaf pages, density, and fragmentation \u2013 using pgstatindex:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">SELECT 'uuidv4_demo_pkey' AS index_name, (pgstatindex('uuidv4_demo_pkey')).*;\n\n        index_name | uuidv4_demo_pkey\n           version | 4\n        tree_level | 2\n        index_size | 40026112\n     root_block_no | 295\n    internal_pages | 24\n        leaf_pages | 4861\n       empty_pages | 0\n     deleted_pages | 0\n  avg_leaf_density | 71          \nleaf_fragmentation | 49.99       \n\nSELECT 'uuidv7_demo_pkey' AS index_name, (pgstatindex('uuidv7_demo_pkey')).*;\n\n        index_name | uuidv7_demo_pkey\n           version | 4\n        tree_level | 2\n        index_size | 31563776\n     root_block_no | 295\n    internal_pages | 20\n        leaf_pages | 3832\n       empty_pages | 0\n     deleted_pages | 0\n  avg_leaf_density | 89.98      -- i.e. standard 90% fillfactor\nleaf_fragmentation | 0\n\n<\/pre>\n<\/blockquote>\n\n\n\n<p>We can immediately see that the primary key index on UUIDv4 is about 26\u201327% bigger:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>index_size is ~40 MB vs ~31.6 MB<\/li>\n\n\n\n<li>leaf_pages are 4861 vs 3832 (again about 26\u201327% more)<\/li>\n\n\n\n<li>leaf pages in the v4 index have lower average density (71 vs ~90)<\/li>\n\n\n\n<li>leaf_fragmentation for v4 is about 50%, while for v7 it is 0<\/li>\n<\/ul>\n\n\n\n<p>So UUIDv4 forces the B\u2011tree to allocate more pages and keep them less full, and it fragments the leaf level much more.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-deeper-index-analysis-with-bt-multi-page-stats\">Deeper index analysis with bt_multi_page_stats<\/h4>\n\n\n\n<p>To go deeper, I examined the B\u2011tree indexes page by page and built some statistics. I used the following query for both indexes (just changing the index name in the CTE). The query calculates the minimum, maximum, and average number of tuples per index leaf page, and also checks how sequentially leaf pages are stored in the index file:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">WITH leaf AS (\n    SELECT *\n    FROM bt_multi_page_stats('uuidv4_demo_pkey', 1, -1) -- from block 1 to end\n    WHERE type = 'l'\n)\nSELECT\n    count(*) AS leaf_pages,\n    min(blkno) AS first_leaf_blk,\n    max(blkno) AS last_leaf_blk,\n    max(blkno) - min(blkno) + 1 AS leaf_span,\n    round( count(*)::numeric \/ (max(blkno) - min(blkno) + 1), 3) AS leaf_density_by_span,\n    min(live_items) AS min_tuples_per_page,\n    max(live_items) AS max_tuples_per_page,\n    avg(live_items)::numeric(10,2) AS avg_tuples_per_page,\n    sum(CASE WHEN btpo_next = blkno + 1 THEN 1 ELSE 0 END) AS contiguous_links,\n    sum(CASE WHEN btpo_next &lt;&gt; 0 AND btpo_next &lt;&gt; blkno + 1 THEN 1 ELSE 0 END) AS non_contiguous_links\nFROM leaf;<\/pre>\n<\/blockquote>\n\n\n\n<p>Results for UUIDv4:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">-- uuidv4_demo_pkey\n          leaf_pages | 4861\n      first_leaf_blk | 1\n       last_leaf_blk | 4885\n           leaf_span | 4885\nleaf_density_by_span | 0.995\n min_tuples_per_page | 146\n max_tuples_per_page | 291\n avg_tuples_per_page | 206.72\n    contiguous_links | 0\nnon_contiguous_links | 4860<\/pre>\n<\/blockquote>\n\n\n\n<p>Results for UUIDv7:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">-- uuidv7_demo_pkey\n          leaf_pages | 3832\n      first_leaf_blk | 1\n       last_leaf_blk | 3852\n           leaf_span | 3852\nleaf_density_by_span | 0.995\n min_tuples_per_page | 109\n max_tuples_per_page | 262\n avg_tuples_per_page | 261.96\n    contiguous_links | 3812\nnon_contiguous_links | 19<\/pre>\n<\/blockquote>\n\n\n\n<p>As we can see- the UUIDv4 index has more leaf pages, spread over a larger span of blocks, and although it has higher minimum and maximum tuples per page, its average number of tuples per leaf page (206.72) is significantly lower than for UUIDv7 (261.96).<\/p>\n\n\n\n<p>But these numbers can obscure the whole pictures. So, let&#8217;s look at histograms visualizing count of tuples in leaf pages. For this I will use following query with buckets between 100 and 300 and will list only non empty results:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">WITH leaf AS (\n    SELECT live_items\n    FROM bt_multi_page_stats('uuidv4_demo_pkey', 1, -1)\n    WHERE type = 'l'\n),\nbuckets AS (\n    -- bucket lower bounds: 100, 110, ..., 290\n    SELECT generate_series(100, 290, 10) AS bucket_min\n)\nSELECT\n    b.bucket_min AS bucket_from,\n    b.bucket_min + 9 AS bucket_to,\n    COUNT(l.live_items) AS page_count\nFROM buckets b\nLEFT JOIN leaf l\n    ON l.live_items BETWEEN b.bucket_min AND b.bucket_min + 9\nGROUP BY b.bucket_min HAVING count(l.live_items) &gt; 0\nORDER BY b.bucket_min;<\/pre>\n<\/blockquote>\n\n\n\n<p>Result for UUIDv4:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\"> bucket_from | bucket_to | page_count \n-------------+-----------+------------\n         140 |       149 |        159\n         150 |       159 |        435\n         160 |       169 |        388\n         170 |       179 |        390\n         180 |       189 |        427\n         190 |       199 |        466\n         200 |       209 |        430\n         210 |       219 |        387\n         220 |       229 |        416\n         230 |       239 |        293\n         240 |       249 |        296\n         250 |       259 |        228\n         260 |       269 |        214\n         270 |       279 |        171\n         280 |       289 |        140\n         290 |       299 |         21<\/pre>\n<\/blockquote>\n\n\n\n<p>Result for UUIDv7:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\"> bucket_from | bucket_to | page_count \n-------------+-----------+------------\n         100 |       109 |          1\n         260 |       269 |       3831<\/pre>\n<\/blockquote>\n\n\n\n<p>There results nicely demonstrate huge fragmentation of UUIDv4 index and stable compact structure of UUIDv7 index. The lowest buckets in UUIDv4 histogram show cases of half empty leaf index pages, on the other hand pages with more than 270 tuples exceed 90% fillfactor, because PostgreSQL uses remaining free space to avoid split. In the UUIDv7 index all leaf pages except for one (the very last one in the tree) are filled up to 90% standard fillfactor.<\/p>\n\n\n\n<p>Another important result is in the last two columns of index statistics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>For UUIDv4: contiguous_links = 0, non_contiguous_links = 4860<\/li>\n\n\n\n<li>For UUIDv7: contiguous_links = 3812, non_contiguous_links = 19<\/li>\n<\/ul>\n\n\n\n<p>btpo_next = blkno + 1 means the next leaf page in the logical B\u2011tree order is also the next physical block. With UUIDv4, that never happens in this test \u2013 the leaf pages are completely fragmented, randomly distributed over the index structure. With UUIDv7, almost all leaf pages are contiguous, i.e. nicely follow each other.<\/p>\n\n\n\n<p>Also, when we examine the actual content of leaf pages, we can immediately see the randomness of UUIDv4 versus the sequential behavior of UUIDv7: UUIDv4 leaf pages point to heap tuples scattered all over the table, while UUIDv7 leaf pages tend to point into tight ranges of heap pages. The result is the same pattern we saw earlier when looking at ctid directly from the table, so I won\u2019t repeat the raw dumps here.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-a-small-gotcha-embedded-timestamp-in-uuidv7\">A small gotcha: embedded timestamp in UUIDv7<\/h4>\n\n\n\n<p>There is one small gotcha with UUIDv7 values: they expose a timestamp of creation. PostgreSQL 18 exposes this explicitly via uuid_extract_timestamp():<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">SELECT \n    id,\n    uuid_extract_timestamp(id) AS created_at_from_uuid\nFROM uuidv7_demo \nORDER BY ord\nLIMIT 5;<\/pre>\n<\/blockquote>\n\n\n\n<p>Sample results:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-preformatted\">                   id                 |       created_at_from_uuid \n--------------------------------------+----------------------------\n 019ad94d-0127-7aba-b9f6-18620afdea4a | 2025-12-01 09:44:53.799+00\n 019ad94d-0131-72b9-823e-89e41d1fad73 | 2025-12-01 09:44:53.809+00\n 019ad94d-0131-7384-b03d-8820be60f88e | 2025-12-01 09:44:53.809+00\n 019ad94d-0131-738b-b3c0-3f91a0b223a8 | 2025-12-01 09:44:53.809+00\n 019ad94d-0131-7391-ab84-a719ca98accf | 2025-12-01 09:44:53.809+00<\/pre>\n<\/blockquote>\n\n\n\n<p>If we look at the whole sequence of values, we can analyze the time deltas between record creations directly from the UUIDs, without any separate timestamp column. For some applications this could be considered a potential information leak (for example, revealing approximate creation times or request rates), while many others will most likely not care.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-summary\">Summary<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>UUIDs provide an enormous identifier space (128 bits, ~3.4 \u00d7 10^38 values) where the probability of collision is negligible for real\u2011world workloads.<\/li>\n\n\n\n<li>Traditional UUIDv4 keys are completely random. When used as primary keys in PostgreSQL, they tend to:\n<ul class=\"wp-block-list\">\n<li>fragment B\u2011tree indexes<\/li>\n\n\n\n<li>lower leaf page density<\/li>\n\n\n\n<li>cause highly random heap access patterns and more random I\/O<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>UUIDv7, introduced natively in PostgreSQL 18 as uuidv7(), keeps the 128\u2011bit space but reorders the bits so that:\n<ul class=\"wp-block-list\">\n<li>the most significant bits contain a Unix timestamp with millisecond precision (plus sub\u2011millisecond fraction)<\/li>\n\n\n\n<li>the remaining bits stay random<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>In practical tests with 1M rows per table:\n<ul class=\"wp-block-list\">\n<li>The UUIDv7 primary key index was about 26\u201327% smaller, with fewer leaf pages and much higher average leaf density<\/li>\n\n\n\n<li>Leaf pages in the UUIDv7 index were overwhelmingly physically contiguous, whereas the UUIDv4 leaf pages were completely fragmented<\/li>\n\n\n\n<li>An ORDER BY id query over UUIDv7 was roughly three times faster in my run than the same query over UUIDv4, thanks to better index locality and more sequential heap access<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>The trade\u2011off is that UUIDv7 embeds a timestamp, which might expose approximate creation times, but for most use cases this is acceptable or even useful.&nbsp;So, UUIDv7 significantly improves the performance and physical layout of UUID primary keys in PostgreSQL, not by abandoning randomness, but by adding a time\u2011ordered prefix. In PostgreSQL 18, that gives us the best of both worlds: the huge identifier space and distributed generation benefits of UUIDs, with index behavior much closer to a classic sequential BIGINT primary key.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><a href=\"https:\/\/www.postgresql.org\/\">PostgreSQL<\/a> is an open-source database provided by the PostgreSQL developers. The PostgreSQL Elephant Logo (&#8220;Slonik&#8221;), Postgres and PostgreSQL are registered trademarks by the PostgreSQL Community Association.<\/p>\n\n\n\n<p>We at credativ provide comprehensive support and consulting services running PostgreSQL and other open-source systems. <\/p>\n\n\n\n<p> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the past there have been many discussions about using UUID as a primary key in PostgreSQL. For some applications, even a BIGINT column does not have sufficient range: it is a signed 8\u2011byte integer with range \u22129,223,372,036,854,775,808 to +9,223,372,036,854,775,807. Although these values look big enough, if we think about web services that collect billions [&hellip;]<\/p>\n","protected":false},"author":82,"featured_media":10406,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_improvement_type_select":"improve_an_existing","_thumb_yes_seoaic":false,"_frame_yes_seoaic":false,"seoaic_generate_description":"","seoaic_improve_instructions_prompt":"","seoaic_rollback_content_improvement":"","seoaic_idea_thumbnail_generator":"","thumbnail_generated":false,"thumbnail_generate_prompt":"","seoaic_article_description":"","seoaic_article_subtitles":[],"footnotes":""},"categories":[1708],"tags":[1707,1887,1801,2165,2166],"class_list":["post-10348","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-postgresql-en","tag-planetpostgres","tag-planetpostgresql","tag-postgresql-en","tag-uuid","tag-uuidv7"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.4 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>UUIDv7 in PostgreSQL: A new key approach - credativ\u00ae<\/title>\n<meta name=\"description\" content=\"Learn how UUIDv7 in PostgreSQL reduces conflicts in data management and why it increases efficiency.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18\" \/>\n<meta property=\"og:description\" content=\"Learn how UUIDv7 in PostgreSQL reduces conflicts in data management and why it increases efficiency.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/\" \/>\n<meta property=\"og:site_name\" content=\"credativ\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/credativDE\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-12-05T11:43:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-05T11:53:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/UUID-key.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Josef Machytka\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@credativde\" \/>\n<meta name=\"twitter:site\" content=\"@credativde\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Josef Machytka\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/\"},\"author\":{\"name\":\"Josef Machytka\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#\\\/schema\\\/person\\\/b5f03833b09ed0acd1c8d3307d05bd1a\"},\"headline\":\"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18\",\"datePublished\":\"2025-12-05T11:43:58+00:00\",\"dateModified\":\"2025-12-05T11:53:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/\"},\"wordCount\":1853,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/UUID-key.png\",\"keywords\":[\"planetpostgres\",\"planetpostgresql\",\"PostgreSQL\u00ae\",\"UUID\",\"UUIDv7\"],\"articleSection\":[\"PostgreSQL\u00ae\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/\",\"name\":\"UUIDv7 in PostgreSQL: A new key approach - credativ\u00ae\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/UUID-key.png\",\"datePublished\":\"2025-12-05T11:43:58+00:00\",\"dateModified\":\"2025-12-05T11:53:46+00:00\",\"description\":\"Learn how UUIDv7 in PostgreSQL reduces conflicts in data management and why it increases efficiency.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/UUID-key.png\",\"contentUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/UUID-key.png\",\"width\":1920,\"height\":1080,\"caption\":\"UUID is the key\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/\",\"name\":\"credativ GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Organization\",\"Place\"],\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#organization\",\"name\":\"credativ\u00ae\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/\",\"logo\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#local-main-organization-logo\"},\"image\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#local-main-organization-logo\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/credativDE\\\/\",\"https:\\\/\\\/x.com\\\/credativde\",\"https:\\\/\\\/mastodon.social\\\/@credativde\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/credativ-gmbh\",\"https:\\\/\\\/www.instagram.com\\\/credativ\\\/\"],\"description\":\"Die credativ GmbH ist ein f\u00fchrendes, auf Open Source Software spezialisiertes IT-Dienstleistungs- und Beratungsunternehmen. Wir bieten umfassende und professionelle Services, von Beratung und Infrastruktur-Betrieb \u00fcber 24\\\/7 Support bis hin zu individuellen L\u00f6sungen und Schulungen. Unser Fokus liegt auf dem ganzheitlichen Management von gesch\u00e4ftskritischen Open-Source-Systemen, darunter Betriebssysteme (z.B. Linux), Datenbanken (z.B. PostgreSQL), Konfigurationsmanagement (z.B. Ansible, Puppet) und Virtualisierung. Als engagierter Teil der Open-Source-Community unterst\u00fctzen wir unsere Kunden dabei, die Vorteile freier Software sicher, stabil und effizient in ihrer IT-Umgebung zu nutzen.\",\"legalName\":\"credativ GmbH\",\"foundingDate\":\"2025-03-01\",\"duns\":\"316387060\",\"numberOfEmployees\":{\"@type\":\"QuantitativeValue\",\"minValue\":\"11\",\"maxValue\":\"50\"},\"address\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#local-main-place-address\"},\"geo\":{\"@type\":\"GeoCoordinates\",\"latitude\":\"51.1732374\",\"longitude\":\"6.392010099999999\"},\"telephone\":[\"+4921619174200\",\"08002733284\"],\"contactPoint\":{\"@type\":\"ContactPoint\",\"telephone\":\"08002733284\",\"email\":\"vertrieb@credativ.de\"},\"openingHoursSpecification\":[{\"@type\":\"OpeningHoursSpecification\",\"dayOfWeek\":[\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\"],\"opens\":\"09:00\",\"closes\":\"17:00\"},{\"@type\":\"OpeningHoursSpecification\",\"dayOfWeek\":[\"Saturday\",\"Sunday\"],\"opens\":\"00:00\",\"closes\":\"00:00\"}],\"email\":\"info@credativ.de\",\"areaServed\":\"D-A-CH\",\"vatID\":\"DE452151696\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#\\\/schema\\\/person\\\/b5f03833b09ed0acd1c8d3307d05bd1a\",\"name\":\"Josef Machytka\"},{\"@type\":\"PostalAddress\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#local-main-place-address\",\"streetAddress\":\"Hennes-Weisweiler-Allee 23\",\"addressLocality\":\"M\u00f6nchengladbach\",\"postalCode\":\"41179\",\"addressRegion\":\"Deutschland\",\"addressCountry\":\"DE\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/postgresql-en\\\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\\\/#local-main-organization-logo\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/credativ-logo-right.svg\",\"contentUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/credativ-logo-right.svg\",\"caption\":\"credativ\u00ae\"}]}<\/script>\n<meta name=\"geo.placename\" content=\"M\u00f6nchengladbach\" \/>\n<meta name=\"geo.position\" content=\"51.1732374;6.392010099999999\" \/>\n<meta name=\"geo.region\" content=\"Germany\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"UUIDv7 in PostgreSQL: A new key approach - credativ\u00ae","description":"Learn how UUIDv7 in PostgreSQL reduces conflicts in data management and why it increases efficiency.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/","og_locale":"en_US","og_type":"article","og_title":"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18","og_description":"Learn how UUIDv7 in PostgreSQL reduces conflicts in data management and why it increases efficiency.","og_url":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/","og_site_name":"credativ\u00ae","article_publisher":"https:\/\/www.facebook.com\/credativDE\/","article_published_time":"2025-12-05T11:43:58+00:00","article_modified_time":"2025-12-05T11:53:46+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/UUID-key.png","type":"image\/png"}],"author":"Josef Machytka","twitter_card":"summary_large_image","twitter_creator":"@credativde","twitter_site":"@credativde","twitter_misc":{"Written by":"Josef Machytka","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#article","isPartOf":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/"},"author":{"name":"Josef Machytka","@id":"https:\/\/www.credativ.de\/en\/#\/schema\/person\/b5f03833b09ed0acd1c8d3307d05bd1a"},"headline":"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18","datePublished":"2025-12-05T11:43:58+00:00","dateModified":"2025-12-05T11:53:46+00:00","mainEntityOfPage":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/"},"wordCount":1853,"commentCount":1,"publisher":{"@id":"https:\/\/www.credativ.de\/en\/#organization"},"image":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#primaryimage"},"thumbnailUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/UUID-key.png","keywords":["planetpostgres","planetpostgresql","PostgreSQL\u00ae","UUID","UUIDv7"],"articleSection":["PostgreSQL\u00ae"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/www.credativ.de\/#organization"}},{"@type":"WebPage","@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/","url":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/","name":"UUIDv7 in PostgreSQL: A new key approach - credativ\u00ae","isPartOf":{"@id":"https:\/\/www.credativ.de\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#primaryimage"},"image":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#primaryimage"},"thumbnailUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/UUID-key.png","datePublished":"2025-12-05T11:43:58+00:00","dateModified":"2025-12-05T11:53:46+00:00","description":"Learn how UUIDv7 in PostgreSQL reduces conflicts in data management and why it increases efficiency.","breadcrumb":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#primaryimage","url":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/UUID-key.png","contentUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/12\/UUID-key.png","width":1920,"height":1080,"caption":"UUID is the key"},{"@type":"BreadcrumbList","@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.credativ.de\/en\/"},{"@type":"ListItem","position":2,"name":"A deeper look at old UUIDv4 vs new UUIDv7 in PostgreSQL 18"}]},{"@type":"WebSite","@id":"https:\/\/www.credativ.de\/en\/#website","url":"https:\/\/www.credativ.de\/en\/","name":"credativ GmbH","description":"","publisher":{"@id":"https:\/\/www.credativ.de\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.credativ.de\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Organization","Place"],"@id":"https:\/\/www.credativ.de\/en\/#organization","name":"credativ\u00ae","url":"https:\/\/www.credativ.de\/en\/","logo":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#local-main-organization-logo"},"image":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#local-main-organization-logo"},"sameAs":["https:\/\/www.facebook.com\/credativDE\/","https:\/\/x.com\/credativde","https:\/\/mastodon.social\/@credativde","https:\/\/www.linkedin.com\/company\/credativ-gmbh","https:\/\/www.instagram.com\/credativ\/"],"description":"Die credativ GmbH ist ein f\u00fchrendes, auf Open Source Software spezialisiertes IT-Dienstleistungs- und Beratungsunternehmen. Wir bieten umfassende und professionelle Services, von Beratung und Infrastruktur-Betrieb \u00fcber 24\/7 Support bis hin zu individuellen L\u00f6sungen und Schulungen. Unser Fokus liegt auf dem ganzheitlichen Management von gesch\u00e4ftskritischen Open-Source-Systemen, darunter Betriebssysteme (z.B. Linux), Datenbanken (z.B. PostgreSQL), Konfigurationsmanagement (z.B. Ansible, Puppet) und Virtualisierung. Als engagierter Teil der Open-Source-Community unterst\u00fctzen wir unsere Kunden dabei, die Vorteile freier Software sicher, stabil und effizient in ihrer IT-Umgebung zu nutzen.","legalName":"credativ GmbH","foundingDate":"2025-03-01","duns":"316387060","numberOfEmployees":{"@type":"QuantitativeValue","minValue":"11","maxValue":"50"},"address":{"@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#local-main-place-address"},"geo":{"@type":"GeoCoordinates","latitude":"51.1732374","longitude":"6.392010099999999"},"telephone":["+4921619174200","08002733284"],"contactPoint":{"@type":"ContactPoint","telephone":"08002733284","email":"vertrieb@credativ.de"},"openingHoursSpecification":[{"@type":"OpeningHoursSpecification","dayOfWeek":["Monday","Tuesday","Wednesday","Thursday","Friday"],"opens":"09:00","closes":"17:00"},{"@type":"OpeningHoursSpecification","dayOfWeek":["Saturday","Sunday"],"opens":"00:00","closes":"00:00"}],"email":"info@credativ.de","areaServed":"D-A-CH","vatID":"DE452151696"},{"@type":"Person","@id":"https:\/\/www.credativ.de\/en\/#\/schema\/person\/b5f03833b09ed0acd1c8d3307d05bd1a","name":"Josef Machytka"},{"@type":"PostalAddress","@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#local-main-place-address","streetAddress":"Hennes-Weisweiler-Allee 23","addressLocality":"M\u00f6nchengladbach","postalCode":"41179","addressRegion":"Deutschland","addressCountry":"DE"},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.credativ.de\/en\/blog\/postgresql-en\/a-deeper-look-at-old-uuidv4-vs-new-uuidv7-in-postgresql-18\/#local-main-organization-logo","url":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/04\/credativ-logo-right.svg","contentUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/04\/credativ-logo-right.svg","caption":"credativ\u00ae"}]},"geo.placename":"M\u00f6nchengladbach","geo.position":{"lat":"51.1732374","long":"6.392010099999999"},"geo.region":"Germany"},"_links":{"self":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts\/10348","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/users\/82"}],"replies":[{"embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/comments?post=10348"}],"version-history":[{"count":34,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts\/10348\/revisions"}],"predecessor-version":[{"id":10412,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts\/10348\/revisions\/10412"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/media\/10406"}],"wp:attachment":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/media?parent=10348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/categories?post=10348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/tags?post=10348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}