PureDevTools

Snowflake ID Generator

Generate and decode Twitter-style 64-bit distributed IDs with configurable epoch and worker

All processing happens in your browser. No data is sent to any server.

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

ComponentBitsMax ValueNotes
Sign10Always 0 (positive)
Timestamp412,199,023,255,551~69 years from epoch
Datacenter ID531Up to 32 datacenters
Worker ID531Up to 32 workers/datacenter
Sequence124,0954,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:

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:

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:

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:

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.

Related Tools

More Code & Config Generators