TL;DR: The
uuidcrate provides theUuidtype for generating and parsing UUIDs. UseUuid::new_v4()for random UUIDs (the standard choice) orUuid::now_v7()for time-ordered UUIDs (better for database index performance). Enable theserdefeature for JSON serialization and thev4feature for generation. TheUuidtype integrates directly withsqlxforUUIDdatabase columns.
How Do You Generate a UUID?
Enable the right features in Cargo.toml, then call Uuid::new_v4() for random or Uuid::now_v7() for time-ordered.
[dependencies]
uuid = { version = "1", features = ["v4", "v7", "serde"] }use uuid::Uuid;
fn main() {
// UUID v4; random, most common
let id = Uuid::new_v4();
println!("{id}"); // e.g. 550e8400-e29b-41d4-a716-446655440000
// UUID v7; time-ordered (better for DB indexes)
let id_v7 = Uuid::now_v7();
println!("{id_v7}");
// Different string formats
println!("{}", id.hyphenated()); // 550e8400-e29b-41d4-a716-446655440000
println!("{}", id.simple()); // 550e8400e29b41d4a716446655440000
println!("{}", id.urn()); // urn:uuid:550e8400-e29b-41d4-a716-446655440000
// As bytes
let bytes: [u8; 16] = *id.as_bytes();
}How Do You Parse and Validate UUIDs?
Use Uuid::parse_str() or the FromStr trait; both return Result and validate the format.
use uuid::Uuid;
use std::str::FromStr;
fn main() {
// Parse from standard hyphenated format
let id = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
// From string trait
let id2: Uuid = "550e8400-e29b-41d4-a716-446655440000".parse().unwrap();
// Handle invalid input gracefully
match Uuid::parse_str("not-a-uuid") {
Ok(id) => println!("valid: {id}"),
Err(e) => println!("invalid: {e}"),
}
// Nil UUID (all zeros)
let nil = Uuid::nil();
println!("is nil: {}", nil.is_nil()); // true
}How Does uuid Work With serde?
Enable the serde feature; Uuid will serialize as a hyphenated string in JSON and deserialize from any valid UUID format.
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize)]
struct User {
id: Uuid,
name: String,
}
fn main() {
let user = User {
id: Uuid::new_v4(),
name: "Alice".to_string(),
};
let json = serde_json::to_string(&user).unwrap();
println!("{json}");
// {"id":"550e8400-e29b-41d4-a716-446655440000","name":"Alice"}
let back: User = serde_json::from_str(&json).unwrap();
println!("{back:?}");
}How Does uuid Work With sqlx?
Enable sqlx's uuid feature; Uuid maps directly to PostgreSQL's UUID column type.
[dependencies]
sqlx = { version = "0.8", features = ["postgres", "uuid"] }
uuid = { version = "1", features = ["v4"] }use sqlx::PgPool;
use uuid::Uuid;
struct User {
id: Uuid,
name: String,
}
async fn get_user(pool: &PgPool, id: Uuid) -> sqlx::Result<Option<User>> {
sqlx::query_as!(
User,
"SELECT id, name FROM users WHERE id = $1",
id
)
.fetch_optional(pool)
.await
}
async fn create_user(pool: &PgPool, name: &str) -> sqlx::Result<Uuid> {
let id = Uuid::new_v4();
sqlx::query_scalar!(
"INSERT INTO users (id, name) VALUES ($1, $2) RETURNING id",
id,
name
)
.fetch_one(pool)
.await
}UUID v4 vs v7; Which Should You Use?
v4 is the default (fully random). v7 is time-ordered; generates sequential UUIDs that are better for database B-tree index performance.
| UUID v4 | UUID v7 | |
|---|---|---|
| Randomness | Fully random | Time prefix + random |
| Sortable | ❌ | ✅ (by creation time) |
| DB index performance | Poor (random inserts) | Good (sequential inserts) |
| Privacy | High (no time info) | Lower (timestamp embedded) |
| Availability | features = ["v4"] | features = ["v7"] |
For new systems with PostgreSQL: prefer v7. For compatibility with existing systems expecting v4: stay with v4.
Frequently Asked Questions
Both are common. UUIDs work better for distributed systems (no central counter), merging data from multiple sources, and hiding record count from users. Auto-increment integers are simpler and have better sequential index performance (unless using UUID v7).
Yes; Uuid implements Copy, Clone, PartialEq, Eq, Hash, Ord, and Display. It's a 16-byte value stored on the stack.
Uuid::nil() is all zeros: 00000000-0000-0000-0000-000000000000. Often used as a sentinel value or default. uuid.is_nil() checks for it.
Enable Diesel's uuid feature. The uuid::Uuid type maps to Diesel's Uuid SQL type on PostgreSQL. Add diesel = { features = ["uuid"] } and uuid = { features = ["v4"] } to Cargo.toml.
Sources
- uuid crate documentation: API reference and feature flags
- uuid GitHub
- RFC 9562; UUID specification: Including UUID v7
Related Glossary Terms
- Serde: UUID serializes as a string in JSON via the
serdefeature - SQLx: sqlx maps PostgreSQL
UUIDcolumns touuid::Uuid - Diesel: Diesel also supports
uuid::Uuidvia itsuuidfeature - Rand: UUID v4 generation depends on random number generation
Keep Reading
- Rust on AWS Lambda: UUID generation for serverless resource identifiers
- Learn Rust in 2026: uuid is one of the most-reached-for crates in backend projects

