CUID2 জেনারেটর
নিরাপদ পরবর্তী প্রজন্মের CUID2 আইডেন্টিফায়ার তৈরি করুন
তৈরি করা CUID2
What is CUID2?
CUID2 (Collision-resistant Unique ID, version 2) is the next-generation successor to CUID v1, designed to generate short, cryptographically secure, opaque IDs that are safe to use as primary keys in databases, URLs, and distributed systems.
Unlike its predecessor, CUID2 reveals no information about the time of creation, the host machine, or the process that generated it. Every ID is a seemingly random string that starts with a random lowercase letter followed by a base-36 hash derived from SHA-512. The default length is 24 characters, but you can configure it anywhere from 2 to 32 characters to suit your storage constraints.
CUID2 is widely recommended by modern database toolkits. Prisma adopted it as the default ID strategy for its @default(cuid()) scalar, and PlanetScale, Neon, and other serverless database providers explicitly list CUID2 as a preferred ID format because it avoids the sequential-scan vulnerabilities of auto-increment integers while being shorter and more readable than a UUID.
Why CUID2 Replaced CUID v1
CUID v1, released in 2012 by Eric Elliott, was a major improvement over plain UUIDs for client-side ID generation. However, security researchers discovered two fundamental problems with its design:
- Fingerprinting: The host fingerprint embedded in every CUID v1 value could be used to identify the machine or process that generated the ID, leaking operational metadata to anyone who could observe the IDs.
- Predictability: Because CUID v1 incorporated a monotonically increasing counter and a timestamp segment, an attacker who observed several IDs could predict the approximate range of future IDs, enabling enumeration attacks against APIs that use IDs as the sole authorization check.
- Non-cryptographic hash: CUID v1 used a simple non-cryptographic hashing step that did not meet modern security standards.
Eric Elliott, the original author, formally deprecated CUID v1 and authored CUID2 from scratch to address all of these issues. The new algorithm uses the Web Crypto API (SHA-512) and eliminates all deterministic components, making each ID statistically independent of every other.
CUID2 Design Principles
CUID2 vs CUID v1 — Comparison
The table below summarises the key differences between CUID2 and the now-deprecated CUID v1. If you are currently using CUID v1, migrating to CUID2 is strongly recommended.
| Attribute | CUID2 | CUID v1 |
|---|---|---|
| Security | Cryptographic (SHA-512) | Non-cryptographic (fingerprint-based) |
| Predictability | Opaque — no leaked metadata | Timestamp + fingerprint visible in ID |
| Length | Configurable (2–32 chars) | Fixed 25 chars |
| Prefix | Random a–z letter | Always starts with "c" |
| Distribution | Flat / uniform | Monotonically increasing segments |
| Status | Actively maintained | Deprecated by original author |
CUID2 vs UUID v4 — Comparison
UUID v4 is the dominant standard for random unique IDs. CUID2 offers several practical advantages over UUID v4 without sacrificing security.
| Attribute | CUID2 | UUID v4 |
|---|---|---|
| Default length | 24 characters | 36 characters (with hyphens) |
| URL-safe | Yes — lowercase a–z + 0–9 | Requires encoding (contains hyphens) |
| Custom length | Yes (2–32) | No — always 128 bits / 36 chars |
| Sortable | No (by design) | No (v4 is random) |
| Entropy source | SHA-512 + Web Crypto | CSPRNG |
| Character set | Base-36 (a–z, 0–9) | Hex + hyphens |
The main trade-off is familiarity: UUID v4 is an IETF standard (RFC 4122) recognised by virtually every database, programming language, and API framework out of the box. CUID2 is a community standard with growing but not universal support. Choose UUID v4 when interoperability with external systems is paramount; choose CUID2 when you control both ends and prefer shorter, URL-safe IDs.
Who Uses CUID2
CUID2 has seen rapid adoption across the modern JavaScript and TypeScript ecosystem:
- Prisma — the most popular TypeScript ORM uses CUID2 as the recommended default for
@idfields with@default(cuid())in Prisma Schema v2+. - PlanetScale — their documentation and starter templates recommend CUID2 for application-generated primary keys to avoid sequential scan performance issues on their distributed MySQL platform.
- Drizzle ORM — provides a built-in
cuid2()default helper for column definitions. - tRPC boilerplates — many community tRPC + Prisma starter templates ship with CUID2 as the primary key strategy.
- T3 Stack — the create-t3-app scaffolding tool uses Prisma with CUID2 defaults in generated schema files.
Code Examples
The official @paralleldrive/cuid2 npm package provides a simple API:
import { createId } from '@paralleldrive/cuid2'
// Generate a single CUID2 (default length: 24)
const id = createId()
console.log(id) // e.g. "tz4a98xxat96iws9zmbrgj3a"
// Custom length
import { init } from '@paralleldrive/cuid2'
const createShortId = init({ length: 16 })
const shortId = createShortId()
console.log(shortId) // e.g. "tz4a98xxat96iws9"Using CUID2 with Prisma schema:
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Generating CUID2 in Node.js without the npm package (using only Web Crypto API, as this tool does in the browser):
async function generateCuid2(length = 24) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
// Random prefix letter
const firstByte = crypto.getRandomValues(new Uint8Array(1))[0]
const firstChar = alphabet[firstByte % 26]
// Random 32-byte salt
const salt = crypto.getRandomValues(new Uint8Array(32))
const saltHex = [...salt].map(b => b.toString(16).padStart(2, '0')).join('')
// SHA-512 of timestamp + salt
const input = Date.now().toString(36) + saltHex
const hashBuffer = await crypto.subtle.digest(
'SHA-512',
new TextEncoder().encode(input)
)
// Encode hash bytes as base-36 string
const bytes = new Uint8Array(hashBuffer)
let hash = ''
for (let i = 0; i < bytes.length; i += 8) {
let chunk = 0n
for (let j = 0; j < 8 && i + j < bytes.length; j++) {
chunk = (chunk << 8n) | BigInt(bytes[i + j])
}
hash += chunk.toString(36)
}
return (firstChar + hash).slice(0, length)
}
// Usage
const id = await generateCuid2()
console.log(id) // e.g. "m7k3r9p2nxq8zt5a6cwj4bvd"