Live data from Hacker News

ULID: Universally Unique Lexicographically Sortable Identifier

packagemain.tech

51–58 of 58 posts

Re: ULID: Universally Unique Lexicographically Sortable Identifier

#51
post #10

Whenever ULID comes up, I need to remind that it has a sequential ID generation mode in its spec which is prone to conflicts on multi-threads, processes or hosts which kills the purpose of a "universal" identifier. If you need a sequential ID, just use an integer, preferably one that's autoincremented by the database. It's best to stick to UUIDv7 because of such quirks of ULID.

Actually dived into this a bit just a couple days ago. It's very near impossibly for there to be a conflict since the timestamp resolves at the microsecond level, and if it's among threads, then there's a global state that, if somehow it should be hit 2+ times in the same microsecond, ensures detection and the random portion is incremented.

Re: ULID: Universally Unique Lexicographically Sortable Identifier

#53
post #36

Earlier quoted context omitted.

I hope that's not literally incrementing a sequence. Because it would lead to trivial neighbor ID guessing attacks. 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 t…

> I hope that's not literally incrementing a sequence It's literally incrementing it by one: https://github.com/ulid/javascript/blob/11c2067821ee19e4dc78... https://github.com/ulid/javascript/blob/11c2067821ee19e4dc78...

Well, that makes little sense for me, you can just use numeric identifier instead. Bulk inserts which generate identifiers in bulk are commonly used.

But that's easy to fix, so just implementation quirk for this particular library, the idea is sound.

Re: ULID: Universally Unique Lexicographically Sortable Identifier

#54
post #42
post #32

Earlier quoted context omitted.

That depends on if the specific implementation of the generator instance is thread safe. Highly implausible to use the same generator instance between different threads/processes/hosts because there's no benefit at all and only additional downsides.

To implement a thread-safe sequential increment, you need locking. When you use locking, then it becomes a “non-universal” ID generator with arbitrary performance impact. Either it’s collision-prone or locking. Both are problematic in their own way. It’s footguns all over while UUIDv7 simply exists.

There is practically no need to have a thread-safe ULID generator that would be shared across threads/processes/hosts - a non-scenario that I cannot envision occurring in practice.

Re: ULID: Universally Unique Lexicographically Sortable Identifier

#55
post #36

Earlier quoted context omitted.

> I hope that's not literally incrementing a sequence It's literally incrementing it by one: https://github.com/ulid/javascript/blob/11c2067821ee19e4dc78... https://github.com/ulid/javascript/blob/11c2067821ee19e4dc78...

Well, that makes little sense for me, you can just use numeric identifier instead. Bulk inserts which generate identifiers in bulk are commonly used. But that's easy to fix, so just implementation quirk for this particular library, the idea is sound.

> But that's easy to fix, so just implementation quirk for this particular library, the idea is sound.

It's in ULID spec.

Re: ULID: Universally Unique Lexicographically Sortable Identifier

#56

I have always been a bit hesitant to use UUIDs with timestamps as it can be a security issue if the IDs are public. For example getting the age of a user account just from the id. I will say, however, that I have not heard of any major incidents stemming from this.

I don’t think it’s generally a good idea to store important domain information in synthetic keys. UUIDs should always be treated as opaque keys, but they may have structure that will help them fulfilling their primary function. Timestamp in UUID v7 may be close to moment of record creation, but it shouldn’t be the contract in your system that it is the creation timestamp.

Re: ULID: Universally Unique Lexicographically Sortable Identifier

#58
post #28
post #20

Earlier quoted context omitted.

You only need to lock sequence if you care about IDs being ordered within a millisecond. That generally only matters when you create a batch of IDs at once, in that case you don't need to lock anything: generate ULID, keep incrementing sequence in that batch either by doing on the same thread, or by moving it from thread to thread. Kinda like creating an iterator and zip'ing it with iterator of thing you need IDs for…

> You only need to lock sequence if you care about IDs being ordered within a millisecond Yes, and that's when sequences are only used. I guess that's to avoid hogging the CPU or emptying the OS entropy pool during high loads. However, that "optimization" is a failure mode if you're not aware how ULID internals work. It's easy to shoot yourself in the foot by blindly trusting ULID will always generate a unique ID acr…

> No, any web service instance can receive requests at arbitrary times, and sometimes in the same millisecond zone. The probability is proportional to the number of concurrent users and requests.

Yes, but does it matter that you have out of order IDs within the same ms for concurrent requests? That's why I said batch. I only ever been an issue for me when I've chosen ULID as an ID for an event log (if the command produced more than one event, random bits will ruin the order)

> However, that "optimization" is a failure mode if you're not aware how ULID internals work.

That's not ULID internals, that's whatever library you're using. The rust implementation I've used, for example, will generate random bits unless you implicitly increment, and that requires `&mut`

Post reply on HN