Scanning database...
Tools
Articles

No matches found for ""

View All Results
Home Dev Lab rust
Developer Lab

UUID in Rust

Production-ready implementation guide with CSPRNG-backed code snippets.



Generate UUID in Rust

The uuid crate on crates.io is the Rust standard — CSPRNG-backed, zero unsafe, no_std compatible, and serde-ready. Uuid::new_v4() in one line.

Quick Reference

Function Version Sortable Use Case
Uuid::new_v4() v4 No General purpose — session IDs, record IDs, API keys
Uuid::now_v7() v7 Yes Database PKs, event logs — time-ordered, B-tree friendly
Uuid::new_v5() v5 No Deterministic — same namespace + name always gives same UUID
Uuid::parse_str() any Parse and validate an existing UUID string

Primary Implementation

Production Ready
rust snippet
use uuid::Uuid;

fn main() {
    // UUID v4 — random, CSPRNG-backed via getrandom crate
    let id = Uuid::new_v4();
    println!("{}", id);
    // → f47ac10b-58cc-4372-a567-0e02b2c3d479

    // As a hyphenated string
    let id_str = id.to_string();

    // As a simple (no-hyphen) string
    let id_simple = id.simple().to_string();
    // → f47ac10b58cc4372a5670e02b2c3d479

    // As raw bytes (16 bytes, stack-allocated)
    let id_bytes: [u8; 16] = *id.as_bytes();

    // Parse and validate an existing UUID string
    match Uuid::parse_str("f47ac10b-58cc-4372-a567-0e02b2c3d479") {
        Ok(parsed) => println!("Version: {:?}", parsed.get_version()),
        Err(e)     => eprintln!("Invalid UUID: {}", e),
    }

    // Generate multiple UUIDs
    let ids: Vec = (0..5).map(|_| Uuid::new_v4()).collect();
}

All UUID Versions

UUID v4 — Random (recommended default)

rust snippet
// Cargo.toml: uuid = { version = "1", features = ["v4"] }
use uuid::Uuid;

let id = Uuid::new_v4();
println!("{}", id); // → "550e8400-e29b-41d4-a716-446655440000"

UUID v7 — Time-ordered (database PKs)

rust snippet
// Cargo.toml: uuid = { version = "1", features = ["v7"] }
use uuid::Uuid;

// Millisecond-precision timestamp prefix + random suffix
// IDs generated later always sort after earlier ones
let id = Uuid::now_v7();
println!("{}", id); // → "018e8f6a-1b2c-7d3e-9f4a-5b6c7d8e9f0a"

UUID v5 — Deterministic / Namespace-based

rust snippet
// Cargo.toml: uuid = { version = "1", features = ["v5"] }
use uuid::Uuid;

// SHA-1 hash of namespace + name — same inputs always produce the same UUID
let id = Uuid::new_v5(&Uuid::NAMESPACE_DNS, b"example.com");
println!("{}", id); // → always "cfbff0d1-9375-5685-968c-48ce8b15ae17"

// Custom namespace for your application
let my_ns = Uuid::new_v4(); // generate once, store as a constant
let record_id = Uuid::new_v5(&my_ns, b"user:42");

UUID v3 — MD5 Namespace (legacy)

rust snippet
// Cargo.toml: uuid = { version = "1", features = ["v3"] }
use uuid::Uuid;

// MD5-based — prefer v5 (SHA-1) for new code
let id = Uuid::new_v3(&Uuid::NAMESPACE_DNS, b"example.com");
println!("{}", id);

Real-World Use Cases

1. Axum web handler — request tracing ID

rust snippet
use axum::{middleware::Next, response::Response, http::Request};
use uuid::Uuid;

// Axum middleware that injects a request ID into every response
pub async fn request_id_middleware<B>(
    mut req: Request<B>,
    next: Next<B>,
) -> Response {
    let request_id = Uuid::new_v4().to_string();
    req.headers_mut().insert(
        "x-request-id",
        request_id.parse().unwrap(),
    );
    let mut response = next.run(req).await;
    response.headers_mut().insert(
        "x-request-id",
        request_id.parse().unwrap(),
    );
    response
}

2. sqlx — UUID primary key in PostgreSQL

rust snippet
use sqlx::PgPool;
use uuid::Uuid;
use serde::{Deserialize, Serialize};

// Cargo.toml: uuid = { version = "1", features = ["v4", "serde"] }
#[derive(Debug, Serialize, Deserialize)]
struct User {
    id: Uuid,   // Store as Uuid type, not String
    name: String,
}

async fn create_user(pool: &PgPool, name: &str) -> Result<User, sqlx::Error> {
    let user = sqlx::query_as!(
        User,
        "INSERT INTO users (id, name) VALUES ($1, $2) RETURNING id, name",
        Uuid::new_v4(),
        name
    )
    .fetch_one(pool)
    .await?;
    Ok(user)
}

3. Event sourcing — deterministic event IDs

rust snippet
use uuid::Uuid;

const EVENT_NAMESPACE: Uuid = Uuid::from_bytes([
    0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
    0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
]);

// Idempotent: same event always gets the same UUID
fn event_id(source: &str, event_type: &str, timestamp: &str) -> Uuid {
    let key = format!("{}:{}:{}", source, event_type, timestamp);
    Uuid::new_v5(&EVENT_NAMESPACE, key.as_bytes())
}

fn main() {
    let id1 = event_id("payments", "charge.created", "2026-05-01T12:00:00Z");
    let id2 = event_id("payments", "charge.created", "2026-05-01T12:00:00Z");
    assert_eq!(id1, id2); // always true — safe to retry
}

Common Mistakes

Forgetting to enable the right Cargo features

The uuid crate ships with no features enabled by default. Calling Uuid::new_v4() without features = ["v4"] in Cargo.toml is a compile error. Enable exactly what you need: ["v4", "v7", "serde"].

Storing UUIDs as String instead of Uuid

The Uuid type is a 16-byte stack-allocated value. Storing it as a String (36 bytes + heap allocation) wastes memory and loses type safety. Pass Uuid around and only call .to_string() at the boundary.

Using UUID v1 in web services

UUID v1 embeds the server's MAC address and a timestamp, leaking network topology and making IDs predictable. Use v4 for random IDs or v7 for time-ordered IDs in web services.

How It Works

The uuid crate delegates entropy to the getrandom crate, which calls the OS CSPRNG directly — /dev/urandom on Linux/macOS and BCryptGenRandom on Windows. No userspace RNG state is maintained.

The Uuid type is a newtype wrapper around [u8; 16] — a 16-byte value type stored entirely on the stack. Zero heap allocation, zero unsafe code in the public API.

With the serde feature, Uuid automatically serializes to a hyphenated string in JSON and deserializes back, with validation included.

Output Formats

id.to_string() / format!("{}", id)

f47ac10b-58cc-4372-a567-0e02b2c3d479

id.simple().to_string()

f47ac10b58cc4372a5670e02b2c3d479

id.as_bytes() — [u8; 16]

[0xf4, 0x7a, 0xc1, 0x0b, ...]

id.as_u128()

324716517733474852975027497220825710713

Best Practices

Store and pass Uuid values — only convert to string at API/DB boundaries.

Enable the serde feature for automatic JSON serialization with validation.

Use Uuid::now_v7() for database primary keys — sequential inserts avoid B-tree fragmentation.

Performance

Rust generates roughly 10–50 million UUIDs/second on modern hardware. The Uuid type is stack-allocated (16 bytes), so there is zero heap allocation per UUID.

The crate is no_std compatible with the getrandom feature, making it suitable for embedded targets.

Installation

# Cargo.toml
[dependencies]
uuid = { version = "1", features = ["v4", "v7", "serde"] }

The uuid crate is on crates.io. Enable only the features you need to keep compile times minimal.

Security

Entropy source: getrandom crate → OS CSPRNG (/dev/urandom on Linux/macOS, BCryptGenRandom on Windows). Cryptographically secure.

The uuid crate contains zero unsafe code in its public API. Suitable for session tokens, CSRF tokens, and security-sensitive IDs.