Snowflake ID Generator
Generate and decode Twitter-style 64-bit distributed IDs with configurable epoch and worker
Configuration
Decode Snowflake ID
Paste a Snowflake ID to extract its timestamp, worker, datacenter, and sequence number. Uses the epoch selected above.
Snowflake ID Specs
| Component | Bits | Max Value | Notes |
|---|---|---|---|
| Sign | 1 | 0 | Always 0 (positive) |
| Timestamp | 41 | 2,199,023,255,551 | ~69 years from epoch |
| Datacenter ID | 5 | 31 | Up to 32 datacenters |
| Worker ID | 5 | 31 | Up to 32 workers/datacenter |
| Sequence | 12 | 4,095 | 4,096 IDs/ms per worker |
Theoretical maximum throughput: 32 × 32 × 4,096 = 4,194,304 IDs/ms across all workers and datacenters.
Twitter published the Snowflake ID generation algorithm in 2010 to solve a specific problem: how do you generate unique, sortable 64-bit integer IDs across thousands of distributed servers without a central coordinator? The solution — packing a millisecond timestamp, datacenter ID, worker ID, and per-millisecond sequence counter into a single 64-bit integer — became one of the most widely copied distributed systems patterns in software engineering.
What Is a Snowflake ID?
A Snowflake ID is a 64-bit integer that encodes:
- 1 bit: Sign bit, always 0 (positive)
- 41 bits: Timestamp in milliseconds relative to a custom epoch
- 5 bits: Datacenter ID (0–31)
- 5 bits: Worker/machine ID (0–31)
- 12 bits: Sequence counter per millisecond (0–4095)
A typical Snowflake ID looks like: 1541815603606036480
That number contains the full creation timestamp of the event — extract the top 41 bits, add back the epoch, and you have the Unix millisecond timestamp when the ID was generated.
Why 64-bit Integers?
Most databases natively support 64-bit integers (BIGINT) with extremely efficient indexing. Unlike UUIDs (128 bits) or ULIDs (128 bits as a 26-character string), Snowflake IDs fit in a native integer column and sort numerically in creation order with zero overhead.
The tradeoff: Snowflake IDs require coordination — each worker must have a unique worker ID, and the epoch must be agreed upon across all producers.
Bit Layout Explained
Bit 63 22 17 12 0
| | | | |
| sign (1) | ts (41) | dc (5) | wk (5) | seq (12)
Timestamp (41 bits): Stores milliseconds since the epoch. With 41 bits, this covers 2^41 = 2,199,023,255,551 milliseconds ≈ 69.7 years from the epoch. Twitter’s epoch is November 4, 2010 — meaning Twitter IDs are valid until approximately 2080.
Datacenter ID (5 bits): Identifies which datacenter generated the ID. Supports up to 32 datacenters.
Worker ID (5 bits): Identifies which machine or process within the datacenter generated the ID. Supports up to 32 workers per datacenter — 1,024 total across all datacenters.
Sequence (12 bits): A counter incremented for each ID generated within the same millisecond by the same worker. Resets to 0 at the start of each new millisecond. This allows up to 4,096 IDs per millisecond per worker.
Maximum Throughput
With 32 datacenters × 32 workers × 4,096 sequence numbers per millisecond:
- Per worker: 4,096 IDs/ms = 4.096 million IDs/second
- Total across all workers: 1,024 × 4,096 = 4,194,304 IDs/ms = 4.2 billion IDs/second
This throughput far exceeds any realistic distributed system requirement.
Custom Epochs
The Twitter Snowflake epoch is November 4, 2010 (1288834974657 ms). By choosing a recent epoch, you maximize the usable range of the 41-bit timestamp. If you use Unix epoch (0), the 69-year range started in 1970 and expires in 2039 — close enough to be a concern for new systems.
Best practice for new systems: set the epoch to the current year. This gives you the full 69-year range going forward.
Common epoch presets:
- Twitter:
1288834974657(2010-11-04) - Discord:
1420070400000(2015-01-01) - Unix:
0(1970-01-01)
Decoding a Snowflake ID
Because the bit layout is a public standard, any Snowflake ID can be decoded to reveal its components. This is useful for debugging, auditing, and understanding the provenance of a record:
// Decode Snowflake ID (Twitter epoch)
const TWITTER_EPOCH = 1288834974657n;
function decode(id) {
const bigId = BigInt(id);
const timestamp = (bigId >> 22n) + TWITTER_EPOCH;
const datacenterId = (bigId >> 17n) & 0x1fn;
const workerId = (bigId >> 12n) & 0x1fn;
const sequence = bigId & 0xfffn;
return {
timestamp: new Date(Number(timestamp)).toISOString(),
datacenterId: Number(datacenterId),
workerId: Number(workerId),
sequence: Number(sequence),
};
}
// Twitter example
decode("175928847299117063");
// {
// timestamp: "2013-07-15T00:00:00.000Z",
// datacenterId: 4,
// workerId: 7,
// sequence: 999
// }
Implementing Snowflake in Production
// Go implementation (simplified)
package snowflake
import (
"sync"
"time"
)
const (
epoch = int64(1288834974657) // Twitter epoch
workerBits = 5
dcBits = 5
seqBits = 12
maxWorker = -1 ^ (-1 << workerBits) // 31
maxDC = -1 ^ (-1 << dcBits) // 31
maxSeq = -1 ^ (-1 << seqBits) // 4095
workerShift = seqBits // 12
dcShift = seqBits + workerBits // 17
tsShift = seqBits + workerBits + dcBits // 22
)
type Node struct {
mu sync.Mutex
lastMs int64
workerID int64
dcID int64
sequence int64
}
func (n *Node) Generate() int64 {
n.mu.Lock()
defer n.mu.Unlock()
now := time.Now().UnixMilli() - epoch
if now == n.lastMs {
n.sequence = (n.sequence + 1) & maxSeq
if n.sequence == 0 {
for now <= n.lastMs {
now = time.Now().UnixMilli() - epoch
}
}
} else {
n.sequence = 0
}
n.lastMs = now
return now<<tsShift | n.dcID<<dcShift | n.workerID<<workerShift | n.sequence
}
# Python implementation
import time
import threading
class Snowflake:
EPOCH = 1288834974657 # Twitter epoch
def __init__(self, worker_id=1, datacenter_id=1):
self.worker_id = worker_id
self.datacenter_id = datacenter_id
self.sequence = 0
self.last_ms = -1
self._lock = threading.Lock()
def generate(self):
with self._lock:
ms = int(time.time() * 1000) - self.EPOCH
if ms == self.last_ms:
self.sequence = (self.sequence + 1) & 0xFFF
if self.sequence == 0:
while ms <= self.last_ms:
ms = int(time.time() * 1000) - self.EPOCH
else:
self.sequence = 0
self.last_ms = ms
return (ms << 22) | (self.datacenter_id << 17) | \
(self.worker_id << 12) | self.sequence
Who Uses Snowflake IDs?
The Snowflake algorithm (with variations) is used by:
- Twitter/X: Original inventor — all tweet IDs, user IDs, and direct message IDs
- Discord: Message IDs, server IDs, user IDs (with Discord’s 2015 epoch)
- Instagram: Shard ID instead of datacenter ID (published in 2012)
- Sony: Sonyflake — a variation using a 39-bit timestamp and 16-bit machine ID
- Baidu: UID Generator — adds higher-throughput modes
Limitations and Considerations
Clock synchronization: If a server’s clock jumps backward (NTP correction), the worker may generate duplicate IDs. Production implementations must detect clock drift and either wait for the clock to catch up or reject ID generation until it does.
Worker ID coordination: Worker IDs must be unique across all active generators sharing the same epoch. In container environments, this often requires a coordination service (ZooKeeper, etcd, Redis) to assign worker IDs at startup.
JavaScript BigInt: Snowflake IDs exceed JavaScript’s safe integer range (Number.MAX_SAFE_INTEGER = 2^53 - 1). Always use BigInt or string representation when handling Snowflake IDs in JavaScript/JSON.
Not random: Unlike UUID v4, Snowflake IDs are deterministic given the timestamp and worker/datacenter configuration. They should not be used as security tokens or in any context where unpredictability is required.
Privacy
All ID generation in this tool runs entirely in your browser. No IDs, configurations, or decoded data are sent to any server.