@breacket/time-id
v0.1.0
Published
Deterministic, collision-safe Node.js id generator that is deliberately NOT sortable — short, URL-safe, configurable alphabet per deployment.
Maintainers
Readme
time-id
A deterministic, collision-safe id generator for Node.js — short enough to paste by hand, and deliberately not sortable.
Most time-based id generators (ULID, KSUID, Snowflake-style ids) exist
specifically to be sortable — that's their selling point. time-id targets
the opposite requirement: ids that don't leak creation order, request volume,
or growth rate to whoever sees them, while still guaranteeing — not just
statistically hoping — that concurrent calls never collide.
const { id } = require('time-id');
id(); // 'StMdgTwA'
id(); // 'StMdgTwB'
id(); // 'StMdgTwC'Why not sortable
A sequential or sortable id tells anyone who sees it roughly how many
records exist, how fast they're being created, and in what order. That's
fine for an internal database key. It's often not fine for anything
exposed in a URL, an API response, or a support ticket. time-id still
uses a timestamp internally (so uniqueness is deterministic, not
probabilistic like a random string), but the default alphabet is not in
ASCII order, so the encoded output doesn't sort the way the underlying
value does.
Why not just nanoid / uuid / ulid / ksuid?
| | uniqueness | sortable | typical length | alphabet |
|---|---|---|---|---|
| uuid v4 | probabilistic (birthday bound) | no | 36 chars | fixed |
| nanoid | probabilistic | no | 21 chars (configurable) | configurable |
| ulid / ksuid | deterministic | yes, by design | 26–27 chars | fixed |
| time-id | deterministic | no, by design | ~8–11 chars typically | fully configurable |
If you want sortable ids, use ULID or KSUID — they do that job well. If you want deterministic (not just probabilistic) uniqueness without leaking order or volume, and something short enough to read out loud, that's the gap this fills.
Install
npm install time-idQuick start
const { id, rawId } = require('time-id');
id(); // 'StLXf1AA' — string, safe for URLs and filenames
rawId(); // 2049638917632n — the same value as a BigInt, if you want to store it as oneCustom configuration
const { createIdGenerator } = require('time-id');
const gen = createIdGenerator({
epoch: Date.UTC(2026, 0, 1),
seqBits: 12, // more headroom per millisecond than the 10-bit default
shardBits: 8, // set >0 only if several processes generate ids at once
shardId: 3, // this process/instance's shard number
onSequenceOverflow: 'throw', // fail loudly instead of blocking under extreme burst
});
gen.nextString();Recovering the parts of an id
gen.decompose('StLXf1AA');
// { timestamp: 2049638917n, date: 2026-07-18T20:07:00.123Z, shardId: 3n, sequence: 0n }Using your own alphabet
Every deployment can use a different character mapping. Two services running the same package with two different alphabets produce structurally incompatible-looking ids — someone who sees one service's ids gains no insight into how the other service's ids are built.
const { IdCodec, createIdGenerator } = require('time-id');
const myCodec = IdCodec.shuffled(); // random private ordering, generated once at deploy time
const gen = createIdGenerator({ alphabet: myCodec });API
id()/rawId()— zero-config, ready to use.createIdGenerator(options)→TimeIdinstance..next()→bigint.nextString(opts?)→string(opts.padfor fixed-width output).decompose(id)→{ timestamp, date, shardId, sequence }
IdCodec— the encode/decode layer, usable standalone.new IdCodec(alphabet)IdCodec.shuffled(alphabet?, rng?)— private per-deployment ordering.encode(value, length?),.decode(string)
What this does not do
- It is not a UUID replacement for interop with systems that expect RFC 4122 UUIDs.
- It does not coordinate shard ids across processes for you — if you use
shardBits, assigning distinctshardIds to each process/instance is on you (env variable, config, orchestrator metadata, etc). - Sequence/clock-rollback handling that defaults to
'wait'/'throw'will either briefly block the event loop or throw under genuinely extreme load — pick whichever behavior fits your service.
License
MIT
