Skip to main content

Flexible 64-bit Snowflake-style unique ID generation for Python

Project description

flakeid

Flexible 64-bit Snowflake-style unique ID generation for Python.

Zero dependencies. Thread-safe. Works for a solo project or a large distributed system.

pip install flakeid

How it works

Each ID is a 64-bit integer whose bits encode when and where it was generated:

 63        22 21    17 16    12 11          0
┌──┬────────────┬───────┬───────┬────────────┐
│ 0│ timestamp  │  DC   │  node │  sequence  │
│1b│  41 bits   │ 5 bits│ 5 bits│  12 bits   │
└──┴────────────┴───────┴───────┴────────────┘
  • Sign bit — always 0, keeping IDs positive in every database and language.
  • Timestamp — milliseconds since a custom epoch (default: 2020-01-01 UTC).
  • Datacenter / Machine IDs — identify the node that generated the ID.
  • Sequence — a counter that resets each millisecond, preventing collisions on the same node.

All four field widths are configurable — any field can be resized or removed entirely, as long as the four values sum to 63.


Installation

pip install flakeid

Requires Python ≥ 3.9. No external dependencies.


Quickstart

Zero-config (smallest possible integration)

import flakeid

uid = flakeid.next_id()        # → 123456789012345678  (one ID)
ids = flakeid.next_ids(100)    # → [...]               (bulk)

The default generator uses a minimal layout (no node identity) and is lazily initialised on first call.


Custom generator — Twitter layout

from flakeid import make_generator, PRESET_TWITTER

gen = make_generator(PRESET_TWITTER, datacenter_id=1, machine_id=7)
uid = gen.next_id()

# Inspect what's inside
print(gen.decode(uid))
# DecodedID(raw=..., generated_at='2025-03-15T10:22:01.123Z',
#           datacenter_id=1, machine_id=7, sequence=0)

# Check the theoretical limits of this config
print(gen.capacity())
# Capacity(years=69.7, nodes=1024, ids_per_sec=4,096,000)

Built-in presets

Preset Layout Use case
PRESET_TWITTER 41 ts · 5 DC · 5 node · 12 seq Classic Twitter / Discord layout
PRESET_MINIMAL 53 ts · 10 seq Solo projects, scripts, single box
PRESET_SINGLE_DC 41 ts · 10 node · 12 seq One DC, many workers
PRESET_LARGE_CLUSTER 41 ts · 8 DC · 8 node · 6 seq 256 DCs × 256 machines
PRESET_HIGH_THROUGHPUT 41 ts · 3 DC · 3 node · 16 seq Max IDs/ms, few nodes
from flakeid import make_generator, PRESET_MINIMAL, PRESET_LARGE_CLUSTER

# By dict
gen = make_generator(PRESET_MINIMAL)

# By name string
gen = make_generator("large_cluster", datacenter_id=200, machine_id=100)

Fully custom layout

Any four values that sum to 63 work:

from flakeid import SnowflakeGenerator

gen = SnowflakeGenerator(
    timestamp_bits=41,
    datacenter_bits=8,   # up to 256 datacenters
    machine_bits=8,      # up to 256 machines per DC
    sequence_bits=6,     # 64 IDs/ms/node
    datacenter_id=200,
    machine_id=100,
)
uid = gen.next_id()

Container / cloud deployment — read node IDs from env vars

from flakeid import make_generator_from_env

# Reads FLAKEID_DATACENTER_ID and FLAKEID_MACHINE_ID from the environment.
# Falls back to 0 if the variables are not set.
gen = make_generator_from_env("twitter")

Set in your Dockerfile / docker-compose.yml / Kubernetes env: block:

FLAKEID_DATACENTER_ID=3
FLAKEID_MACHINE_ID=12

Custom variable names are supported:

gen = make_generator_from_env(
    "twitter",
    datacenter_env="MY_APP_DC",
    machine_env="MY_APP_NODE",
)

Infinite ID stream

from flakeid import make_generator, PRESET_TWITTER

gen = make_generator(PRESET_TWITTER)

for uid in gen.stream():
    save_to_db(uid)

Decoding an ID

dec = gen.decode(uid)

dec.timestamp_ms    # Unix ms when it was generated
dec.generated_at    # ISO-8601 UTC string, e.g. '2025-03-15T10:22:01.123Z'
dec.datacenter_id   # 3
dec.machine_id      # 12
dec.sequence        # 0

Thread safety

SnowflakeGenerator is thread-safe — a single instance can be shared across any number of threads.

import threading
from flakeid import make_generator, PRESET_TWITTER

gen = make_generator(PRESET_TWITTER, machine_id=1)

def worker():
    for _ in range(10_000):
        uid = gen.next_id()
        save(uid)

threads = [threading.Thread(target=worker) for _ in range(16)]
for t in threads: t.start()
for t in threads: t.join()
# All 160,000 IDs are guaranteed unique

Error handling

from flakeid import ClockBackwardsError, TimestampOverflowError, EpochError

try:
    uid = gen.next_id()
except ClockBackwardsError:
    # System clock jumped backwards by > 10 ms — check NTP
    ...
except TimestampOverflowError:
    # timestamp bits exhausted — increase timestamp_bits or update epoch_ms
    ...
except EpochError:
    # epoch_ms is in the future relative to current time
    ...

API reference

flakeid.next_id() → int

Module-level shortcut. Zero-config unique ID.

flakeid.next_ids(count) → list[int]

Module-level shortcut for bulk generation.

make_generator(preset=None, **overrides) → SnowflakeGenerator

Build a generator from a preset dict/name plus optional overrides.

make_generator_from_env(preset=None, *, datacenter_env, machine_env, epoch_env, **overrides) → SnowflakeGenerator

Build a generator whose node IDs come from environment variables.

SnowflakeGenerator

Method Description
next_id() One unique ID
next_ids(count) Many unique IDs, single lock
stream() Infinite iterator
decode(uid) Decompose an ID → DecodedID
capacity() Limits of this config → Capacity

Publishing to PyPI

# 1. Install the package + dev test deps (src/ layout) and build tools
pip install -e ".[dev]" hatch twine

# 2. Run the tests
pytest

# 3. Build distributions
hatch build        # creates dist/flakeid-0.1.0.tar.gz and .whl

# 4. Upload to PyPI
twine upload dist/*
# Enter your PyPI username/password or API token when prompted.

# 5. Users can now install with:
# pip install flakeid

For a test run first, upload to TestPyPI:

twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ flakeid

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flakeid-0.1.1.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flakeid-0.1.1-py3-none-any.whl (17.2 kB view details)

Uploaded Python 3

File details

Details for the file flakeid-0.1.1.tar.gz.

File metadata

  • Download URL: flakeid-0.1.1.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for flakeid-0.1.1.tar.gz
Algorithm Hash digest
SHA256 6ac70a7771007e5fe8c87d4c5ce1ad9965bb7d870864cabf5fcf8cafee082329
MD5 ffb73e63d53ef88fd2ea3ac136b57968
BLAKE2b-256 9e780d90fad8e08581b36aa89a84910ba0aed145e45e0d3a3f035732018fcc43

See more details on using hashes here.

File details

Details for the file flakeid-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: flakeid-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 17.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for flakeid-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 984d6e30ef6af5ef24f46d1f80d6b74547b992626eb4e53ca63a186a09c17372
MD5 42a821751e30da281d29ce1299f8afc0
BLAKE2b-256 cc27d294267c8eb5446bb9fe30a7442035bc4e8c5795b76545602157e5b170e0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page