-
Notifications
You must be signed in to change notification settings - Fork 2
ID Comparison
Comprehensive comparison and decision guide for choosing the right ID generator for your use case.
- Feature Comparison Matrix
- Which ID Should I Use?
- Detailed Use Case Recommendations
- Performance
- Security Comparison
- Storage Size Comparison
- Decision Tree
- Real-World Examples
| Feature | NanoID | ObjectID | ULID | CUID | CUID2 | SequenceID | SimpleID |
|---|---|---|---|---|---|---|---|
| Default Length | 21 chars | 26 chars | 26 chars | 25 chars | 24 chars | 19 digits | 12-18 digits |
| Format | Base62-like | Mixed-radix | Base32 |
c + base36 |
Letter + base36 | BigInt | BigInt |
| Sortable | ❌ No | ✅ Yes | ❌ No (by design) | ✅ Yes | ✅ Yes | ||
| URL-Safe | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Cryptographic | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No | ❌ No | ||
| Customizable | ✅ High | ❌ Low | ❌ Fixed | ||||
| Timestamp Embedded | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Privacy-Preserving | ✅ Yes | ❌ Leaks time | ❌ Leaks time | ❌ Leaks time | ✅ Yes | ❌ Leaks time | ❌ Leaks time |
| Human-Readable | ❌ No | ✅ Yes | |||||
| Database-Friendly | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Excellent | ✅ Excellent |
| Distributed-Safe | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ||
| Sequential | ❌ No | ❌ No | ✅ Yes | ✅ Yes | |||
| Extract Timestamp | ❌ No | ✅ Yes | ✅ Yes | ❌ Not exposed | ❌ N/A | ✅ Yes | ✅ Yes |
| Collision Risk | Very Low | Very Low | Very Low | Very Low | Very Low | Very Low | Low |
| Generation Speed | ⚡ Fast | ⚡⚡ Very Fast | ⚡ Fast | ⚡ Fast | ⚡ Fast | ⚡⚡⚡ Fastest | ⚡⚡ Very Fast |
| Memory Usage | Low | Medium | Low | Low | Low | Very Low | Very Low |
- ✅ Yes: Fully supported
⚠️ Partial: Partially supported or with limitations- ❌ No: Not supported
- ⚡ Relative generation speed (more = faster) — for measured per-runtime numbers see Performance
┌─────────────────────────────────────────────┐
│ What's your primary requirement? │
└─────────────────────────────────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Compact │ │Database │ │Sortable │
│URLs │ │Primary │ │by Time │
└─────────┘ └─────────┘ └─────────┘
│ │ │
▼ ▼ ▼
NanoID SequenceID ULID
ObjectID
→ Use NanoID (21 chars, customizable, URL-safe)
// Short, clean URLs
https://app.com/p/g0b30yv24uuo0grjv→ Use SequenceID (64-bit BigInt, indexed efficiently)
// Excellent for auto-increment replacement
1234567890123456789n;→ Use ObjectID (MongoDB-style traceable IDs — stored as strings, not
the native 24-char hex ObjectId)
// Usable as a string _id field (26-char mixed-radix, not canonical hex)
'65a1b2c3019aB30c1f4q000001';→ Use ULID (sortable, timestamp-based, UUID-compatible)
// Time-ordered across multiple servers
'01ARZ3NDEKTSV4RRFFQ69G5FAV';→ Use SimpleID (date-based, easy to read)
// Invoice or order numbers
202412260001n;→ Use NanoID with custom alphabet (high entropy)
import { ALPHA_NUMERIC_CASE, nanoID } from '@tundralibs/id';
// 32-char alphanumeric token
nanoID(32, ALPHA_NUMERIC_CASE);→ Use SimpleID or SequenceID (minimal overhead)
→ Use ULID or ObjectID (no coordination needed)
Best For:
- Public-facing URLs and shortened links
- API endpoints requiring compact identifiers
- Client-side ID generation (browser-safe)
- Customizable ID formats (alphanumeric, numeric-only)
- External-facing identifiers in REST APIs
- Session identifiers and tracking tokens
- File uploads and temporary resource naming
Advantages:
- ✅ Compact size: 21 characters (vs 36 for UUID)
- ✅ URL-safe: No special encoding needed
- ✅ Customizable: Choose alphabet and length
- ✅ Cryptographically secure: Uses Web Crypto API
- ✅ Dependency-light: only the
@tundralibs/compatand@tundralibs/utilsworkspace siblings, no third-party runtime deps (CUID needs neither; nanoID/CUID2/ULID pull in only the shared@tundralibs/utilserror base) - ✅ Collision resistant: ~110 bits of entropy at the default 21-char length (21 × log2(38)); collisions are negligible at realistic volumes
Trade-offs:
- ❌ Not sortable by creation time
- ❌ No embedded timestamp
- ❌ Cannot extract creation metadata
Example Use Cases:
import { ALPHA_NUMERIC, nanoID, NUMBERS } from '@tundralibs/id';
// Short URLs
const shortUrl = nanoID(8);
// => "4f90d13a"
// https://app.com/s/4f90d13a
// File uploads
const fileId = nanoID(16);
// => "0gwamxlyi9c0udp2"
// uploads/0gwamxlyi9c0udp2.pdf
// Numeric tracking codes
const trackingCode = nanoID(12, NUMBERS);
// => "123456789012"
// API keys (high security)
const apiKey = nanoID(32, ALPHA_NUMERIC);
// => "4f90d13a42e5f83b7d12c3a8f9b2e6d1"When NOT to Use:
- Database primary keys requiring sort order
- Systems requiring timestamp extraction
- Sequential numbering requirements
Best For:
- MongoDB database primary keys
- Distributed systems with MongoDB
- Document-based databases
- Systems requiring embedded timestamp
- Applications needing machine/process identification
- Cross-platform MongoDB compatibility
Advantages:
- ✅ MongoDB-style layout: Usable as a string
_id(not the native 24-char hex) - ✅ Timestamp embedded: Extract creation time
- ✅ Distributed-safe: No coordination needed
- ✅ Machine/process identification: Traceable origin
- ✅ Incremental counter: Collision prevention
- ✅ Industry standard: Widely recognized format
Trade-offs:
⚠️ Only partially sortable (second precision)⚠️ Longer than NanoID (26 mixed-radix characters)⚠️ Traceable, not unguessable: timestamp, process ID, and counter are predictable — only the short worker/machine-ID segments are CSPRNG-backed. Never use it for tokens or secrets (see ObjectID docs)
Example Use Cases:
import { ObjectID } from '@tundralibs/id';
// Document IDs stored as strings (26-char mixed-radix, not canonical hex)
const genId = ObjectID();
const userId = genId();
// => "65a1b2c3019aB30c1f4q000001"
// Distributed system with machine identification
const serverGen = ObjectID(0, 'srv01');
const docId = serverGen();
// => "65a1b2c3019srv010c1f4q000001" (28 chars: 5-char machine ID)
// Microservices with process tracking
const processGen = ObjectID();
const eventId = processGen();
// => "65a1b2c3019aB30c1f4q000002"When NOT to Use:
- Non-MongoDB SQL databases (use SequenceID)
- Requiring millisecond-precision sorting
- Public-facing URLs (use NanoID)
- Human-readable requirements (use SimpleID)
Best For:
- Distributed systems requiring sort order
- Event logging and time-series data
- Microservices architectures
- Replace UUIDs with better sorting
- Multi-region deployments
- High-throughput event streams
- Replacing auto-increment in distributed databases
Advantages:
- ✅ Lexicographically sortable: Time-ordered
- ✅ UUID-compatible: 128-bit like UUID
- ✅ Millisecond precision: Accurate timestamps
- ✅ Monotonic variant: Guaranteed ordering
- ✅ Crockford Base32: No ambiguous characters
- ✅ 1.21e+24 unique IDs: Per millisecond
- ✅ Extract timestamp: Recoverable creation time
Trade-offs:
⚠️ Longer than NanoID (26 characters)⚠️ Not customizable (fixed format)⚠️ Slightly slower generation than SequenceID
Example Use Cases:
import { getTimestamp, monotonicUlid, ulid } from '@tundralibs/id';
// Event logging (sortable by time)
const eventId = ulid();
// => "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// Guaranteed ordering in same millisecond
const event1 = monotonicUlid();
const event2 = monotonicUlid();
// event2 > event1 always
// Time-series data
const dataPoints = Array.from({ length: 1000 }, () => ({
id: ulid(),
value: Math.random(),
}));
// Automatically sorted by creation time
// Extract creation timestamp
const id = ulid();
const createdAt = getTimestamp(id);
// => 1628000000000 (milliseconds)
// Distributed logs across regions
const logId = ulid();
// Maintains global time orderWhen NOT to Use:
- Need extreme compactness (use NanoID)
- Custom alphabet requirements
- Pure sequential integers (use SequenceID)
- Daily reset requirements (use SimpleID)
Best For:
- Migrations from ParallelDrive's original CUID convention.
- Process-local sortable identifiers that need a recognisable
cprefix. - Mixed-environment apps that benefit from a self-identifying ID format.
Advantages:
- ✅
cprefix: Self-identifying — distinguishes CUIDs from raw base36 strings. - ✅ Process-sortable: Timestamp + counter give in-process ordering for free.
- ✅ Compact: 25 chars, URL- and shell-safe.
- ✅ Cross-process disambiguation: Per-process fingerprint segment.
Example:
import { cuid } from '@tundralibs/id';
const userId = cuid();
// => 'clrwk6yt40001qz2ek6f7r2t1'When NOT to Use:
- The ID is shown to attackers and minting time must stay private → use CUID2.
- Need cross-machine sortability → use ULID.
- Need MongoDB-native IDs → use ObjectID.
Best For:
- Public-facing tokens (magic links, password reset, email verification).
- Privacy-sensitive IDs where the minting time must not leak.
- Anywhere CUID2's lack of timestamp removes a side-channel without costing you anything you actually need.
Advantages:
- ✅ No information leakage: No embedded timestamp, counter, or fingerprint.
- ✅ Cryptographically secure: Entire body sourced from
crypto.getRandomValues. - ✅ Configurable length: 24..32 chars to tune collision resistance.
- ✅ URL-safe: Lowercase alphanumeric only.
Example:
import { cuid2 } from '@tundralibs/id';
const resetToken = cuid2(32);
// => 'k3rj9xn8q1p7m2w5y6h4t8d9a2b3c4d5'When NOT to Use:
- You need sortability (use ULID or CUID).
- You need a fixed length that matches an existing schema (use NanoID with the exact length you want).
Best For:
- Database primary keys (auto-increment replacement, single-producer)
- High-performance SQL databases
- Sequential ordering requirements
- Indexed columns (B-tree friendly)
- Legacy system migration from auto-increment
Advantages:
- ✅ 64-bit BigInt: Native database support
- ✅ Sequential: Optimal for B-tree indexes
- ✅ Timestamp embedded: Extractable creation time
- ✅ Extremely fast: Minimal overhead
- ✅ Memory efficient: No string allocation
- ✅ Database-optimized: Integer indexing
Trade-offs:
⚠️ Caller singleton required: twosequenceID()instances in the same process at the same startup-second produce identical IDs. Instantiate once per logical sequence at module scope and share the returned function.⚠️ Limited cross-process safety: distinct processes are discriminated only by(PID % 256, startup_second). Two processes with colliding PID residue starting in the same second will produce overlapping IDs.⚠️ Not cryptographically secure: contents are predictable from server-state.⚠️ Less human-readable than SimpleID.
Example Use Cases:
import { sequenceID } from '@tundralibs/id';
// Create the generator ONCE per logical sequence at module scope.
const genUserId = sequenceID();
// Database primary keys
const userId = genUserId();
// => 1234567890123456789n
// Bulk insert reuses the same generator
const users = Array.from({ length: 10000 }, (_, i) => ({
id: genUserId(),
name: `User ${i}`,
}));When NOT to Use:
- Public URLs (use NanoID).
- Distributed deployments where multiple nodes may share
PID % 256(use ULID or ObjectID). - Workloads emitting more than ~16M IDs per startup-second per generator (use ULID).
- Anywhere unpredictability of the ID matters for security.
Best For:
- Invoice numbering systems
- Order numbers
- Daily sequential IDs
- Human-readable identifiers
- Date-traceable records
- Receipt numbers
- Ticket systems
- Reference numbers
Advantages:
- ✅ Human-readable: Date + counter format
- ✅ Date-based: YYYYMMDDNNNN structure
- ✅ Auto-reset: Counter resets daily
- ✅ Predictable: Sequential within day
- ✅ Simple: Minimal complexity
- ✅ Customizable: Configurable counter length
- ✅ Fastest: Minimal overhead
Trade-offs:
- ❌ Not suitable for distributed systems
- ❌ Limited uniqueness (daily counter)
- ❌ No cryptographic security
- ❌ Predictable sequence
Example Use Cases:
import { simpleID } from '@tundralibs/id';
// Invoice numbers
const invoiceGen = simpleID(0, 6);
const invoice = invoiceGen();
// => 20241226000001n
// Display: INV-2024-12-26-000001
// Order numbers
const orderGen = simpleID();
const orderId = orderGen();
// => 202412260001n
// Display: ORD-20241226-0001
// Daily ticket numbers
const ticketGen = simpleID();
const ticket1 = ticketGen(); // 202412260001n
const ticket2 = ticketGen(); // 202412260002n
// Resets at midnight
// Receipt numbers
const receiptGen = simpleID(0, 4);
const receiptId = receiptGen();
// => 202412260001n
// Reference tracking with microseconds
const preciseGen = simpleID(0, 4, true);
const refId = preciseGen();
// => 20241226123456789012nWhen NOT to Use:
- High-security requirements
- Distributed/multi-server systems
- Non-sequential requirements
- Public-facing identifiers
- Systems requiring cryptographic guarantees
All seven generators are fast — roughly 57 ns (sequenceID) to 1.5 µs
(nanoID(32) on Node) per ID — so generation is rarely a bottleneck next to
the I/O it usually accompanies. The relative ordering is stable across runtimes:
-
Counter / time-based (
sequenceID,ObjectID,simpleID) are the fastest. They touch no CSPRNG on the hot path, so their cost stays flat across Deno, Bun, and Node. -
CSPRNG-backed (
cuid2,ulid,nanoID,cuid) each draw fromcrypto.getRandomValuesonce per ID — a little slower, and most visible on Node, whose per-call crypto cost is the highest of the three runtimes.
For the measured per-generator numbers across all three runtimes — and the commands to reproduce them — see Performance.
| Generator | Entropy Source | Predictability | Brute Force Resistance | Recommended for Security |
|---|---|---|---|---|
| NanoID | Web Crypto API | Unpredictable | ⭐⭐⭐⭐⭐ Excellent | ✅ Yes |
| ULID | Crypto Random | Unpredictable | ⭐⭐⭐⭐⭐ Excellent | ✅ Yes |
| ObjectID | Crypto + Counter | Semi-predict | ⭐⭐⭐⭐ Very Good | |
| SequenceID | Time + ServerID + Counter | Semi-predict | ⭐⭐⭐ Good | |
| SimpleID | Sequential Counter | Predictable | ⭐ Poor | ❌ No |
// Use NanoID with maximum length
import { ALPHA_NUMERIC_CASE, nanoID } from '@tundralibs/id';
const apiKey = nanoID(32, ALPHA_NUMERIC_CASE);
// 62^32 = 2.27 x 10^57 combinationsRecommendations:
- ✅ NanoID (32+ characters)
- ✅ ULID (128-bit entropy)
- ❌ Never use SimpleID or SequenceID
import { nanoID, ulid } from '@tundralibs/id';
// NanoID or ULID work well
const sessionId = nanoID(); // 21 chars
const resourceId = ulid(); // 26 charsRecommendations:
- ✅ NanoID (default 21 chars)
- ✅ ULID
⚠️ ObjectID (acceptable)
import { sequenceID, simpleID } from '@tundralibs/id';
// Any generator is suitable
const userId = sequenceID()();
const orderId = simpleID()();Recommendations:
- ✅ All generators acceptable
- Choose based on performance/features
// nanoID — ~110 bits of entropy at the default 21-char WEB_SAFE length
// (21 × log2(38)); collision-free at any realistic volume.
// ulid — 80 bits of randomness per millisecond, plus the 48-bit timestamp.
// cuid2 — whole body from crypto.getRandomValues; length 24..32 tunes it.
// ObjectID — timestamp + machine/process/worker prefix + counter; the counter
// wraps at 1,000,000 within a millisecond.
// sequenceID — no collisions within one generator (monotonic counter). Across
// generators/processes, see its uniqueness caveats.
// simpleID — no collisions within one generator per day (daily counter).| Generator | String Length | Bytes (UTF-8) | Database VARCHAR Size |
|---|---|---|---|
| NanoID | 21 chars | 21 bytes | VARCHAR(21) |
| ObjectID | 26 chars | 26 bytes | VARCHAR(26) or BINARY |
| ULID | 26 chars | 26 bytes | VARCHAR(26) |
| SequenceID | 19 digits | 8 bytes | BIGINT |
| SimpleID | 12-18 digits | 8 bytes | BIGINT |
-- String-based IDs
CREATE TABLE users_nano (
id VARCHAR(21) PRIMARY KEY, -- 21 bytes + overhead
name VARCHAR(100)
);
CREATE TABLE users_ulid (
id VARCHAR(26) PRIMARY KEY, -- 26 bytes + overhead
name VARCHAR(100)
);
-- Integer-based IDs (most efficient)
CREATE TABLE users_seq (
id BIGINT PRIMARY KEY, -- 8 bytes, indexed efficiently
name VARCHAR(100)
);
-- Storage for 1M records:
-- NanoID: ~21 MB (id only)
-- ULID: ~26 MB (id only)
-- SequenceID: ~8 MB (id only)// ObjectID (native format)
{
_id: ObjectId("507f1f77bcf86cd799439011"), // 12 bytes (binary)
name: "John"
}
// String IDs
{
_id: "g0b30yv24uuo0grjvi6su", // 21 bytes + overhead
name: "John"
}
// Storage for 1M documents:
// ObjectID: ~12 MB (id only)
// NanoID: ~21 MB (id only)
// ULID: ~26 MB (id only)| Generator | Index Size (1M rows) | Index Fragmentation | Insertion Performance |
|---|---|---|---|
| SequenceID | ~8 MB | ⭐⭐⭐ Minimal | ⭐⭐⭐ Excellent |
| SimpleID | ~8 MB | ⭐⭐⭐ Minimal | ⭐⭐⭐ Excellent |
| ULID | ~26 MB | ⭐⭐ Low | ⭐⭐ Very Good |
| ObjectID | ~24 MB | ⭐⭐ Low | ⭐⭐ Very Good |
| NanoID | ~21 MB | ⭐ High | ⭐ Good |
Key Insight: Sequential IDs (SequenceID, SimpleID) have the smallest index footprint and best insertion performance due to B-tree efficiency.
START: Choose an ID Generator
│
├─ Question 1: Is this for a public-facing URL or API?
│ ├─ YES → Question 2: Do you need it to be very compact?
│ │ ├─ YES → Use NanoID (customizable length)
│ │ └─ NO → Use ULID (sortable + unique)
│ │
│ └─ NO → Question 3: What's your database?
│ ├─ MongoDB → Use ObjectID (native compatibility)
│ │
│ ├─ SQL Database → Question 4: Need time-based sorting?
│ │ ├─ YES → Question 5: Distributed system?
│ │ │ ├─ YES → Use ULID (distributed + sortable)
│ │ │ └─ NO → Use SequenceID (fastest + indexed)
│ │ │
│ │ └─ NO → Question 6: Human-readable needed?
│ │ ├─ YES → Use SimpleID (date-based)
│ │ └─ NO → Use SequenceID (performance)
│ │
│ └─ Other/NoSQL → Question 7: Need sorting by time?
│ ├─ YES → Use ULID (universal compatibility)
│ └─ NO → Use NanoID (compact + flexible)
┌─────────────────┐
│ Start: Choose │
│ ID Generator │
└────────┬────────┘
│
┌────────▼─────────┐
│ Public-facing │
│ URL or API? │
└────┬──────┬──────┘
YES │ │ NO
┌──────────┘ └──────────┐
│ │
┌────────▼─────────┐ ┌────────▼─────────┐
│ Need compact? │ │ Database type? │
└────┬──────┬──────┘ └────┬──────┬──────┘
YES │ │ NO Mongo│ │ SQL
┌───────┘ └────────┐ ┌─────┘ └─────┐
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌────────┐ ┌──────────┐
│ NanoID │ │ ULID │ │ObjectID│ │Sortable? │
│ 8-21ch │ │ Sortable│ │ Native │ └────┬─────┘
└─────────┘ └─────────┘ └────────┘ YES │ NO
┌──────┘ └────┐
▼ ▼
┌─────────┐ ┌──────────┐
│ ULID │ │SimpleID/ │
│Sequential│ │SequenceID│
└─────────┘ └──────────┘
- SimpleID (fastest)
- SequenceID
- NanoID
- ULID (millisecond precision)
- SequenceID (sequential)
- SimpleID (date-based)
- NanoID (customizable)
- SequenceID (8 bytes)
- ObjectID
- NanoID (32+ chars)
- ULID (128-bit)
- ObjectID
- SimpleID
- NanoID
- SequenceID
Requirement: Multi-tenant e-commerce with products, orders, and users.
import { nanoID, ObjectID, simpleID } from '@tundralibs/id';
// User IDs: string primary keys with an embedded timestamp
const userIdGen = ObjectID();
const userId = userIdGen();
// => "65a1b2c3019aB30c1f4q000001"
// Product SKUs: Short, URL-safe
const productSku = nanoID(10);
// => "ridvgi_4p7"
// URL: /products/ridvgi_4p7
// Order Numbers: Human-readable
const orderGen = simpleID(0, 6);
const orderNumber = orderGen();
// => 20241226000001n
// Display: ORD-2024-12-26-000001Requirement: Distributed logging, event tracking, and service-to-service communication.
import { ObjectID, ulid } from '@tundralibs/id';
// Request IDs: Sortable across services
const requestId = ulid();
// => "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// Maintains order across regions
// Event IDs: Monotonic ordering
import { monotonicUlid } from '@tundralibs/id';
const event1 = monotonicUlid();
const event2 = monotonicUlid();
// Guaranteed: event2 > event1
// Service Instance IDs
const serviceIdGen = ObjectID(0, 'api-gateway');
const instanceId = serviceIdGen();
// => "65a1b2c3019api-gateway0c1f4q000001" (34 chars: 11-char machine ID)Requirement: Multi-tenant platform with workspaces, projects, and tasks.
import { nanoID, sequenceID, ulid } from '@tundralibs/id';
// Workspace Slug: User-friendly URLs
const workspaceId = nanoID(8);
// => "4f90d13a"
// URL: app.com/w/4f90d13a
// Project IDs: Database primary keys
const projectIdGen = sequenceID();
const projectId = projectIdGen();
// => 1234567890123456789n
// Task IDs: Sortable by creation
const taskId = ulid();
// => "01ARZ3NDEKTSV4RRFFQ69G5FAV"Requirement: Secure API keys and session tokens.
import { ALPHA_NUMERIC_CASE, nanoID } from '@tundralibs/id';
// API Keys: High entropy
const apiKey = `sk_live_${nanoID(32, ALPHA_NUMERIC_CASE)}`;
// => "sk_live_<random 32-char ALPHA_NUMERIC_CASE nanoID>"
// Session Tokens: Standard length
const sessionToken = nanoID();
// => "g0b30yv24uuo0grjvi6su"
// Refresh Tokens: Maximum security
const refreshToken = nanoID(48, ALPHA_NUMERIC_CASE);
// => "4f90d13a42e5f83b7d12c3a8f9b2e6d1a5c7f8b9d0e1f2a3b4c5"Requirement: Articles, media assets, and revisions.
import { nanoID, ObjectID, ulid } from '@tundralibs/id';
// Article IDs: traceable string document IDs
const articleIdGen = ObjectID();
const articleId = articleIdGen();
// => "65a1b2c3019aB30c1f4q000001"
// Media Asset IDs: Short URLs
const assetId = nanoID(12);
// => "57lvfwtpxx9g"
// CDN URL: cdn.example.com/i/57lvfwtpxx9g.jpg
// Revision IDs: Sortable timeline
const revisionId = ulid();
// => "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// Automatically ordered by timeRequirement: Device registration, telemetry, and command tracking.
import { ObjectID, sequenceID, ulid } from '@tundralibs/id';
// Device IDs: Unique hardware identifiers
const deviceIdGen = ObjectID(0, 'factory-01');
const deviceId = deviceIdGen();
// => "65a1b2c3019factory-010c1f4q000001" (33 chars: 10-char machine ID)
// Telemetry Events: Time-ordered
const telemetryId = ulid();
// => "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// Command IDs: Sequential tracking
const commandSeq = sequenceID();
const commandId = commandSeq();
// => 1234567890123456789nRequirement: Transactions, invoices, and audit trails.
import { sequenceID, simpleID, ulid } from '@tundralibs/id';
// Transaction IDs: Sequential + traceable
const txnGen = sequenceID();
const transactionId = txnGen();
// => 1234567890123456789n
// Invoice Numbers: Human-readable
const invoiceGen = simpleID(0, 6);
const invoiceNumber = invoiceGen();
// => 20241226000001n
// Display: INV-2024-12-26-000001
// Audit Log IDs: Sortable + immutable
const auditId = ulid();
// => "01ARZ3NDEKTSV4RRFFQ69G5FAV"| Use Case | Recommended | Alternative | Avoid |
|---|---|---|---|
| Public URLs | NanoID | ULID | SimpleID |
| Database Primary Keys | SequenceID | ObjectID | SimpleID |
| MongoDB | ObjectID | ULID | - |
| Distributed Systems | ULID | ObjectID | SimpleID |
| Sequential Ordering | SequenceID | ULID | NanoID |
| Human-Readable | SimpleID | - | ULID |
| API Keys | NanoID (32+) | ULID | SimpleID |
| Event Logging | ULID | ObjectID | SimpleID |
| High Performance | SimpleID | SequenceID | - |
| Time-Series Data | ULID | SequenceID | NanoID |
Choose your ID generator based on your specific requirements:
- Compact & Flexible: NanoID
- MongoDB Native: ObjectID
- Sortable & Distributed: ULID
- High Performance: SequenceID
- Human-Readable: SimpleID
All generators are production-ready, well-tested, and optimized for their respective use cases.