One integer, split four ways
One published design in 2010 became the shared vocabulary for this problem, invented to mint identifiers after a company outgrew its single database sequence.
Split one 64-bit integer four ways. A sign bit left at zero, so identifiers stay positive in every language and database. Then 41 bits of milliseconds since an epoch you choose. Then 10 bits naming the machine. Then 12 bits of sequence within that millisecond.
Walk the budget each field buys you. Forty-one bits of milliseconds is about 69 years from your chosen epoch. That is why generators define their own, instead of starting from 1970. You spend the range on the system's actual lifetime.
Ten bits of machine identifier allows 1,024 generators running at once. Twelve bits of sequence allows 4,096 per machine per millisecond, four million a second, and a machine that exhausts its sequence simply waits for the next tick.
Total that up: four billion identifiers a second across the fleet, minted with no network calls at all, from one clock read and two local increments.
Get sortability free from the layout, because the timestamp sits in the high bits. Numeric order is creation order to the millisecond, and identifiers from the same millisecond order arbitrarily, which nobody cares about.
Collect the downstream benefits. Your indexes get roughly sequential inserts. Your pagination becomes a comparison against a cursor. And any service decodes an identifier's timestamp with a shift, needing no lookup, a trick some public APIs formally document.
The one coordination point
Guard the one coordination point left, assigning machine identifiers, and make it airtight. Two generators sharing one identifier silently mint colliding values.
Choose from three production options. Derive it from something already unique in your orchestration. Lease it from a coordination store at startup, with the generator refusing to run without a lease. Or assign it from configuration with an audit.
Notice the design's entire trick: coordinate once at boot, and never per identifier.
Worked example
Discord's public API makes Snowflake anatomy something you can poke with a calculator. Every Discord object ID is a Snowflake with epoch 2015-01-01: take any message ID, shift right 22 bits, add 1420070400000, and you get the message's creation time in Unix milliseconds, which is exactly how third-party Discord tools timestamp objects without any API call. Priya, building a moderation bot, uses the layout directly: to fetch messages from a specific hour, she constructs synthetic Snowflakes for the hour's boundaries (timestamp bits set, machine and sequence bits zero) and passes them as before and after cursors. No search endpoint needed; the ID space is the time index. Her one bug comes from JavaScript, whose numbers lose integer precision past 2^53, silently corrupting the low bits until she switches to BigInt, the standard rite of passage for anyone handling 64-bit Snowflakes in a browser.