Snowflake IDs: The Timestamps Hidden in Discord and Twitter IDs
A Discord message ID, a Twitter/X post ID, and millions of internal database keys are not random: they are 64-bit integers with a millisecond timestamp packed into the high bits. Decode the bits and you can date-stamp almost anything without a database lookup.
Why IDs carry timestamps at all
In 2010 Twitter needed an ID scheme that worked across many machines without a central counter — but also sorted roughly by creation time, so new items naturally appear after old ones. The answer was Snowflake: instead of a random number, generate a 64-bit ID whose most significant bits are the current time in milliseconds. Two IDs generated a minute apart compare correctly with no coordination, and any service can mint unique IDs locally. The design was so successful that Discord adopted the same idea with its own epoch, and countless internal systems followed.
Anatomy of a 64-bit snowflake
A snowflake-style ID is one unsigned 64-bit integer. The layout, read from the most significant bit:
- 41 bits — timestamp. Milliseconds since a custom epoch, left-shifted into the top of the number.
- 10 bits — machine / worker identity. Which node generated the ID (Discord splits this into 5 bits of worker ID and 5 bits of process ID; Twitter used a single 10-bit machine ID).
- 12 bits — sequence. A per-millisecond counter, so up to 4,096 IDs per machine per millisecond are unique with no clock change at all.
Discord and Twitter both use the 41/10/12 split, which is why the same decode formula works for both — only the epoch differs.
The two epochs
-
Discord counts from January 1, 2015,
00:00:00 UTC, which is Unix millisecond
1420070400000. -
Twitter/X counts from November 4, 2010,
Unix millisecond
1288834974657(note: that epoch is not an exact midnight — it is 01:42:54.657 UTC that day, and some references therefore quote the rounded1288834974000).
The generic decode is: shift the ID right by 22 bits to drop the worker and sequence fields, then add the epoch to get Unix milliseconds:
discord_date_ms = (id >> 22) + 1420070400000twitter_date_ms = (id >> 22) + 1288834974657
Building an ID from a date reverses the math: subtract the epoch, shift left by 22, and OR in the worker and sequence bits.
A worked example
Take a Discord ID and read it as a date:
-
Take the value
175928847299117063. Shifting it right by 22 drops the worker and sequence bits and leaves41947057796milliseconds since the Discord epoch. -
Adding the Discord epoch
1420070400000gives1462015105796Unix milliseconds. - That decodes to April 30, 2016, 11:18:25.796 UTC.
(The arithmetic checks out: a 2016-era ID sits near 1.76 × 1017,
which is exactly where 175… falls.)
Rather than doing the shift by hand, paste the ID into the snowflake ID converter — it separates the timestamp, worker, process, and sequence fields, supports any custom epoch, and can also build an ID from a date.
Why this matters in practice
- Dating content without a database. A message ID alone tells you when it was created — useful when auditing exports or debugging sync issues where timestamps were not stored.
- Time-ordered keys. Because the timestamp occupies the high bits, snowflake IDs sort chronologically. Databases that store them as integers get roughly insertion-ordered scans for free.
-
The precision trap. Snowflake IDs are up to 19 digits
and exceed JavaScript's safe-integer limit (
2^53 − 1, about 9,007,199,254,740,991). Libraries that parse them as plain numbers silently round the low bits. Treat them as strings orBigIntvalues. - The rollover horizon. With 41 bits of milliseconds, both schemes have room for about 69 years from their epochs — Discord's epoch therefore lasts until the year 2084.
The same trick, other families
Snowflakes are not the only IDs that smuggle a timestamp into the bits. UUID v1 packs a 100-nanosecond timestamp since October 15, 1582 into its 128 bits; UUID v7 and ULID both lead with a 48-bit Unix millisecond timestamp, giving them the same sortable-by-creation property as a snowflake with a much simpler layout. Whatever the family, the decode is the same idea: find the epoch, find the bit width, shift, and add.
First published · Last reviewed · Maintained and developed by the Real Epoch Converter team · [email protected] · Contact · Methodology
Sources & references
More guides
- What Is Unix Time? The Epoch Explained for Developers
- How to Read Unix Timestamps in Logs, Fast
- Seconds, Milliseconds, or Microseconds? Detecting a Timestamp’s Unit
- ISO 8601 vs Unix Time: When to Use Which
- Leap Seconds and GPS Time: Why Two Clocks Disagree
- Windows Time Formats: FILETIME, .NET Ticks, and the 1601 Epoch
- 7 Timestamp Bugs That Bite Every Developer
Every article is written by the Real Epoch Converter team and cross-checked against the specifications listed in its sources. To try what you just read, open the epoch time converter — the free online tool on the home page — or browse the FAQ.