Randflake ID
Overview
Randflake ID is a distributed, uniform, unpredictable, and unique random ID generator designed to provide robust identifier generation across multiple programming languages and environments.
Key Features
- 🌐 Multi-Language Support: Available in Go, Python, and TypeScript/JavaScript
- 🔒 Cryptographically Secure: Generates unpredictable and unique identifiers
- Allocation: Atomic timestamp/sequence state in Go; thread-safe allocation in Python
- Capacity: 131,072 IDs per node per second across 131,072 node IDs; actual throughput depends on the implementation and hardware
- 🔀 Distributed-Friendly: Suitable for distributed systems and microservices
- 📊 Uniform Distribution: Ensures even spread of generated IDs
Installation
Go
go get gosuda.org/randflake/v2@v2.1.0
The Go module is gosuda.org/randflake/v2, with the v2 API at its root. Go 1.23 remains supported. The original constructor API is available at gosuda.org/randflake/v2/legacy; the unsuffixed module path remains on the v1 release line.
Python
pip install randflake==2.1.0
TypeScript/JavaScript
npm install randflake@2.1.0
JSR
npx jsr add @safe/randflake@2.1.0
Usage Examples (v2)
Go
package main
import (
"fmt"
"time"
randflake "gosuda.org/randflake/v2"
)
func main() {
now := randflake.UnixSeconds(time.Now().Unix())
g, err := randflake.New(randflake.Config{
Lease: randflake.Lease{NodeID: 42, Start: now, EndExclusive: now + 600},
Secret: []byte("super-secret-key"),
})
if err != nil {
panic(err)
}
id, err := g.Generate()
if err != nil {
panic(err)
}
fmt.Println(id, g.Inspect(id).Timestamp)
}
Python
import time
from randflake.v2 import Config, Generator, Lease
now = int(time.time())
generator = Generator(Config(
lease=Lease(node_id=42, start=now, end_exclusive=now + 600),
secret=b"super-secret-key",
))
uid = generator.generate()
print(uid, generator.inspect(uid).timestamp)
TypeScript/JavaScript
import { Generator } from 'randflake/v2';
const now = Math.floor(Date.now() / 1000);
const generator = new Generator({
lease: { nodeID: 42, start: now, endExclusive: now + 600 },
secret: new TextEncoder().encode('super-secret-key'),
});
const uid = generator.generate();
console.log(uid, generator.inspect(uid).timestamp);
Clock and Lease Contract
- Timestamps are whole POSIX Unix seconds, not milliseconds, nanoseconds, or continuous SI time. The full 30-bit timestamp range is supported through 2058-11-05 17:10:23 UTC.
- v2 leases are half-open:
start <= now < endExclusive. The largest exclusive end is the maximum timestamp plus one. - A node must have only one active generator for overlapping lease seconds. A restart must obtain a non-overlapping lease; the library does not allocate node ownership or persist sequence state.
- Sequence values run from 0 through 131071 and restart at 0 in a new second. Backwards seconds are rejected on every allocation. Exhaustion returns an error without waiting or inventing a future timestamp.
- The optional constructor clock returns Unix seconds: Go
func() (UnixSeconds, error), Python a callable returningint, TypeScript() => number. Failures propagate without consuming a sequence. Callbacks must be read-only, non-reentrant, and safe for concurrent reads where applicable; Go may resample on a CAS retry. ExtendLease/extend_lease/extendLeaserequires the same node and start. It never shortens a lease; an already-satisfied valid request succeeds without changing it.Lease()/lease()returns a snapshot.- Inspection decrypts fields but does not authenticate an ID or require an active lease. Do not use successful inspection as proof that an ID was issued by a trusted party.
gstime is not a dependency. An application-supplied clock must explicitly project its time to Unix seconds and handle provider failures; continuous GST instants are not interchangeable with POSIX timestamps.
Migrating from the Legacy API
Go callers migrate to gosuda.org/randflake/v2, or temporarily use gosuda.org/randflake/v2/legacy for the deprecated constructor and signatures. The unsuffixed Go module remains available through existing v1 tags. Python randflake.Generator and the TypeScript randflake entrypoint remain deprecated compatibility facades. Removal is reserved for a future major release. Python warns at construction, never per generated ID; Go and TypeScript use deprecation documentation.
| Legacy | v2 |
|---|---|
| Positional node/start/end/secret constructor | Config with Lease, secret, and optional clock |
Inclusive leaseEnd / lease_end |
Exclusive end: pass the old end plus one |
| Mutable clock assignment | Constructor-supplied clock |
| Boolean lease update | Valid idempotent extension succeeds; invalid requests return/raise a domain error |
| Inspection tuple | Named Parts fields |
| Case-insensitive, padding-terminated string input | Canonical lowercase, unpadded base32hex only |
Both surfaces share one generation implementation per language. Existing encrypted IDs and canonical strings remain compatible; internal counters and the old counter progression are not a persistence API. Use lease update methods instead of mutating allocation state.
Go and Python return signed 64-bit integer values; TypeScript returns signed bigint. For JSON interchange, use decimal strings or the base32hex representation rather than converting IDs to JavaScript number.
Performance
Go allocates the timestamp and sequence in one CAS state transition; successful numeric generation has no per-ID heap allocation. A heavily shared generator can contend on this state. Independent generators require distinct leased node IDs, not copies of one generator.
Python locks only clock reading and allocation; encryption runs outside the lock. TypeScript reuses its crypto buffer and precomputes node bits. Neither implementation creates a lease snapshot on each generation.
Benchmarks must stay below per-second capacity or advance a controlled clock. Burst ns/op figures are not sustained IDs/second guarantees, and benchmarks using separate generators do not measure shared-generator contention.
String Representation
v2 codecs accept signed 64-bit IDs and emit canonical lowercase base32hex:
from randflake.v2 import decode_string, encode_string
assert encode_string(4594531474933654033) == "3vgoe12ccb8gh"
assert decode_string("3vgoe12ccb8gh") == 4594531474933654033
assert encode_string(-1) == "fvvvvvvvvvvvv"
assert decode_string("fvvvvvvvvvvvv") == -1
The strict decoder rejects empty input, leading zeros except "0", uppercase, padding, invalid characters, and values exceeding 64 bits. Legacy decoders retain their permissive case/padding behavior and modulo-64 overflow handling.
Cross-Language Test Vectors
The repository root contains test_vectors.json, generated by the Go test
suite and consumed by the Go, Python, and TypeScript tests. Each vector records
the secret, lease, timestamp, node ID, sequence, raw bit-packed ID, encrypted ID,
and base32hex encoded ID.
The raw_id and encrypted_id values are JSON strings, not JSON numbers, so
64-bit values round-trip safely in JavaScript/TypeScript and other IEEE
754-number environments.
Vector lease ends retain the legacy inclusive convention; v2 consumers add one to obtain the exclusive end. The corpus includes both the first timestamp setting raw bit 63 and the final supported timestamp.
To regenerate the canonical vectors after an intentional algorithm change:
go test ./legacy -run TestRandflakeTestVectors -update-test-vectors
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
Distributed under the MIT License. See LICENSE for more information.
More Information
For detailed documentation and additional resources, visit: https://gosuda.org/randflake
Metadata
Release files for randflake 2.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| randflake-2.1.0.tar.gz | 73.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| randflake-2.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.7 kB
Release files / randflake-2.1.0.tar.gz
| Download URL | randflake-2.1.0.tar.gz |
|---|---|
| Size | 73.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5750a5b0c2475b1b88c136b881127cc0e775c26c312e8a328e3b5cd254652138
|
|
BLAKE2b-256 checksum How to use checksums |
0680b6935897ea539864e4e037acd3d3a5efb3b69fdb1fbc1d76ac51f7cd1fdc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency logRelease files / randflake-2.1.0-py3-none-any.whl
| Download URL | randflake-2.1.0-py3-none-any.whl |
|---|---|
| Size | 17.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7a4f280cee3984f2ec6da7ed3eb17dbccff916481a5f8b850a99d2d4ae89a08c
|
|
BLAKE2b-256 checksum How to use checksums |
7a83bd762c0531d36a4effa299a485245af8426845de43e3fa3f7f758cfd8960
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency log