I'm the writer. I'm just not very interested in the topic. Just annoyed about UUID overuse enough to write a post. It's also superficial because Tom's video already explains the matter of uniqueness quite well.
The main advantage with UUIDs (and why I now use them widely everywhere) is with relations, foreign keys, multi-region setups, replication, backups, and the ease of restoring those backups.
With sequential IDs, the database state is pretty rigid and cannot easily be restored while still in continuous use, because you can relatively easily run into primary key collisions/violations that can make it incredibly difficult to backup and restore data without taking the whole database offline for writes. Things like scaling out to multi-region and sharding also can get pretty quickly problematic - you end up with duplicate IDs that makes it impossible to easily move data between regions - unless you use a centralized unique ID service (see Twitter's Snowflake for an example). UUIDs just avoids this issue entirely and you can move data around with ease.
With UUIDs, things like being able to grab some test data from production, scrub it, insert it into your local database, test with it, and then update it back to staging or production uses trivial normal insert/update operations.
With sequential IDs, this task becomes a nightmare of ID collisions and manually altering foreign keys if you do run into duplicate IDs.
If anything really does need to be exposed to end users, I typically use another unique string field like username, post slug, etc. rather than directly exposing the UUID to search engine traffic, while still using UUIDs internally everywhere within my database.
It's not like the only two choices you have in the world are UUIDs and auto-incrementing sequential IDs.
There are many better alternatives to UUID for the general case in which UUIDv4 is used, that provide some of the following advantages (based on the implementation):
- Simpler spec and implementation
- Easier to enforce compatibility across implementations (no ambiguity about letter case, order or hyphenation)
- Smaller size and better readability
- Lexicographically sortable based on time of generation
- Deterministic uniqueness guarantee
UUID is too much of a jack-of-all-trades-master-of-none. It originally defined many versions (which should have been called "formats") for flexibility, but nowadays only UUIDv4 (and less often UUIDv1) seem to be in use. UUIDv3 and UUIDv5 rely on the insecure MD5 and SHA-1, which, while it seems UUIDv2 and Nil UUIDs were rarely ever used.
I hate it when developers are always reaching immediately for UUIDv4 while they almost always have a better choice for their case.
Agreed, I don't understand why anyone reaches for uuid v4; it's the dumbest thing out there that sees regular use for no reason whatsoever. The number of developers who reach for uuid v4 is scary; I swear they don't understand what it contains, or care to think critically about their use case. The worst is reading about using uuid v4 for "offline client-side ID generation", such that any client can fixate object IDs that wind up in the server's database, and in fact are likely NOT unique if you have nefarious clients purposely generating duplicates client-side.
There is also no reason to give up 6 reserved bits of a uuid v4's 128 bits (it's only 122 random bits + 6 bits of unnecessary version info). If you want random IDs, make your own. Simply generate 16 bytes of raw data; or combine two random 64-bit integers; or combine a timestamp prefix with random bytes at the end. Your needs probably don't warrant exactly 128 (well, 122 bits) that uuid v4 gives anyway, so you can customize to a specific number of bits. You can also use base62 (0-9, A-Z, a-z) or base64 instead of hexadecimal (0-9, A-F) to reduce the number of displayed characters (eg. in URLs), while omitting the stupid hyphens of a uuid too.
tldr; uuid v4 shouldn't even exist, and certainly should not be used unless integrating with pre-existing systems.
I'm the OP. Well, I've used UUID to generate ids on the client-side for a metrics system. Well, if someone submitted duplicated data, my server would ignore it. The context is critical to decide whether you can let clients generate an ID or not. In my case, the worst that could happen would be a Denial-of-Service attack if someone found a weakness in the UUID algorithm I relied upon.
> There are many better alternatives to UUID for the general case in which UUIDv4 is used, that provide some of the following advantages (based on the implementation): - Simpler spec and implementation - Easier to enforce compatibility across implementations (no ambiguity about letter case, order or hyphenation) - Smaller size and better readability - Lexicographically sortable based on time of generation - Deterministic uniqueness guarantee
Could you name a few with their trade off or point me to some resources? I only know about UUIDs and auto-incrementing sequentail ID, but I would love to add a few tools to my toolbox.
Your points are true, but UUID is built-in to most databases, and thus the most easy to use and rely upon everywhere (i.e. "id" uuid NOT NULL DEFAULT uuid_generate_v4()). That's why it gets the most use now, and will continue to do so in the future.
PostgreSQL (and other RDBMS) also supports storing and indexing the data in UUIDs in a binary format. With binary, the space and speed concerns are greatly minimized, especially when comparing UUIDs to other randomly generated homegrown strings.
There should be a name for this kind of article, this sort of know-it-all hectoring that occurs in so much media now. It goes well beyond the technical fields - think of how many parenting, cooking, and athletics blogs and articles hasten to inform you “you’re doing it wrong.”
No doubt this phenomenon successfully plucks at some emotional vulnerability most of us have, and thus brings in the clicks.
edit: I also disagree with most of the points this article makes, but that’s just, like, my opinion, man.
The Amazon example is so weak. Who the f navigates to a product page by typing the ID in the URL?
The only argument I can think of in favor of this proposed alternative is if at some point in your business workflow someone needs to manually type an ID and cannot copy paste it. Sounds pretty rare to me. Even support is now done more and more via chat systems.
It's also a URL coming from a link shortener, the slug on it doesn't seem related to any ID on the product page's full URL. The product behind the url could have been using a UUID if they wanted to.
Why do people forget that uuids were created to solve a real problem: generating ids on remote/distributed systems where a central authority is not available. This makes distributed systems way easier as you can assume any id you generate anywhere is valid immediately. Any article offering alternatives to uuid needs to start with this problem as a prerequisite.
The thing I like about UUIDs is that they're universal, so if we make contact with aliens they'll be like "don't worry, our UUIDs don't overlap with yours!"
The thing I don't like about UUIDs is that they're not necessarily unique across multiple universes.
Does anyone else get a weird feeling when generating a uuid to not generate too many because there are only a finite number? Because they are mostly considered unique … I feel like I’m wasting them.
I sometimes have this odd cognitive dissonance about it and have to consciously remind myself that this intuition is ridiculous.
No. I've got a similar feeling for other silly stuff, like if I create a temporary file and lose its reference. I start thinking, "okay, in 10 years, it'll still be there," even though this is not usually true.
The counterpoint is "You Don't Need to Micro-Optimise Your PK Type".
UUIDs offer by far the best developer UX. They're first class objects for most of your tech stack, and they eliminate or massively simplify a lot of potential backend issues, from idempotency to merges to sharding.
The main downsides are two:
- They're not human friendly. This is a good thing. Surrogate keys should never be exposed to the human user, because what is a 1:1 mapping today may not be 1:1 any longer tomorrow. If you need to let the user input a unique object reference manually, you're free to design that reference with human UX in mind. Maybe it's a set of dictionary words, maybe it's a code with an expiration date, maybe it's the same code but referring to different versions of the object depending on the user.
The only people who may need to copy/paste UUIDs manually are database admins, and they will thank you so much more for never bothering them with fixing a pkey clash or an accidental join on the wrong key.
- They are less performant than sequential integers. For 99% of projects this is not going to be an actual issue. Once you _do_ find that your queries are being slowed down by the size of primary keys specifically, you have my absolute blessing to add an integer sequence column and make that the primary key.
30 comments
[ 2.5 ms ] story [ 79.1 ms ] threadA superficial post. Doesn't talk at all about when/when-not to use source-generated random identifiers.
With sequential IDs, the database state is pretty rigid and cannot easily be restored while still in continuous use, because you can relatively easily run into primary key collisions/violations that can make it incredibly difficult to backup and restore data without taking the whole database offline for writes. Things like scaling out to multi-region and sharding also can get pretty quickly problematic - you end up with duplicate IDs that makes it impossible to easily move data between regions - unless you use a centralized unique ID service (see Twitter's Snowflake for an example). UUIDs just avoids this issue entirely and you can move data around with ease.
With UUIDs, things like being able to grab some test data from production, scrub it, insert it into your local database, test with it, and then update it back to staging or production uses trivial normal insert/update operations.
With sequential IDs, this task becomes a nightmare of ID collisions and manually altering foreign keys if you do run into duplicate IDs.
If anything really does need to be exposed to end users, I typically use another unique string field like username, post slug, etc. rather than directly exposing the UUID to search engine traffic, while still using UUIDs internally everywhere within my database.
The author is explaining the drawbacks of UUID as a user experience problem.
UUIDs are built for machines.
The solution to providing an identifier for humans doesn't need to involve long—difficult to remember—numbers at all.
There are many better alternatives to UUID for the general case in which UUIDv4 is used, that provide some of the following advantages (based on the implementation): - Simpler spec and implementation - Easier to enforce compatibility across implementations (no ambiguity about letter case, order or hyphenation) - Smaller size and better readability - Lexicographically sortable based on time of generation - Deterministic uniqueness guarantee
UUID is too much of a jack-of-all-trades-master-of-none. It originally defined many versions (which should have been called "formats") for flexibility, but nowadays only UUIDv4 (and less often UUIDv1) seem to be in use. UUIDv3 and UUIDv5 rely on the insecure MD5 and SHA-1, which, while it seems UUIDv2 and Nil UUIDs were rarely ever used.
I hate it when developers are always reaching immediately for UUIDv4 while they almost always have a better choice for their case.
There is also no reason to give up 6 reserved bits of a uuid v4's 128 bits (it's only 122 random bits + 6 bits of unnecessary version info). If you want random IDs, make your own. Simply generate 16 bytes of raw data; or combine two random 64-bit integers; or combine a timestamp prefix with random bytes at the end. Your needs probably don't warrant exactly 128 (well, 122 bits) that uuid v4 gives anyway, so you can customize to a specific number of bits. You can also use base62 (0-9, A-Z, a-z) or base64 instead of hexadecimal (0-9, A-F) to reduce the number of displayed characters (eg. in URLs), while omitting the stupid hyphens of a uuid too.
tldr; uuid v4 shouldn't even exist, and certainly should not be used unless integrating with pre-existing systems.
Could you name a few with their trade off or point me to some resources? I only know about UUIDs and auto-incrementing sequentail ID, but I would love to add a few tools to my toolbox.
PostgreSQL (and other RDBMS) also supports storing and indexing the data in UUIDs in a binary format. With binary, the space and speed concerns are greatly minimized, especially when comparing UUIDs to other randomly generated homegrown strings.
No doubt this phenomenon successfully plucks at some emotional vulnerability most of us have, and thus brings in the clicks.
edit: I also disagree with most of the points this article makes, but that’s just, like, my opinion, man.
The only argument I can think of in favor of this proposed alternative is if at some point in your business workflow someone needs to manually type an ID and cannot copy paste it. Sounds pretty rare to me. Even support is now done more and more via chat systems.
Two cases:
- screenshots - a page that's on your phone that you want to see on your computer
Sure, those are not the most frequent, but I'm glad I don't have to type a UUID each time.
https://github.com/rs/xid
The thing I don't like about UUIDs is that they're not necessarily unique across multiple universes.
I sometimes have this odd cognitive dissonance about it and have to consciously remind myself that this intuition is ridiculous.
Is it just me?
UUIDs offer by far the best developer UX. They're first class objects for most of your tech stack, and they eliminate or massively simplify a lot of potential backend issues, from idempotency to merges to sharding.
The main downsides are two:
- They're not human friendly. This is a good thing. Surrogate keys should never be exposed to the human user, because what is a 1:1 mapping today may not be 1:1 any longer tomorrow. If you need to let the user input a unique object reference manually, you're free to design that reference with human UX in mind. Maybe it's a set of dictionary words, maybe it's a code with an expiration date, maybe it's the same code but referring to different versions of the object depending on the user.
The only people who may need to copy/paste UUIDs manually are database admins, and they will thank you so much more for never bothering them with fixing a pkey clash or an accidental join on the wrong key.
- They are less performant than sequential integers. For 99% of projects this is not going to be an actual issue. Once you _do_ find that your queries are being slowed down by the size of primary keys specifically, you have my absolute blessing to add an integer sequence column and make that the primary key.