RustConf 2025 took place in Montreal, Canada on September 12–13, 2025, bringing together systems programmers, library authors, and infrastructure engineers from across the Rust community.

Several sessions addressing database-backed Rust services converged on UUID v7 as the default choice for primary keys. The core argument: UUID v4 from the uuid crate is trivially available and cryptographically strong, but its random distribution fragments B-tree indexes at scale. UUID v7, standardized in RFC 9562, adds a millisecond timestamp prefix that keeps inserts sequential in the index. The full API is documented on docs.rs/uuid, including the v7 feature flag and timestamp context types.

The uuid crate’s v7 support has stabilized significantly since its introduction, and talks noted that the ergonomics are now comparable to v4:

use uuid::{Uuid, Timestamp, NoContext};

// UUID v4 — random
let v4 = Uuid::new_v4();

// UUID v7 — time-sortable
let ts = Timestamp::now(NoContext);
let v7 = Uuid::new_v7(ts);

println!("{}", v7); // 018fbe3a-4c5d-7b12-8abc-0123456789ab

Monotonic counters in high-throughput Rust services

One session focused specifically on UUID v7 generation in services emitting thousands of IDs per millisecond. Without a monotonic counter, multiple IDs generated within the same millisecond share the same timestamp bits and differ only in random bits — their sort order relative to each other is non-deterministic.

RFC 9562 §6.2 recommends a per-process monotonic counter that increments within a millisecond and resets when the clock advances. The uuid crate provides this through the ClockSequence trait:

use std::sync::atomic::{AtomicU64, Ordering};
use uuid::{ClockSequence, Timestamp};

struct MonotonicContext(AtomicU64);

impl ClockSequence for MonotonicContext {
    type Output = u16;
    fn generate_sequence(&self, _: u64, _: u32) -> Self::Output {
        self.0.fetch_add(1, Ordering::Relaxed) as u16
    }
    fn usable_bits() -> usize { 12 }
}

// Shared across all UUID generation in a process
static CONTEXT: MonotonicContext = MonotonicContext(AtomicU64::new(0));

This guarantees that even same-millisecond UUIDs sort in generation order — important for audit logs and event-sourced systems. The uuid crate’s Timestamp documentation covers the full context API.

SQLx and SeaORM integration

Database sessions covered UUID v7 integration with sqlx and SeaORM. Both ORMs use the uuid::Uuid type for UUID columns, so UUID v7 values require no additional configuration:

// sqlx — PostgreSQL with uuid column
let id = Uuid::new_v7(Timestamp::now(NoContext));

let row = sqlx::query!(
    "INSERT INTO orders (id, total_cents) VALUES ($1, $2) RETURNING id",
    id,
    total_cents
)
.fetch_one(&pool)
.await?;
// SeaORM entity with UUID v7
use sea_orm::entity::prelude::*;
use uuid::{Uuid, Timestamp, NoContext};

#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "orders")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: Uuid,
    pub total_cents: i32,
}

impl ActiveModelBehavior for ActiveModel {
    fn new() -> Self {
        Self {
            id: Set(Uuid::new_v7(Timestamp::now(NoContext))),
            ..ActiveModelTrait::default()
        }
    }
}

Serde serialization

UUID v7 serializes and deserializes identically to v4 via serde when the uuid crate’s serde feature is enabled:

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

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

External references

Frequently asked questions

Does the Rust uuid crate support UUID v7?

Yes. The uuid crate (version 1.6+) supports UUID v7 generation with the v7 feature flag. Enable it in Cargo.toml with uuid = { version = "1", features = ["v7"] }. UUID v7 requires a timestamp context — pass Timestamp::now(NoContext) or implement a custom context with a monotonic counter.

How does UUID v7 compare to other distributed ID schemes in Rust?

UUID v7 is RFC-standardised, 128 bits, and compatible with any UUID column type. Alternatives like ULID (ulid crate) offer the same chronological sort but use Base32 encoding (26 chars vs 36). Snowflake IDs require a coordination layer to assign node IDs. For most Rust services storing data in PostgreSQL or MySQL, UUID v7 is the lowest-friction choice.

Can I use UUID v7 with SQLx in Rust?

Yes. The sqlx crate supports the uuid crate's Uuid type natively via the uuid feature flag. PostgreSQL's uuid column maps directly to uuid::Uuid — UUID v7 values encode and decode identically to v4.