A lightweight ID generator for TypeScript and JavaScript that doesn't break when your system clock rolls back.
I built this because I needed time-sortable (k-ordered) IDs that were resilient to clock drift and worked in small distributed environments (up to 64 nodes) without pulling in massive external dependencies.
There are plenty of ID libraries out there, but I wanted something that hit three specific points:
- Actually lightweight: Zero dependencies. It just works in Node.js, browsers, and edge environments without any extra setup.
- Secure by design: I'm not using
Math.random(). I implementedcryptowith rejection sampling to eliminate modulo bias, making sure every character is truly random. - Clock-drift resilience: If your server's clock drifts backward,
createAsync()intelligently waits for time to "catch up" to the ID sequence instead of crashing or creating duplicates.
npm i dotidimport { etch } from 'dotid';
// Generates time-sortable 14-character IDs by default.
// I'm assigning machine ID 1 here (accepts 0 to 63).
const ids = etch({ mid: 1 });
const id = ids.create();
// Real example: "AN7wDREABBky_W"
// If your environment is prone to system clock shifts:
const safeId = await ids.createAsync();If I don't need time-ordering and just want pure entropy (for tokens or session keys):
const tokens = etch({ mode: 'secure', length: 32 });
const sessionToken = tokens.create();
// For maximum security (defaults to 32 chars):
const secrets = etch({ mode: 'high-entropy' });The generator instance (ids) has a few more tricks:
// Generate multiple IDs at once
const batch = ids.createBatch(10);
// Validate an ID's format and length
const isValid = ids.isValid("AN7wDREABBky_W");Unlike other libraries that try to automate everything, I prefer being explicit:
mode: Can betimestamp(default),secure,distributed, orhigh-entropy.mid: Machine ID. This is required if I'm usingdistributedmode.epoch: Allows me to adjust the base timestamp so IDs are shorter or start from a specific date.length: ID length, only applied to entropy modes.
I added a couple of things I always find myself rewriting:
constantTimeCompare: To compare tokens safely without leaving me open to timing attacks.sift: A basic filter to prevent the generator from accidentally spitting out bad words.isSupported: Checks if the environment supports the necessary crypto features.
MIT © [qgave]