Time-ordered, human-readable, collision-resistant identifiers for distributed systems.
Simple WID 20260217T143052.0000Z-a3f91c
Distributed HLC 20260217T143052.0000Z-node01-a3f91c
Millisecond mode 20260217T143052789.0042Z-e7b3a1
╰─── timestamp ───╯╰seq╯ ╰─pad─╯
| Property | UUID v4 | UUID v7 | ULID | KSUID | WID | HLC-WID |
|---|---|---|---|---|---|---|
| Time-sortable | No | Yes | Yes | Yes | Yes | Yes |
| Human-readable timestamp | No | No | No | No | Yes | Yes |
| Collision-resistant | Yes | Yes | Yes | Yes | Yes | Yes |
| No coordination needed | Yes | Yes | Yes | Yes | Yes | Yes |
| Distributed causal ordering | No | No | No | No | No | Yes |
| Configurable precision | No | No | No | No | Yes | Yes |
| Debuggable at a glance | No | No | No | No | Yes | Yes |
git clone https://github.com/waldiez/wid && cd wid
make next # generate one WID via the canonical sh CLI
make quick-check # fast gate across all implementations# Generate
wid next # → 20260217T143052.0000Z-a3f91c
wid next --kind hlc --node sensor42 # → …0000Z-sensor42-a3f91c
wid next --time-unit ms # millisecond precision
# Stream
wid stream --count 10 # 10 WIDs, back-to-back
# Validate / parse
wid validate 20260217T143052.0000Z-a3f91c
wid parse 20260217T143052.0000Z-a3f91c --jsonAll implementations accept the same flag matrix (--kind, --node, --W, --Z, --time-unit, etc.) defined in spec/quick-usage.md.
| # | Language | Source | Tests | Crypto | Notes |
|---|---|---|---|---|---|
| 1 | Rust | rust/ | cargo test |
Yes | Reference implementation · Docker |
| 2 | Python | python/ | pytest |
Yes | Async generators · aiosqlite SQL |
| 3 | C | c/ | custom | Yes | Single-header wid.h |
| 4 | TypeScript | typescript/ | vitest |
Yes | ESM + CJS · browser-ready |
| 5 | Go | go/ | go test |
Yes | Thread-safe · stdlib only |
| 6 | sh | sh/ | self-test | Yes | Canonical POSIX orchestrator |
All implementations conform to the same specification and pass the shared conformance fixtures in spec/conformance/.
WID TIMESTAMP . SEQ Z [ - PAD ]
HLC-WID TIMESTAMP . LC Z - NODE [ - PAD ]
| Component | Description | Example |
|---|---|---|
TIMESTAMP |
UTC, YYYYMMDDTHHMMSS or YYYYMMDDTHHMMSSmmm |
20260217T143052 |
SEQ/LC |
Zero-padded sequence or logical counter (width W) | 0000 |
Z |
Literal Z (UTC marker + separator) |
Z |
NODE |
Alphanumeric + underscore identifier (HLC only) | node01 |
PAD |
Random lowercase hex (length Z) | a3f91c |
Parameters
| Param | Default | Description |
|---|---|---|
| W | 4 | Sequence width — supports 10^W IDs/tick |
| Z | 6 | Hex padding length (0 disables) |
| T | sec |
Time unit: sec or ms |
Full specification with EBNF grammar: spec/SPEC.md
cargo install waldiez-widpip install waldiez-widnpm install @waldiez/widgo install github.com/waldiez/wid/go/cmd/wid@latest// Single header — copy c/include/wid.h into your project
#include "wid.h"docker pull ghcr.io/waldiez/wid
docker run --rm ghcr.io/waldiez/wid nextmake setup # install language tooling
make test # all language test suites
make check # lint + type-check + test
make bench-matrix # cross-language benchmark
make docker # build Docker image
make clean # remove build artifactsPer-language helpers: make rust-test, make python-check, make ts-build, make go-next, etc.
wid A=sign— Ed25519 signature over a WID + optional payload.wid A=verify— Verify signature against a WID and public key.wid A=w-otp— WID-bound OTP (MODE=gen|verify): HMAC-SHA256 keyed on the WID.
Full specification: spec/CRYPTO_SPEC.md
When using E=sql, generator state (last_tick, last_seq) is persisted per key and resumed across restarts.
State modes:
-
E=state -
E=stateless -
E=sql -
A=stream N=0means infinite stream (all primary implementations).
CREATE TABLE IF NOT EXISTS wid_state (
k TEXT PRIMARY KEY,
last_tick INTEGER NOT NULL,
last_seq INTEGER NOT NULL
);WID as a primary key:
CREATE TABLE events (
wid TEXT PRIMARY KEY,
payload JSON NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Time-range scans by WID prefix are zero-cost (lexicographic order = time order)
CREATE INDEX IF NOT EXISTS ix_events_wid_prefix ON events(wid);