Last time this discussion came up, someone shared this nice article[0] about all the different ID options. It mentions Stripe IDs, which have pretty prefixes like "prod_foo" and "user_bar". These are great for users of their API (no wondering what an ID refers to) and for internal tooling and debugging, but have to be stored as inefficient varchars, which is not great for indexing and whatnot.<p>So I spent the weekend creating "UPID"[1], which is like ULID but prefixable! Up to four characters for the prefix, 40 bits of time (256ms precision, but could change in a revision) and still 64 bits of randomness. So you can do pretty Stripe-style IDs without losing the benefits of a neat 128-bit UUID column. Have implemented it for Python, Rust and Postgres, maybe worth a kick around for someone!<p>[0] <a href="https://brandur.org/nanoglyphs/026-ids" rel="nofollow">https://brandur.org/nanoglyphs/026-ids</a><p>[1] <a href="https://github.com/carderne/upid">https://github.com/carderne/upid</a>
There's no mention of the UUID v7 in the README. Based on my basic understanding, v7 uses the first 48 bits to encode the Unix epoch, which makes them more useful for sort/indexing scenarios. Might be useful to compare ULID and v7 in the README to make it clearer the benefits one has over the other.
Discussions<p>(238 points, 6 years ago, 129 comments) <a href="https://news.ycombinator.com/item?id=18768909">https://news.ycombinator.com/item?id=18768909</a><p>(213 points, 3 years ago, 100 comments) <a href="https://news.ycombinator.com/item?id=29794186">https://news.ycombinator.com/item?id=29794186</a><p>(33 points, 2 years ago, 23 comments) <a href="https://news.ycombinator.com/item?id=34281969">https://news.ycombinator.com/item?id=34281969</a><p><i>Now that UUIDv7 is lexicographic, does that mean there is no use for ULID?</i> (19 points, 26 days ago, 6 comments) <a href="https://news.ycombinator.com/item?id=40712872">https://news.ycombinator.com/item?id=40712872</a>
It says both:<p>> Within the same millisecond, sort order is not guaranteed<p>And:<p>> Monotonic sort order (correctly detects and handles the same millisecond)<p>Which is it?<p>To make it more confusing, the spec later contains a section about monotonic sort order[1]. And looks like not all libraries implement it [2].<p>[1]: <a href="https://github.com/ulid/spec?tab=readme-ov-file#monotonicity">https://github.com/ulid/spec?tab=readme-ov-file#monotonicity</a><p>[2]: <a href="https://github.com/suyash/ulid/issues/10">https://github.com/suyash/ulid/issues/10</a>
Using ULID has probably the best ROI among all the architectural decisions I've made. Generating IDs on the server before insert is helpful, and not just for distributed system issues.<p>Issues to think about before you switch:<p>- The ID includes the timestamp of it's creation. If you don't want to leak it, you should use another identifier along with it. (I've never needed this in my use cases)<p>- You won't be able to see the ID in its common representation format if you are using a database GUI. (I'm using Postico 2 for postgresql and the developer was kind enough to add "display as Crockford Base 32" to bytea columns making this a non-issue for me. UUIDv7 will also fix this.)
<a href="https://github.com/grantcarthew/awesome-unique-id">https://github.com/grantcarthew/awesome-unique-id</a><p>Here's a great list of many IDs if you haven't got enough dillema on what to use. Everyone is welcome to contribute
While looking into a replacement for auto increment primary keys, I also encountered TSIDs / Snowflakes. At least with TSIDs you can store them easily as 64 bit integers; ULIDs were not as compact. Haven't made a decision yet though.
Do ULIDs have a defined endianness for their binary representation? Because there was none defined for UUIDs and there ended up to be two versions of it: Big Endian and Microsoft. That mess has created many problems.
An auto incrementing integer (for internal use) and a string (for external) will be enough for the vast majority of use cases, is simple to understand, and works well.
Hot take: I wish people just used UUIDs as UUIDs, instead of seeing the plethora of bits and going "it's free real estate". Treat it like a random identifier and move on with your life, rather than having all sorts of weird emergent properties that kinda sorta provide something valuable but not if you squint at it too hard.