It's best to stick to UUIDv7 because of such quirks of ULID.
It's best to stick to UUIDv7 because of such quirks of ULID.
Can you expand on how this can actually cause a problem? My understanding is different processes and hosts should never conflict because of the 80 bits of random data. The only way I can conceive of a conflict is multiple threads using the same non-thread-safe generator during the same millisecond.
I've switched to using UUIDv7 tho. It made sense to use ULID before v7, but now ULID only has one thing going on - smaller string representation. That doesn't matter if your storage can store UUIDs natively (i.e. as 128 bit integer)
If your goal is to have global order intact, then neither ULID nor UUIDv7 is going to work for you.
I've implemented this thing, though not called it ULID. I've dedicated some bits for timestamp, some bits for counter within millisecond and rest for randomness. So they always ordered and always unpredictable.
Another approach is to keep latest generated UUID and if new UUID requested within the same timestamp - generate random part until it's greater than previous one. I think that's pretty good approach as well.
It's literally incrementing it by one:
https://github.com/ulid/javascript/blob/11c2067821ee19e4dc78...
https://github.com/ulid/javascript/blob/11c2067821ee19e4dc78...
It is and it does.
Also the ULID spec suggests you use a CSPRNG, but doesn't mandate that or provide specific advice on appropriate algorithms. So in practice people may reach for whatever hash function is convenient in their project, which may just be FNV or similar with considerably weaker randomness too.
But that's easy to fix, so just implementation quirk for this particular library, the idea is sound.