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:
- Time-ordered - IDs generated later are numerically larger
- Distributed-safe - No coordination needed between multiple generators
- Compact - Fits in a 64-bit integer (vs UUID's 128 bits)
- 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
npm install simpleflakesconst { 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)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)// 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)
);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// 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`);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
This library is optimized for speed:
// Benchmark results (operations per second)
simpleflake() // ~8.8M+ ops/sec
parseSimpleflake() // ~3.9M+ ops/sec
binary() // ~26M+ ops/secPerfect for high-throughput applications requiring millions of IDs per second.
- 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
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
// Perfect for database IDs - time-ordered and unique
const userId = simpleflake();
await db.users.create({ id: userId.toString(), name: "John" });// Each service can generate IDs independently
const serviceAId = simpleflake(); // Service A
const serviceBId = simpleflake(); // Service B
// No coordination needed, guaranteed unique across services// Generate compact URL identifiers
const shortId = simpleflake().toString(36); // "w68acyhy50hc"
const url = `https://short.ly/${shortId}`;// Time-ordered event IDs for chronological processing
const eventId = simpleflake();
await analytics.track({ eventId, userId, action: "click" });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 numberepoch(number, optional): Epoch start time. Default:Date.UTC(2000, 0, 1)
Returns: BigInt - The generated ID
const id = simpleflake();
const customId = simpleflake(Date.now(), 12345, Date.UTC(2000, 0, 1));Parses a simpleflake ID into its components.
Parameters:
flake(bigint | string | number): The ID to parse
Returns: Object with timestamp and randomBits properties (both bigint)
const parsed = parseSimpleflake(4234673179811182512n);
console.log(parsed.timestamp); // "1693244847123"
console.log(parsed.randomBits); // "4567234"Converts a number to binary string representation.
Parameters:
value(bigint | string | number): Value to convertpadding(boolean, optional): Whether to pad to 64 bits. Default:true
Returns: String - Binary representation
console.log(binary(42n)); // "0000000000000000000000000000000000000000000000000000000000101010"
console.log(binary(42n, false)); // "101010"Extracts a portion of bits from a number.
Parameters:
data(bigint | string | number): Source datashift(bigint): Starting bit position (0-based from right)length(bigint): Number of bits to extract
Returns: BigInt - Extracted bits as number
const bits = extractBits(0b11110000n, 4n, 4n); // Extract 4 bits starting at position 4
console.log(bits); // 15n (0b1111)The epoch start time (January 1, 2000 UTC) as Unix timestamp.
import { SIMPLEFLAKE_EPOCH } from 'simpleflakes';
console.log(SIMPLEFLAKE_EPOCH); // 946684800000interface SimpleflakeStruct {
timestamp: bigint; // Unix timestamp as bigint (since 2000)
randomBits: bigint; // Random component as bigint
}// 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!)// 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| 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 |
| 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 |
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Original concept by Mali Akmanalp
- TypeScript port and optimizations by Leo Dutra
- Inspired by Twitter Snowflake