ULIDs and Primary Keys (2022)
blog.daveallie.com
blog.daveallie.com
I think the issue above and UUIDv7’s existence make ULID completely unnecessary.
It doesn’t even make sense to have such a scheme in ULID. The only advantage it has over a 64-bit integer is that ULID is 128-bits but, that doesn’t solve any problem or help with anything. It’s just waste, and will cause pain and confusion.
I would also argue, strongly, that if you are planning to use the datetime an account/event/item was generated, you should track it separately from the UUID, in a dedicated column.
This isn’t intended to refute the article - it was an interesting read and I definitely learned some stuff, but rather to provide an argument for why you might want to stick with v4.
80 bits of randomness is just on the edge of unguessable, though. Most people accept that 128+ bits is cryptographically secure now and in the future.
This is incorrect / outdated. UUIDv7 switched to 48 bits of milliseconds instead of 36 seconds / 12 milliseconds: https://datatracker.ietf.org/doc/html/draft-peabody-dispatch...
The newer draft proposal allows for multiple different options of time information to be added to a UUIDv7 encoding, beyond the typical 48-bits of Unix epoch millisecond data.
https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc...
First thing that isn't correct or changed since this was written:
> There don't seem to be any existing built-in or extension functions that support generating UUIDv7s in PostgreSQL. To generate a UUIDv7, the function below could be tweaked in order to support the correct formatting.
This is the extension I use until UUIDv7 native support lands in PostgreSQL https://github.com/fboulnois/pg_uuidv7. As for native support, it's definitely underway, though it seems to have a few issues keeping up with the version 17 target release: https://commitfest.postgresql.org/47/4388/
> PostgreSQL has built in support for UUIDv4 through the pgcrypto or the uuid-ossp extensions.
PostgreSQL hasn't needed an extension to generate UUIDv4 since v13 which was released in Sep 2020.
Your tokens/identifiers should look like this:
namespace_crockfordEncodedEntropy
- There must be token/identifier prefixes like Stripe. While one could concatenate/prefix these bytes in application code, it's best to just accept the overhead and store them in your records for ease of lookup. It makes an engineer's life so much easier when debugging foreign keys on the fly or during an emergency SEV.
- There should be no hyphens (in string serialization). You probably want to encode and store crockford directly rather than do bytes to hex encoding, again for engineer ease of use.
- You may want to leave some trailing bytes for request routing in active-active high SLA systems. Especially for when record lookup cannot fail.
Doesn’t use the crockford encoding, but does is another one that minimises confusables. Definitely looks pretty solid, so keen to give them a shot in my next project.
Insert performance could be even better, iirc for BTree Indexes monotonic increasing values are better than random ones, but feel free to correct me on that ;)
Using a monotonically increasing PK would cause pages in the index to be allocated and filled sequentially, increasing throughput.
Using random UUIDs would lead to page-splitting and partially-filled pages everywhere, negatively impacting performance and size-on-disk.
As with all databases, measure before you cut.
UUIDv7 support unfortunately didn't make it to Postgres 17, since the RFC wasn't completely finalized yet by the time of feature freeze (April 8), see discussion on pgsql-hackers:
https://www.postgresql.org/message-id/flat/ZhzFQxU0t0xk9mA_%...
So I guess we'll unfortunately have to rely on extensions or client-side generation for the time being, until Postgres 18.
ULIDs and Primary Keys - https://news.ycombinator.com/item?id=34175639 - Dec 2022 (46 comments)
The UX of UUIDs - https://news.ycombinator.com/item?id=39974465 - April 2024 (196 comments)