Generating a unique identifier is sometimes a very trivial job. All you need is to get an index of integer type and increment it any time you need an identifier. The things get more complicated, if an identifier needs to be unique in a distributed environment.

In this post, I am sharing couple of approaches to generated unique identifiers in Node.js. The solutions can be used in a single process as well as distributed environment.

Using UUID as a identifier

A universal unique identifier (UUID) is a standard of generating identifiers, standardized by the Open Software Foundation (OSF).

The intent of UUIDs is to be able to generate unique identifiers in a distributed system without central coordination point. The word unique should not be taken to mean guaranteed unique; it is rather practically unique.

UUID canonical form is as follows:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

where N indicates the variant and M indicates the UUID version. You can find all the UUID details in RFC4112

Version 1 UUID is meant for generating time-based UUIDs. They also accept 48 bit long identifier (281,474,976,710,655 available values). In many cases it make sense to use a machine MAC Address as an identifier. Sometimes if we use several UUID generators on the same system, we can just use configured identifiers. It is very important to have unique identifier in a distributed environment. That will guarantee conflict-free ids.

Version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers. UUID v4 are not giving us guaranteed unique numbers; they are rather practically unique. Probability of getting a duplicate is as follows:

Only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%

There are several Node.js modules generating UUID numbers. The one which I use very often is node-uuid. Simple and fast implementation of UUID version 1 and 4.

The Node.js node-uuid module is very simple to use. You can install it using npm manager:

npm install node-uuid

And use it in your script e.g.:

var uuid = require('node-uuid');
var uuid1 = uuid.v1();
var uuid2 = uuid.v1({node:[0x01,0x23,0x45,0x67,0x89,0xab]});
var uuid3 = uuid.v1({node:[0, 0, 0, 0, 0, 0]})
var uuid4 = uuid.v4();
var uuid5 = uuid.v4();

And that would give something like:

// uuid1 -> ec654ec1-7f8f-11e3-ae96-b385f4bc450c
// uuid2 -> ec666030-7f8f-11e3-ae96-0123456789ab
// uuid3 -> ec66fc70-7f8f-11e3-ae96-000000000000
// uuid4 -> 32a4fbed-676d-47f9-a321-cb2f267e2918
// uuid5 -> 8b68cf5b-d619-4281-b560-1578b0ee891d

Generate identifiers using Snowflake approach

An alternative to UUID identifiers might be 64 bit long identifiers generated using Twitter Snowflake approach. I have created Node.js flake-idgen module which generates ids meeting following requirements:

  • Uncoordinated - services generating ids should not have any central coordination point. That is very important for high availability services.
  • Compact - generated ids are 64-bit long. There are other good solutions generating bigger ids e.g. 128-bit long UUIDs.
  • (Roughly) Time ordered - the ids will be k-ordered (roughly ordered) i.e. ids are no more than k positions from its totally ordered position.
  • Good performance - a service generating ids can product up to 4096 ids per millisecond.

The Node.js flake-idgen module is very simple to use. You can install it using npm manager:

npm install flake-idgen

And use it in your script e.g.:

var FlakeIdGen = require('flake-idgen')
    , intformat = require('biguint-format')
    , generator = new FlakeIdGen;

var id1 = generator.next();
var id2 = generator.next();
var id3 = intformat(id1, 'dec');
var id4 = intformat(id2, 'hex', {prefix:'0x'})

And that would give something like:

// id1 -> <Buffer 50 e8 46 15 20 c0 00 02>
// id2 -> <Buffer 50 e8 46 15 20 c0 00 03>
// id3 -> 5829986774188818434
// id4 -> 0x50e8461520c00003

Conclusion

There are several other solutions to generate unique identifiers. Some of them may be good for distributed environments, some others may work only on a single node.

In this post I wanted to share with you some simple solutions producing unique identifiers in distributed environments which could be implemented in Node.js in production systems.