Company Standard UUID

Many years ago, I had the experience of dealing with UUIDs in an application. The plural here is deceiving, “UUIDs” meaning (at least) three different UUID formats in the same application. While it was too long ago to recall the precise details, the formats involved were defined by a Ruby gem, Postgres, and Cassandra.

Not surprisingly, the Wikipedia article on UUID is pretty good.

Ruby’s SecureRandom implementation of UUID is based on V4 of RFC 4122.

UUID versus sequential IDs

From Reddit, verify all of this, reword what’s applicable into language for the this article, delete the remaining. Reddit comment

UUIDs offer the following advantages:

  1. There is native support in many languages and frameworks.
  2. They can be strongly typed, reducing the risk of illegal or nonsensical operations (for example, concatenating characters).
  3. Not subject to sequential rollover (which has happened to this author).
  4. Eliminates enumeration exposure, there is no sequential ID.
  5. Independent of datastore, important when data is distributed. Sequential primary keys are bound to their database.
  6. Can be generated and used by clients, reducing database calls.

Disadvantages include:

  1. More difficult to reference entities by number; debugging may become more difficult, ugly URLs.
  2. There are many different UUID schemes, not of all which work well together, and risks platform-dependence.
  3. Some engineers simply do not like UUID primary keys, and may actively oppose their introduction and use.

Given the variety of UUID schemes, obvious questions include: which scheme is best, and how to implement consistently?

Choosing the best scheme is dependent on the specific uses cases and beyond the scope of this article.

Consistency of implementation can be addressed by:

  1. Ensuring the UUID scheme which is chosen is effectively communicated to all engineers, some of which may not understand there is more than one way to define UUIDs and the definition in their favorite support library may not be what’s chosen.

  2. Implement wrappers for consistent implementation on all platforms, and have all platforms use the wrapper. For a Rails monolith, this is easy. Instead of reaching for a Uuid, reach for an AUuid.

module Acme
  class Uuid
    def new
      # your UUID generator here
    end
  end
end
alias AUuid Acme::Uuid

For a (micro)services implementation, use a company-specific library such as Ruby gem, or npm package, etc.