Fast, time-sortable, 21-char Base58 unique ID generator
Project description
sparkid
Fast, monotonic, time-sortable, 21-char Base58 unique ID generator. Zero dependencies.
1ocmpHE1bFnygEBAPTzMK
1ocmpHE1bFnygFv4Wp4dL
1ocmpHE1bFnygGoUXUL7X
Install
pip install sparkid
Usage
from sparkid import generate_id
id = generate_id()
# => "1ocmpHE1bFnygEBAPTzMK"
Properties
| Property | Value |
|---|---|
| Length | 21 characters, fixed |
| Alphabet | Base58 (no 0, O, I, l) |
| Sortable | Lexicographically, by creation time |
| Monotonic | Strictly increasing within each thread |
| URL-safe | Yes |
| Collision resistance | ~58^13 (~8.4 x 10^22) combinations per millisecond |
| Randomness | Cryptographically secure (os.urandom) |
| Thread-safe | Yes (via threading.local) |
How it works
Each ID is composed of two parts:
[8-char timestamp][13-char suffix]
- Timestamp (8 chars): Current time in milliseconds, Base58-encoded. IDs generated in a later millisecond always sort after earlier ones.
- Suffix (13 chars): Seeded from
os.urandom(rejection-sampled, no modulo bias) at the start of each millisecond, then monotonically incremented for each subsequent ID within that millisecond. This guarantees strict ordering even when multiple IDs share a timestamp.
Ordering guarantees
IDs from a single IdGenerator instance (or a single thread using generate_id()) are strictly monotonically increasing — every ID is lexicographically greater than the one before it.
Across threads, IDs are unique but not ordered relative to each other. Each thread gets its own generator via threading.local, so there is no cross-thread coordination. This is the same guarantee provided by most UUID v7 libraries.
If you need process-wide monotonic ordering across threads, wrap a single IdGenerator in a lock:
import threading
from sparkid import IdGenerator
_lock = threading.Lock()
_gen = IdGenerator()
def generate_id_monotonic():
with _lock:
return _gen()
Advanced usage
For manual control, use the IdGenerator class directly:
from sparkid import IdGenerator
gen = IdGenerator()
id = gen()
Each IdGenerator instance maintains its own internal state. The module-level generate_id() function uses threading.local to automatically create one instance per thread.
Performance
python bench/benchmark.py
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sparkid-1.3.1.tar.gz.
File metadata
- Download URL: sparkid-1.3.1.tar.gz
- Upload date:
- Size: 24.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8dc8ef2f87d95a2de814d7e3f63b5176c07230f61d95c58ce666d994a654438
|
|
| MD5 |
206b977bc11c8c543bf365ebec7620ea
|
|
| BLAKE2b-256 |
5b750a6013d1f37bf5f92f1aec46f7d7649462fb4860483bc4d21f227291fb26
|
File details
Details for the file sparkid-1.3.1-py3-none-any.whl.
File metadata
- Download URL: sparkid-1.3.1-py3-none-any.whl
- Upload date:
- Size: 6.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c0c45845a1b402042bdfd6ba2934481974a913a456b6e6c9df81cbcded1ff57
|
|
| MD5 |
daf05b92b4b8a04301881e4b1cd4fadb
|
|
| BLAKE2b-256 |
41737b6515f50695e4180a082d38c6e39d92c949a2303eb7a1d563303374a903
|