
Security News
GitHub Actions Checkout Now Blocks Risky pull_request_target Checkouts
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.
@cdlab996/genid
Advanced tools
High-performance distributed unique ID generator based on the Snowflake algorithm
High-performance distributed unique ID generator based on the Snowflake algorithm, with drift mode and clock-rollback handling.
afterTime support# npm
npm install @cdlab996/genid
# pnpm
pnpm add @cdlab996/genid
import { GenidOptimized } from '@cdlab996/genid'
// Create an instance (use a different workerId for each worker/process)
const genid = new GenidOptimized({ workerId: 1 })
// Generate an ID
const id = genid.nextId()
// Batch generate
const ids = genid.nextBatch(1000)
// Parse an ID
const info = genid.parse(id)
// => { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
// Validate an ID
genid.isValid(id) // true
new GenidOptimized(options)| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
workerId | number | Yes | - | Worker node ID (0 to 2^workerIdBitLength-1) |
method | GenidMethod | DRIFT | Algorithm: DRIFT or TRADITIONAL | |
baseTime | number | 1577836800000 | Base timestamp in ms (default: 2020-01-01) | |
workerIdBitLength | number | 6 | Bit length for worker ID (1-15) | |
seqBitLength | number | 6 | Bit length for sequence (3-21) | |
maxSeqNumber | number | 2^seqBitLength-1 | Maximum sequence number | |
minSeqNumber | number | 5 | Minimum sequence number (0-4 reserved for rollback) | |
topOverCostCount | number | 2000 | Maximum drift count |
genid.nextId() // Returns number | bigint (auto-selects)
genid.nextNumber() // Returns number (throws if exceeds safe integer range)
genid.nextBigId() // Returns bigint
genid.nextBatch(100) // Batch generate 100 IDs
genid.nextBatch(100, true) // Batch generate 100 BigInt IDs
// Parse an ID into its components
genid.parse(id)
// => { timestamp: Date, timestampMs: number, workerId: number, sequence: number }
// Loose validation: checks structural validity
genid.isValid(id) // true
genid.isValid('invalid') // false
// Strict validation: requires workerId to match the current instance
genid.isValid(id, true) // true (generated by this instance)
genid.isValid(otherId, true) // false (generated by another instance)
// Time-bound validation: reject IDs generated before a given time
const startupTime = Date.now()
genid.isValid(id, { afterTime: startupTime }) // true
genid.isValid(id, { strictWorkerId: true, afterTime: startupTime }) // combined
// Get runtime statistics
genid.getStats()
// => {
// totalGenerated: 1000,
// overCostCount: 10,
// turnBackCount: 2,
// uptimeMs: 60000,
// avgPerSecond: 16,
// currentState: 'NORMAL' | 'OVER_COST'
// }
// Get current configuration
genid.getConfig()
// => {
// method: 'DRIFT',
// workerId: 1,
// workerIdRange: '0-63',
// sequenceRange: '5-63',
// maxSequence: 63,
// idsPerMillisecond: 59,
// baseTime: Date,
// timestampBits: 52,
// workerIdBits: 6,
// sequenceBits: 6
// }
// Reset statistics
genid.resetStats()
genid.formatBinary(id)
// ID: 123456789012345
// Binary (64-bit):
// 0000000000011010... - Timestamp (52 bits) = 2025-10-17T...
// 000001 - Worker ID (6 bits) = 1
// 101010 - Sequence (6 bits) = 42
import { GenidOptimized, GenidMethod } from '@cdlab996/genid'
const genid = new GenidOptimized({
workerId: 1,
method: GenidMethod.TRADITIONAL,
baseTime: new Date('2024-01-01').valueOf(),
workerIdBitLength: 10, // Support 1024 nodes
seqBitLength: 12, // 4096 IDs per millisecond
topOverCostCount: 5000,
})
// Validate IDs from a database or API
const externalId = '123456789012345'
if (genid.isValid(externalId)) {
const info = genid.parse(externalId)
console.log('Generated at:', info.timestamp)
console.log('From worker:', info.workerId)
} else {
console.error('Invalid ID')
}
setInterval(() => {
const stats = genid.getStats()
console.log(`Rate: ${stats.avgPerSecond} ID/s | Drift: ${stats.overCostCount} | Rollback: ${stats.turnBackCount}`)
}, 10000)
| Mode | Description | Use Case |
|---|---|---|
| DRIFT (default) | Borrows future timestamps when sequence is exhausted; avoids waits | High-frequency ID generation |
| TRADITIONAL | Strictly increasing timestamps; waits for next ms on exhaustion | Strict time-ordering required |
|------------ Timestamp ------------|-- Worker ID --|-- Sequence --|
42-52 bits 1-15 bits 3-21 bits
Default: Timestamp 52 bits (~139 years) | Worker ID 6 bits (64 nodes) | Sequence 6 bits (59 IDs/ms)
Sequence values 0-4 are reserved for clock rollback; normal generation starts at 5.
graph TB
A[Start ID Generation] --> B{In drift mode?}
B -->|No| C[Normal Path]
B -->|Yes| D[Drift Path]
C --> E{Check Clock}
E -->|Clock Rollback| F[Use Reserved Sequence 0-4]
E -->|Time Advanced| G[Reset Sequence]
E -->|Same Millisecond| H{Sequence Exhausted?}
H -->|No| I[Increment Sequence]
H -->|Yes| J[Enter Drift Mode, Timestamp+1]
D --> K{Check Time}
K -->|Time Caught Up| L[Exit Drift, Resume Normal]
K -->|Exceeded Max Drift| M[Wait for Next ms, Exit Drift]
K -->|Continue Drift| N{Sequence Exhausted?}
N -->|No| O[Use Current Sequence]
N -->|Yes| P[Timestamp+1, Reset Sequence]
F --> Q[Assemble ID]
G --> Q
I --> Q
J --> Q
L --> Q
M --> Q
O --> Q
P --> Q
Q --> R[Update Statistics]
R --> S[Return ID]
Throughput is determined by the number of available sequence slots per millisecond. Increasing seqBitLength scales linearly:
| seqBitLength | Slots/ms | Throughput |
|---|---|---|
| 3 | 3 | ~3,000 IDs/sec |
| 4 | 11 | ~11,000 IDs/sec |
| 6 (default) | 59 | ~58,000 IDs/sec |
| 8 | 251 | ~247,000 IDs/sec |
| 10 | 1,019 | ~1,000,000 IDs/sec |
| 14 | 16,379 | ~4,500,000 IDs/sec |
Measured on Node.js v22 (x64). Actual results vary by environment. Run
pnpm run benchmarkto probe your own machine.
| Metric | Value (default config) |
|---|---|
| Max worker nodes | 64 |
| Timestamp lifespan | ~139 years |
| P99 latency (single call) | < 1µs |
A built-in probe script measures the actual capability of the current environment:
pnpm run benchmark
It reports:
nextId() IDs/secnextBatch() across different batch sizesstation :: /app/projects/genid ‹main*› » pnpm run benchmark
> @cdlab996/genid@1.4.0 benchmark /app/projects/genid
> npx tsx scripts/benchmark.ts
============================================================
GenidOptimized — Environment Capability Probe
Node v22.22.0 | linux x64
Date: 2026-04-01T08:41:07.669Z
============================================================
────────────────────────────────────────────────────────────
1. Single-call throughput (nextId)
────────────────────────────────────────────────────────────
Duration: 3001ms
Generated: 226,073
Throughput: 75,332 IDs/sec
────────────────────────────────────────────────────────────
2. Batch throughput (nextBatch)
────────────────────────────────────────────────────────────
batch= 100 × 5000 => 61,665 IDs/sec
batch= 1,000 × 500 => 61,577 IDs/sec
batch= 10,000 × 50 => 61,716 IDs/sec
batch=100,000 × 5 => 61,644 IDs/sec
────────────────────────────────────────────────────────────
3. Single-call latency percentiles
────────────────────────────────────────────────────────────
Samples: 100,000
Avg: 0µs
P50: 0µs
P95: 1µs
P99: 1µs
P99.9: 1µs
Max: 364µs
────────────────────────────────────────────────────────────
4. Algorithm comparison (DRIFT vs TRADITIONAL)
────────────────────────────────────────────────────────────
DRIFT 58,296 IDs/sec drift=1
TRADITIONAL 59,000 IDs/sec drift=0
────────────────────────────────────────────────────────────
5. Throughput by sequence bit length
────────────────────────────────────────────────────────────
seqBits= 3 maxSeq= 7 => 2,986 IDs/sec drift=1
seqBits= 4 maxSeq= 15 => 10,884 IDs/sec drift=1
seqBits= 6 maxSeq= 63 => 58,240 IDs/sec drift=1
seqBits= 8 maxSeq= 255 => 247,804 IDs/sec drift=1
seqBits=10 maxSeq= 1023 => 1,008,930 IDs/sec drift=1
seqBits=14 maxSeq=16383 => 4,130,701 IDs/sec drift=0
────────────────────────────────────────────────────────────
6. Memory footprint
────────────────────────────────────────────────────────────
Generated: 1,000,000 IDs (not stored)
Heap delta: -6.27 MB
Note: Run with --expose-gc for accurate GC-forced measurement
────────────────────────────────────────────────────────────
Summary — Recommended test thresholds
────────────────────────────────────────────────────────────
Peak single-call: 75,332 IDs/sec
Peak batch: 61,716 IDs/sec
Suggested min threshold: 45,199 IDs/sec (60% of peak)
Suggested batch threshold: 37,029 IDs/sec (60% of peak)
Suggested P99 cap: 2µs (3× measured P99)
pnpm install # Install dependencies
pnpm run build # Build (ESM + CJS)
pnpm run dev # Watch mode
pnpm run test # Run tests
pnpm run benchmark # Run environment capability probe
pnpm run typecheck # Type check
pnpm run lint # Lint (Biome)
pnpm run format # Format (Biome)
workerIdBitLength + seqBitLength must not exceed 22nextBigId() or nextId() (auto-returns BigInt)FAQs
High-performance distributed unique ID generator based on the Snowflake algorithm
The npm package @cdlab996/genid receives a total of 29 weekly downloads. As such, @cdlab996/genid popularity was classified as not popular.
We found that @cdlab996/genid demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.