Replies: 4 comments 2 replies
-
So Matt King found a few existing approaches to this same problem: The
The Sami Fayoumi approach is similar, trading a larger sequence for fewer workers:
Both approaches seem pretty good, the former allowing for more parallelization (which might be better suited to Laravel Vapor) while the latter allows for more individual throughput (you could generate 32 unique IDs inside a process before having to I definitely think that jumping from milliseconds to seconds is maybe too much, but I wonder if we could trim a few bits from the timestamp if we used |
Beta Was this translation helpful? Give feedback.
-
FWIW I've been using this https://github.com/kra8/laravel-snowflake for generating snowflake primary keys in apps. It supports a shorter 53bit snowflake version. I'm not sure what 11 bits it's cutting though, actually I think they are droping the unused but plus the data center and worker bits do maybe that's a bad example because you lose parallelization support. Personally I think for most uses it makes sense to prioritize a longer timestamp and longer sequence over parallelization. At least for me personally I figure it'll be 2038 long before I need hundreds of servers. Although I wonder if the answer isn't to just use a ULID instead of a snowflake. |
Beta Was this translation helpful? Give feedback.
-
I've had a similar problem before with CockroachDB and Livewire. CockroachDB uses random IDs instead of autoincrementing so they become large numbers that Javascript doesn't like. Surely the best thing is to make the IDs cast to a string via the model casts and in the event you need to use them for some kind of functionality you just grab the ID and convert it to an int? |
Beta Was this translation helpful? Give feedback.
-
Not sure if this is relevant but it looks like Laravel just pushed support for unique string primary keys. PR here: |
Beta Was this translation helpful? Give feedback.
-
I posted this in the Verbs discord, but I'm going to re-post here for more visibility…
An issue with using Snowflakes everywhere is that javascript doesn't handle 64-bit integers very well (only the first 53 bits are accurately stored). That means that if you try to use a snowflake as an integer in JS, things may break. The solution is to treat snowflakes as strings, which is how the default
jsonSerialize
behavior ofglhd/bits
works, but that doesn't help people who are echoing the IDs directly to their page…I have a potential solution… but it's pretty technical.
Snowflakes are made up of 6 parts:
The 12 bits of sequence lets you generate 4096 snowflakes per millisecond, per worker, per datacenter. That's a lot of parallel capacity. Arguably more than anyone other Twitter (the creator of the snowflake format) would need…
We could, theoretically, get a 53-bit version with some trade-offs. Traditional 32-bit signed unix timestamps have about +68 years of capacity (that's why we're hitting the year 2038 problem — 1970 + 68). But we don't need a sign bit, since snowflake IDs only move forward.
That means that if we accept second-accuracy, rather than millisecond-accuracy, we can fit about 136 years into 32 bits. So if we do the following:
That would let you generate 4096 unique snowflakes per second, per worker, per datacenter, and produce a 53-bit value that could be represented in JS.
We'd need to pick a set of defaults that would cover most decent-scale apps (I'm not sure that 32/4/5/12 is right… but it's a decent example).
Any thoughts?
Beta Was this translation helpful? Give feedback.
All reactions