Prefer UUID for your Primary Key

August 2, 2021
3 minutes to read
Share this post:

In my last post I discussed the downsides of using numerical types for the primary key of an entity. We should avoid these issues all together by using UUID instead and in this post I will discuss the up- and downsides of this approach.

Using a UUID as the primary ID is simple:

class Flat(
    val id: UUID = UUID.randomUUID()

Generate the ID on the application

Similar to numerical ids we can generate it on the database as well. But for UUID this is not necessary. The reason we did this in the first place is that we needed to make sure that an ID is not used twice. A collision of UUID is very unlikely to occur.

And what do we do when such error happens? We don’t need to establish any special handling of it. We throw an exception, cancel the transaction and let the client redo the operation. Like we would always do when something happens that we can’t handle.

But we get extraordinary benefits from UUID:

Offline Capability

We don’t need to generate the UUID on the database. We don’t even need to generate it on the backend. We can create it in the client. And this enables the client to create new entities without synchronizing them to the backend. This enables us to make the client very resilient to network issues. E.g. I implemented such behavior in a game I developed and that enabled us to support playing the game even in unstable environments like when you play on the train and drive through tunnels. It is an awesome experience for the users and does not require a lot of work on the application to achieve.

Easier (Unit) Testing

When you generate the UUID on the client or server you have much more control over it. And this is beneficial when you want to write unit tests for your entities. You can simply use the constructor. Generating it on the database relied on reflection and in the runtime between the setting of the id and the creation of the object it is in an unstable state. Have a look at the “Collection Problem” in my previous post .

Tedious Debugging

UUIDs are unhandy. Remembering that E209C805-C7D5-4C7A-8F02-37BEA845A405 is the ID of the entity you look at is of course harder than remembering 2837. This is a downside and everyone needs to decide whether that is a strong argument.

More Space

Of course UUID are larger than Int. You can do a whole evaluation of this aspect. You can even fill pages and whole blogs about it. But I don’t do that. In relation to all the other kind of data that we store nowadays it is a waste of time and energy. Space - in this scale - does not matter for 99% of the applications out there. If you work in an environment where it matters, sure, do the evaluation and make a proper decision. But for most of the developers our there it shouldn’t matter at all.

Have you heard of Marcus' Backend Newsletter?

New ideas. Every week!