Rust’s systems-programming focus makes identifier generation performance a first-class concern. The uuid crate provides zero-overhead UUID v4 and v7 generation, and both Diesel and SQLx support the Uuid type natively for PostgreSQL and MySQL backends.

Setting Up the uuid Crate

# Cargo.toml
[dependencies]
uuid = { version = "1", features = ["v4", "v7", "serde"] }
FeatureEnables
v4Uuid::new_v4() — random UUID
v7Uuid::now_v7() — time-ordered UUID
serdeSerialize / Deserialize for JSON and binary formats
fast-rngFaster RNG (still cryptographically adequate for v4)

Generating UUIDs

use uuid::Uuid;

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

let v7 = Uuid::now_v7();
println!("{v7}"); // 018fbe3a-4c5d-7000-8abc-0123456789ab

Uuid::now_v7() reads std::time::SystemTime::now() for the 48-bit millisecond timestamp and fills the remaining 74 bits with randomness from the OS CSPRNG. Monotonic counter behaviour within a single millisecond is not implemented by default — if within-millisecond ordering matters, use Uuid::new_v7(Timestamp) with a manually managed counter.

Diesel Integration

Diesel’s PostgreSQL backend maps uuid::Uuid to the uuid column type:

[dependencies]
diesel = { version = "2", features = ["postgres", "uuid"] }
uuid = { version = "1", features = ["v7"] }

Schema (generated by diesel migration):

CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    customer_id UUID NOT NULL,
    status VARCHAR NOT NULL
);

Rust model:

use diesel::prelude::*;
use uuid::Uuid;

#[derive(Queryable, Selectable)]
#[diesel(table_name = crate::schema::orders)]
pub struct Order {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub status: String,
}

#[derive(Insertable)]
#[diesel(table_name = crate::schema::orders)]
pub struct NewOrder {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub status: String,
}

fn create_order(conn: &mut PgConnection, customer_id: Uuid) -> QueryResult<Order> {
    let new = NewOrder {
        id: Uuid::now_v7(),
        customer_id,
        status: "pending".into(),
    };
    diesel::insert_into(orders::table)
        .values(&new)
        .get_result(conn)
}

SQLx Integration

SQLx maps uuid::Uuid to PostgreSQL’s uuid type via the PgHasArrayType and Encode/Decode traits:

[dependencies]
sqlx = { version = "0.8", features = ["postgres", "uuid", "runtime-tokio-rustls"] }
uuid = { version = "1", features = ["v7"] }
use sqlx::PgPool;
use uuid::Uuid;

async fn create_order(pool: &PgPool, customer_id: Uuid) -> sqlx::Result<Uuid> {
    let id = Uuid::now_v7();
    sqlx::query!(
        "INSERT INTO orders (id, customer_id, status) VALUES ($1, $2, 'pending')",
        id,
        customer_id,
    )
    .execute(pool)
    .await?;
    Ok(id)
}

Serde JSON Serialization

With the serde feature, Uuid serializes to the standard hyphenated string:

use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Serialize, Deserialize)]
struct OrderResponse {
    id: Uuid,    // serializes as "018fbe3a-4c5d-7000-8abc-0123456789ab"
    status: String,
}

For compact binary protocols (MessagePack, CBOR), use uuid::serde::compact to serialize as 16 raw bytes instead of the 36-byte string.

Choosing v4 vs v7

Use caseVersion
PostgreSQL / MySQL primary keyv7 — index-friendly sequential inserts
External API identifier (URL, token)v4 — creation time not leaked
Distributed trace / correlation IDv7 — sortable across services
Idempotency keyv4 — must be unguessable
In-memory cache keyEither — no database index involved

Frequently asked questions

How do I generate UUID v7 in Rust?

Use the uuid crate with the v7 feature: uuid = { version = "1", features = ["v7"] }. Then call Uuid::now_v7(). For Diesel or SQLx integration, also enable the uuid feature on those crates — they map Uuid to the PostgreSQL uuid column type automatically.

Do UUIDs hurt database index performance?

UUID v4 does — its randomness causes every insert to land at a different leaf page, leading to page splits and poor cache locality. UUID v7 embeds a millisecond timestamp so consecutive inserts cluster together, behaving like an auto-increment integer for B-tree purposes.

Should I use v4 or v7?

Use v7 for database primary keys (time-sortable, index-friendly) and v4 for anything where creation order could leak information, like tokens or share links.

How do I generate a UUID v7 in Rust?

Add the uuid crate with the v7 feature: uuid = { version = "1", features = ["v7"] }. Then call Uuid::now_v7(). The crate reads the system clock via SystemTime::now() and fills the remaining 74 bits with CSPRNG randomness.

Does Diesel support UUID primary keys in Rust?

Yes. Enable the uuid feature on the diesel crate: diesel = { version = "2", features = ["postgres", "uuid"] }. Diesel maps uuid::Uuid to PostgreSQL's native uuid column type automatically. No custom type mapping or conversion is needed.