Oh thanks for sharing, never found that somehow. It seems that's mostly formalising the general idea of adding a prefix to a UUID, but you still end up storing them as variable length strings.
I left 4 bits out in UPID as a version specifier, so could theoretically add a version with longer prefixes or more/less timestamp precision if that seemed useful to anyone.
I’m a little late to the conversation, but I’m using the Elixir version of TypeID[0] in my project. While the repo linked to above doesn’t provide any guidance on storing the TypeIDs, the Elixir version does this really well. You store the prefix in the your schema (model) code, but the underlying database column is simply a UUIDv7.
So when you call the new function, it will generate a UUIDv7, base32 encode it, and then prepend the prefix. Then at the database layer it will translate that to a UUIDv7 for storing and translate back to the string version when loading.
Oh yeah that looks ideal. My initial idea was down those lines, but realised this wouldn't be possible with many (most?) languages/ORMs/adapters. Eg for Prisma (TypeScript ORM) it would need to be built in to Prisma itself.
Another small benefit of UPID is that it works even for raw SQL sessions, but this obviously requires that it's installed into Postgres, which unfortunately for most is much harder than installing an Elixir/whatever lib.
But even if you just store them as u128/UUID, a nice thing is the IDs always know what their prefix is, so eg if you dump data into a warehouse, the IDs don't lose their context and an analytics person can still find what they're looking for.
The main differences:
- typeid allows up to a 63 byte prefix
- typeid follows it with a full 128-bit UUID
I prefer your implementation generally I think - I like the fixed size - just wanted to link something similar.