Ever wonder what are the differences between UUID versions? If so, this short article for you.

Are newer UUID versions always better?

No. As we are going to see bellow, when it comes to UUID's, different versions have different use cases. Even though you should generally favor using v4 and v5, that doesn't mean v5 is better than v4.

UUID version 1

The UUID v1 uses a computer identifier (typically your MAC address) and the timestamp to generate the unique identifiers.

This means that if you know the MAC address and timestamp you could generate again the same UUID.

UUID v1 is easier to guess than some of the other versions. If this is important for your application, see the alternatives bellow.

Example code:

const uuidv1 = require('uuid/v1')
let uuid, newUuid

// different time, different UUID
uuid = uuidv1()
newUuid = uuidv1()
console.log(uuid === newUuid) // false

// same time, same UUID
uuid = uuidv1({ clockseq: 1, msecs: 1, nsecs: 1 })
newUuid = uuidv1({ clockseq: 1, msecs: 1, nsecs: 1 })
console.log(uuid === newUuid) // true

UUID version 2

UUID v2 are often left out of many implementations due to not being specified in the RFC4122.

This version uses the MAC address and timestamp (much like version 1), but also allows you to include a domain and identifier in the UUID.

You should not use this version, as collision chance per domain/identifier is high. See here for more.

UUID version 3

UUID v3 generates values by hashing (MD5) a name (eg. domain or URL) and a namespace identifier. This namespace identifier must be a valid UUID.

For example:

const uuidv3 = require('uuid/v3')

// same domain, same output
uuidv3('hello.example.com', uuidv3.DNS) // 9125a8dc-52ee-365b-a5aa-81b0b3681cf6
uuidv3('hello.example.com', uuidv3.DNS) // 9125a8dc-52ee-365b-a5aa-81b0b3681cf6

// different domain, different output
uuidv3('example.com', uuidv3.DNS) // 9073926b-929f-31c2-abc9-fad77ae3e8eb

In the example above, uuidv3.DNS maps to a UUID value specified in the RFC 4122, but you can also provide any other valid UUID as well:

const uuidv3 = require('uuid/v3')

const customNamespace = 'c6235813-3ba4-3801-ae84-e0a6ebb7d138'
uuidv3('http://example.com/hello', customNamespace)  // 2c48dc1f-974a-3253-b4ba-191c5417afb3

The use case for UUID v3 is to generate unique identifiers from a name and  namespace input in a deterministic way: given same input, always generate the same output. The generated output UUID, does not allow for easy reverse engineering the input values. When compared with UUID v1, brute forcing UUID v3 is much more difficult.

UUID version 4

UUID v4 differs from other versions in that it is not based on any easily reproducible data (MAC/timestamp for v1, name/namespace for v3 and v5). Instead, v4 generates unique identifiers based on random numbers (pseudo-random).

This results in unique identifiers that cannot be replayed and have  extremely low change of being guessed.

Given such small chance of collision, v4's main use case is when you need to ensure that the generated identifier is truly unique across your entire application (and likely around the globe)

Example:

const uuidv4 = require('uuid/v4')

uuidv4() // aa2bd832-191e-4d2b-98d4-b0d4778844f9
uuidv4() // 0e382d43-b07d-4c62-81d8-605c0c853c62
uuidv4() // fad74d27-32c4-4fbb-8844-ee123f75622a

UUID version 5

UUID v5 works the same as v3, only difference being that it uses SHA-1 as the hashing algorithm, while and UUID v3 uses MD5. You would generally use v5 for the same reasons you would chose v3, opting for v3 only when integrating with older systems that use MD5 for hasing names.

Conclusion

This article was a brief look at the different UUID versions.

You should generally be using version 4 if just want your identifiers to be random and unique.

Use version 5 if you want a unique identifier that can be recreated again (by your own system or another integrating system)  based on the inputs name and namespace.