In Postgresql, generally an incrementing primary key is used, which SERIAL
is an excellent helper type for.
Sometimes though, an incrementing ID exposed in an API or URLs reveals too much about the service, like the number of users you have (see the German Tank Problem).
You could use UUIDs for this, but they're long and obnoxious if you're exposing them to a user via URLs.
Instead, we want a short string, say 8 characters in length, that is a cryptographically-secure, random value. We need a cryptographically-secure generator because otherwise someone could guess the generator algorithm, seed the previous value, and we'd again be vulnerable to the German Tank Problem.
Postgresql comes with an extension called pgcrypto that has a generate_random_bytes
function.
We'll use this to generate 6 bytes, giving us 2^48 possible keys, and then encode them in URL-safe Base64.
The Birthday Problem probability table says that we can expect a 1% chance of having had a collision once we've generated 240,000 IDs, 25% after 1,300,000 IDs, and 50% at 20,000,000 IDs.
So even after 20,000,000 IDs generated, we may only have had 1 collision.
We'll use a LOOP
just in case we hit a collision.