Guide

What is a TNID?

A TNID (Typed Named ID) is a unique identifier that includes a human-readable type name. Instead of seeing d6157329-4640-8e30-8012-3456789abcde in your logs or database, you see user.Br2flcNDfF6LYICnT and immediately know it's a user ID.

Why TNIDs?

Benefits over plain UUIDs:

Two Formats, Same ID

Every TNID can be represented in two string formats:

TNID Format
user.Br2flcNDfF6LYICnT

Human-readable. Use in logs, URLs, APIs, and anywhere humans might see it.

UUID Format
d6157329-4640-8e30-8012-3456789abcde

Standard format. Use with existing UUID tooling and libraries that expect this format.

These are the same 128 bits — convert freely between them. Store as a string (either format) or as binary (UUID/u128 columns).

Choosing a Name

The name is the type prefix (e.g., user in user.Br2flcNDfF6LYICnT).

Rules:

Examples:

Variants

TNIDs have a 2-bit variant field, allowing 4 variants:

V0 (Time-ordered)

Like UUIDv7: contains a millisecond timestamp. IDs sort chronologically.

Use when: You want to sort by creation time.

V1 (Random)

Like UUIDv4: 100 bits of random entropy. Maximum unpredictability.

Use when: You don't need chronological sorting.

V2 and V3 are reserved for future use.

When in doubt, use V0. Time-ordering is usually helpful.

Type Safety

In languages that support it, the type system prevents mixing different TNID types. This catches bugs at compile time:

const userId: UserId = UserId.new_v0();
const postId: PostId = PostId.new_v0();

getUser(userId);  // OK
getUser(postId);  // Compile error!

The compiler catches the bug before your code runs. No more accidentally passing a post ID to a user lookup.

Quick Example

TypeScript

import { Tnid, TnidType } from "@tnid/core";

// Define your ID type
const UserId = Tnid("user");
type UserId = TnidType<typeof UserId>;

// Generate IDs
const id: UserId = UserId.new_v0();
console.log(id);  // "user.Br2flcNDfF6LYICnT"

// Convert to UUID for database storage
const uuid = UserId.toUuidString(id);
// "d6157329-4640-8e30-8012-3456789abcde"

// Parse from string
const parsed = UserId.parse("user.Br2flcNDfF6LYICnT");

Rust

use tnid::Tnid;

// Define your ID type
type UserId = Tnid<"user">;

// Generate IDs
let id: UserId = UserId::new_v0();
println!("{}", id);  // "user.Br2flcNDfF6LYICnT"

// Convert to UUID
let uuid = id.to_uuid();

// Parse from string
let parsed: UserId = "user.Br2flcNDfF6LYICnT".parse()?;

See all implementations →