Base58 Unique IDs

Unique IDs

TL;DR version - Use UUIDs, but make them save space.

Generating Unique IDs

Do you key your whole system by database generated IDs that are autoincrementing integers. As you probably know that means that your APIs and endpoints are ready targets for somebody who wants to test lots of differt IDs against them. After all customer ID # 1000 demonstrates there is probably customer # 1001 and 1002. While you can look at systems like snowflake it’s much easier to build something based on UUID.

>>> import uuid
>>> uuid.uuid4()

That’s 128 bits of uniqueness that makes it possible to do lots of interesting things. Now you don’t need to generate a unique ID for everything, you still will have DB tables keyed by IDs, but if you ever think it’s going to be public, make the primary ID a UUID based token.

Making them compact

From DB keys, to anything down the road 128 bits encoded into hex bytes is always going to be 32 bytes (with the -s removed). Base16 isn’t really the most compact way to save things and storing raw 128 bits in the database sucks for many other reasons.

Compacting; you have a few quick and easy choices.

Encoding Length/Example
Raw 16 bytes
This doesn't transmit over the wire well, encode into JSON or really be useful outside of an internal representation.
Base 16 32 characters
That's 32 characters, good but not very compact.
Base 64 24 / 22 characters
Good representation, but you have URL issues with the default encoding which includes '/' and '+' (usually translated to '-' and '_' to make it safe)
Base 32 32 / 26 characters
We've avoided the URL problems. but it's gotten longer.
Base 58 22 characters
As compact as Base64, avoiding the URL issues and in a unambigious alphabet and error checks.

What would I choose to generate unique, customer visible IDs… That’s pretty easy. Base58 encoding UUIDs, using the Bitcoin alphabet (this is going to be the default for most Base58 encoders).

Your quick python example, that’s it Unique Keys in “one” line of code.

def idGen():
   return b58encode((uuid.uuid4()).bytes)
Share Comments
comments powered by Disqus