UUID/GUID, CUID & NanoID: What's The Difference?
Tags: database, productivity, beginners, sql
Published: 2022-04-04 03:00:04

So recently, I was on a live steam with @aydrian on [Twitch](https://www.twitch.tv/videos/1440503147) where I demonstrated how to migrate a live serverless application ([Next.js](https://nextjs.org) and [Vercel](https://vercel.com)) from a [PostgreSQL](https://postgresql.org) database onto [CockroachDB serverless](https://cockroachlabs.com/lp/serverless) with zero application downtime. If you're interested in that, please do check out the video.

{% twitter https://twitter.com/CockroachDB/status/1509308541395509249 %}

In the stream, we talked a lot about different topics I had going on in the code, and one of them was about the difference between a CUID and a UUID. Now, at the time of the stream I was unsure of the difference between the two, and I just kind of used whatever. 

After the stream, I too was curious what the difference is between the two. After doing some research, I'd like to share my findings.

We'll be looking at UUID and CUID, along with [NanoID] as it has started to gain traction lately. 

# What is UUID?

UUID, or universally unique identifier, is a 128 bit label used for information in operating systems. The probability that an ID will be replicated isn't zero, it's close enough that when we generate a UUID, the chances of the identifier being used ANYWHERE else is near zero.  

An example would be something like that fits the format of xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, so something like 123e4567-e89b-12d3-a456-426614174000.

### The problem with the UUID

While researching, I came across this blog by [PlanetScale](https://planetscale.com/), which is a MySQL-compatible serverless data platform. 

The title of the post was ["Why we chose NanoIDs for PlanetScale's API"](https://planetscale.com/blog/why-we-chose-nanoids-for-planetscales-api), and the post goes onto talk about how UUIDs are great and all as it's near impossible to generate a duplicate identifier, however they have a huge problem: they're too big, and take up too much space in the URL. 


Don't we all love clean and short URLs? Nobody likes seeing a bunch of digits and weird symbols in your URL. Quoted from their blog,

> They take up a lot of space in a URL: `api.planetscale.com/v1/deploy-requests/7cb776c5-8c12-4b1a-84aa-9941b815d873`

> Try double clicking on that ID to select and copy it. You can't. The browser interprets it as 5 different words.

> It may seem minor, but to build a product that developers love to use, we need to care about details like these.

Which is true! If we look into the history of UUID, we realise that it wasn't ever really made to be used in web applications. If we have a website such as, say, [HasteBin](https://www.toptal.com/developers/hastebin/), which depends upon generating these short, three letter IDs to easily share with people, this causes a problem.

# CUID

CUID aims to solve the exact problem we discussed above with UUIDs. Quoted from [CUID's GitHub](https://github.com/ericelliott/cuid):

> Modern web applications have different requirements than applications from just a few years ago. Our modern unique identifiers have a stricter list of requirements that cannot all be satisfied by any existing version of the GUID/UUID specifications

CUID aims to focus on horizontal scalability (as today's applications don't run on a single machine), performance, size, security, and portability. [The GitHub repository](https://github.com/ericelliott/cuid#motivation) offers a more specific breakdown of the problems that this aims to solve.

They're shorter, but what about collisions? I found this [online benchmark](https://gist.github.com/evalphobia/1f40afcfc73ce207d890dd4b1705a0c9) ran on a GitHub gist, showing that the chances for collisions are still extremely slim. It found no collisions on 100 million iterations!

Since the talk I gave about was related to [Prisma ORM](https://prisma.io/), the [Prisma schema](https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference) (in relational databases) can generate both either a CUID or UUID, depending on the needs of your application. 

# ...what about NanoID?

As a bonus, we'll being going over [NanoID]. It's said to be a tiny (only 130 bytes minified and gzipped), fast (x2 faster than UUID), safe, short, and portable.

[NanoID's website](https://zelark.github.io/nano-id-cc/) has a cool visualiser tool in it, where we can calculate the chances of a collision. With an ID length of 15 characters (pretty short and sweet), and a generation of 1,000 IDs every hour, it'll take a mind boggling 569 thousand years for it to have a _1%_ probability of a _single_ collision. Now if we switch that to 1000 IDs being generated _every single second_, it'd still take around 158  for it to have a 1% probability of at least a single collision. That's longer than me or you will probably live.

To visualise that, let's see:
 - Human lifespan: 79 years.
 - Life on Earth will be impossible in ~1.1 billion years.
 - Age of the Earth: ~4.543 billion years.
 - Age of the Universe: ~13.799 billion years.

[NanoID] also lets you customise the alphabet it uses, so you can remove and/or add in custom alphabets. 

Anyways, I think you get the point. Just because something's short doesn't mean it's insecure - but let's move onto another metric: performance. 

On the NanoID's README, there's a section for [benchmarks](https://github.com/ai/nanoid#benchmark) which they've run with other popular generators. As we can see here, compared to [uuidv4](https://www.npmjs.com/package/uuidv4), there's a huge upscale in performance.

# Conclusion

With that being said, I think I've given a fair comparison of the different methods of ID generation, their pros, and their cons. For most cases, I believe the best option is [NanoID] due to the fact that it's insanely customisable whilst being performant. It's slowly but surely taking over [uuidv4](https://www.npmjs.com/package/uuidv4), if we look at this [npm trends](https://www.npmtrends.com/cuid-vs-nanoid-vs-uuid) comparison between the three. In the context of [Prisma](https://prisma.io), the built-in CUID is perhaps the best choice.

[NanoID]: https://github.com/ai/nanoid