Fast, lightweight, and reliable distributed 64-bit ID generation with zero dependencies for Node.js.
npm install simpleflakes
[![npm][npm-badge]][npm-link]
[![coveralls status][coveralls-badge]][coveralls-link]








> Fast, lightweight, and reliable distributed 64-bit ID generation for Node.js
> Zero dependencies • TypeScript-ready • 8.8M+ ops/sec performance
- ⚡ 8.8M+ ops/sec - Ultra-fast performance
- 🔢 Time-oriented 64-bit IDs - Globally unique, sortable by creation time
- 0️⃣ Zero dependencies - Pure JavaScript, lightweight bundle
- 🏷️ TypeScript-ready - Full type safety and universal module support
- 🚀 Production-ready - 100% test coverage, Snowflake compatible
- What is Simpleflake?
- Installation
- Quick Start
- Advanced Usage
- ID Structure
- Performance
- Architecture
- Use Cases
- API Reference
- Migration Guide
- Comparison
- Contributing
Simpleflake generates unique 64-bit integers that are:
1. Time-ordered - IDs generated later are numerically larger
2. Distributed-safe - No coordination needed between multiple generators
3. Compact - Fits in a 64-bit integer (vs UUID's 128 bits)
4. URL-friendly - Can be represented as short strings
Perfect for database primary keys, distributed system IDs, and anywhere you need fast, unique identifiers.
- Original Presentation - Introduction to the concept by Mali Akmanalp
- Video Discussion - Detailed explanation and use cases
- Python Implementation - Original reference implementation
- Twitter Snowflake - Similar distributed ID system
``bash`
npm install simpleflakes
javascript
const { simpleflake } = require('simpleflakes');// Generate a unique ID
const id = simpleflake();
console.log(id); // 4234673179811182512n (BigInt)
// Convert to different formats
console.log(id.toString()); // "4234673179811182512"
console.log(id.toString(16)); // "3ac494d21e84f7b0" (hex)
console.log(id.toString(36)); // "w68acyhy50hc" (base36 - shortest)
`$3
`typescript
import { simpleflake, parseSimpleflake, type SimpleflakeStruct } from 'simpleflakes';// Generate with full type safety
const id: bigint = simpleflake();
// Parse the ID to extract timestamp and random bits
const parsed: SimpleflakeStruct = parseSimpleflake(id);
console.log(parsed.timestamp); // "1693244847123" (Unix timestamp as string)
console.log(parsed.randomBits); // "4567234" (Random component as string)
`Advanced Usage
$3
`javascript
// Generate with custom timestamp and random bits
const customId = simpleflake(
Date.now(), // timestamp (default: Date.now())
12345, // random bits (default: 23-bit random)
Date.UTC(2000, 0, 1) // epoch (default: Year 2000)
);
`$3
`javascript
import { binary, extractBits } from 'simpleflakes';const id = simpleflake();
// View binary representation
console.log(binary(id));
// Output: "0011101011000100100100110100001000011110100001001111011110110000"
// Extract specific bit ranges
const timestampBits = extractBits(id, 23n, 41n); // Extract 41 bits starting at position 23
const randomBits = extractBits(id, 0n, 23n); // Extract first 23 bits
`$3
`javascript
// Generate multiple IDs efficiently
function generateBatch(count) {
const ids = [];
for (let i = 0; i < count; i++) {
ids.push(simpleflake());
}
return ids;
}const batch = generateBatch(1000);
console.log(
Generated ${batch.length} unique IDs);
`ID Structure
Each 64-bit simpleflake ID contains:
|<------- 41 bits ------->|<- 23 bits ->|
|-------------------------|-------------|
|Timestamp |Random |
|(milliseconds from epoch)|(0-8388607) |
- 41 bits timestamp: Milliseconds since epoch (Year 2000)
- 23 bits random: Random number for uniqueness within the same millisecond
- Total: 64 bits = fits in a signed 64-bit integer
This gives you:
- 69+ years of timestamp range (until year 2069)
- 8.3 million unique IDs per millisecond
- Extremely low collision chance - 1 in 8.3 million per millisecond
- Sortable by creation time when converted to integers
Performance
This library is optimized for speed:
`javascript
// Benchmark results (operations per second)
simpleflake() // ~8.8M+ ops/sec
parseSimpleflake() // ~3.9M+ ops/sec
binary() // ~26M+ ops/sec
`Perfect for high-throughput applications requiring millions of IDs per second.
Architecture
$3
- Database-friendly: Most databases optimize for 64-bit integers
- Memory efficient: Half the size of UUIDs (128-bit)
- Performance: Integer operations are faster than string operations
- Sortable: Natural ordering by creation time
- Compact URLs: Shorter than UUIDs when base36-encoded
$3
No coordination required between multiple ID generators:
- Clock skew tolerant: Small time differences between servers are fine
- Random collision protection: 23 random bits provide 8.3M combinations per millisecond
- High availability: Each service can generate IDs independently
Use Cases
$3
`javascript
// Perfect for database IDs - time-ordered and unique
const userId = simpleflake();
await db.users.create({ id: userId.toString(), name: "John" });
`$3
`javascript
// Each service can generate IDs independently
const serviceAId = simpleflake(); // Service A
const serviceBId = simpleflake(); // Service B
// No coordination needed, guaranteed unique across services
`$3
`javascript
// Generate compact URL identifiers
const shortId = simpleflake().toString(36); // "w68acyhy50hc"
const url = https://short.ly/${shortId};
`$3
`javascript
// Time-ordered event IDs for chronological processing
const eventId = simpleflake();
await analytics.track({ eventId, userId, action: "click" });
`API Reference
$3
####
simpleflake(timestamp?, randomBits?, epoch?): bigint
Generates a unique 64-bit ID.Parameters:
-
timestamp (number, optional): Unix timestamp in milliseconds. Default: Date.now()
- randomBits (number, optional): Random bits (0-8388607). Default: random 23-bit number
- epoch (number, optional): Epoch start time. Default: Date.UTC(2000, 0, 1)Returns: BigInt - The generated ID
`javascript
const id = simpleflake();
const customId = simpleflake(Date.now(), 12345, Date.UTC(2000, 0, 1));
`####
parseSimpleflake(flake): SimpleflakeStruct
Parses a simpleflake ID into its components.Parameters:
-
flake (bigint | string | number): The ID to parseReturns: Object with
timestamp and randomBits properties (both bigint)`javascript
const parsed = parseSimpleflake(4234673179811182512n);
console.log(parsed.timestamp); // "1693244847123"
console.log(parsed.randomBits); // "4567234"
`####
binary(value, padding?): string
Converts a number to binary string representation.Parameters:
-
value (bigint | string | number): Value to convert
- padding (boolean, optional): Whether to pad to 64 bits. Default: trueReturns: String - Binary representation
`javascript
console.log(binary(42n)); // "0000000000000000000000000000000000000000000000000000000000101010"
console.log(binary(42n, false)); // "101010"
`####
extractBits(data, shift, length): bigint
Extracts a portion of bits from a number.Parameters:
-
data (bigint | string | number): Source data
- shift (bigint): Starting bit position (0-based from right)
- length (bigint): Number of bits to extractReturns: BigInt - Extracted bits as number
`javascript
const bits = extractBits(0b11110000n, 4n, 4n); // Extract 4 bits starting at position 4
console.log(bits); // 15n (0b1111)
`$3
####
SIMPLEFLAKE_EPOCH: number
The epoch start time (January 1, 2000 UTC) as Unix timestamp.`javascript
import { SIMPLEFLAKE_EPOCH } from 'simpleflakes';
console.log(SIMPLEFLAKE_EPOCH); // 946684800000
`$3
`typescript
interface SimpleflakeStruct {
timestamp: bigint; // Unix timestamp as bigint (since 2000)
randomBits: bigint; // Random component as bigint
}
`Migration Guide
$3
`javascript
// Before (UUID v4)
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // "f47ac10b-58cc-4372-a567-0e02b2c3d479"// After (Simpleflake)
import { simpleflake } from 'simpleflakes';
const id = simpleflake().toString(36); // "w68acyhy50hc" (shorter!)
`$3
`javascript
// Simpleflake is backwards compatible with Snowflake structure
// Just different bit allocation:
// - Snowflake: 41 bits timestamp + 10 bits machine + 12 bits sequence
// - Simpleflake: 41 bits timestamp + 23 bits random
//
// *double-check epoch
`Comparison
$3
| Library | Size | Time-ordered | Performance |
|---------|------|--------------|-------------|
| Simpleflake | 64-bit | ✅ Yes | ⚡ 8.8M/sec |
| UUID v4 | 128-bit | ❌ No | 🔸 ~2M/sec |
| UUID v7 | 128-bit | ✅ Yes | 🔸 ~2M/sec |
| Nanoid | Variable | ❌ No | ⚡ ~5M/sec |
| KSUID | 160-bit | ✅ Yes | 🔸 ~1M/sec |
| Twitter Snowflake | 64-bit | ✅ Yes | ⚡ ~10M/sec |$3
| Library | Dependencies | Database-friendly | URL-friendly | Distributed |
|---------|--------------|-------------------|--------------|-------------|
| Simpleflake | ✅ Zero | ✅ Integer | ✅ Base36 | ✅ Yes |
| UUID v4 | ❌ crypto | ❌ String | ❌ Long hex | ✅ Yes |
| UUID v7 | ❌ crypto | ❌ String | ❌ Long hex | ✅ Yes |
| Nanoid | ✅ Zero | ❌ String | ✅ Custom | ✅ Yes |
| KSUID | ❌ crypto | ❌ String | ✅ Base62 | ✅ Yes |
| Twitter Snowflake | ❌ System clock | ✅ Integer | ✅ Base36 | ⚠️ Needs config |Contributing
1. Fork the repository
2. Create your feature branch (
git checkout -b feature/amazing-feature)
3. Commit your changes (git commit -m 'Add amazing feature')
4. Push to the branch (git push origin feature/amazing-feature`)---
- Original concept by Mali Akmanalp
- TypeScript port and optimizations by Leo Dutra
- Inspired by Twitter Snowflake
[npm-badge]: https://img.shields.io/npm/v/simpleflakes.svg?style=flat
[coveralls-badge]: https://img.shields.io/coveralls/leodutra/simpleflakes.svg?style=flat
[npm-link]: https://www.npmjs.com/package/simpleflakes
[coveralls-link]: https://coveralls.io/github/leodutra/simpleflakes
