BeakId
English | Русский
Snowflake-like 64-bit unique IDs for Rust, returned as non-negative i64
values for PostgreSQL BIGINT.
Layout
Each ID uses this 64-bit layout:
[ reserved: 1 | timestamp: 35 | sequence: 18 | worker: 10 ]
Parts:
reserved: always0timestamp: 100ms windows since the configured custom epochsequence: per-window counterworker: generator worker id in0..=1023
Because the highest bit is always zero, generated IDs are valid non-negative
i64 values.
Configuration
The global singleton reads configuration lazily on first use:
BEAKID_EPOCH=2025-01-01T00:00:00Z
BEAKID_WORKER_ID=42
Variables:
BEAKID_EPOCH: required RFC 3339 UTC datetime, for example2025-01-01T00:00:00ZBEAKID_WORKER_ID: optionalu16, defaults to0, must fit in 10 bits
Invalid or missing epoch configuration is rejected.
API
Singleton
let id = next_id;
next_id() panics if environment configuration is invalid. Use
try_next_id() to handle errors:
let id = try_next_id?;
# Ok::
Background Updater
Start the standard-thread background updater once during application startup:
start_background?;
# Ok::
The updater runs roughly every 30ms and reconciles the generator with real time. The crate does not depend on Tokio or any other async runtime.
Explicit Generator
use UNIX_EPOCH;
let generator = new?;
let id = generator.next_id?;
# Ok::
Algorithm
Generator follows the reference beakid-rs approach:
The hot path increments one atomic ID value by 1 << 10, which advances the
sequence while preserving the worker bits. No mutexes are used.
When sequence overflow crosses a 100ms window boundary, the generator refreshes real time. If the generated virtual window is ahead of real time, generation can continue up to 10 virtual windows. If that limit is exhausted, generation waits until real time catches up.
Storage
Use PostgreSQL BIGINT:
id BIGINT PRIMARY KEY
Generated values are sortable by approximate creation time within the configured epoch and worker-id scheme.