Why Macro Uses UUIDv7 for IDs: Time-Ordered Distributed Identifiers

Macro uses UUIDv7 because it embeds millisecond-precision timestamps into globally unique identifiers, enabling lexicographical sorting while eliminating coordination overhead in distributed services.

The macro-inc/macro codebase generates identifiers for users, messages, documents, and events using UUIDv7 via the internal macro_uuid crate. This architectural decision provides built-in temporal ordering without sacrificing the uniqueness guarantees required by a microservices architecture.

What Is UUIDv7 and Why It Matters

UUIDv7 is the latest RFC 4122-compatible format that structures the 128-bit identifier with a Unix timestamp in the most significant bits followed by random data. Unlike UUIDv4, which is entirely random, or UUIDv1, which leaks MAC addresses, UUIDv7 offers monotonic, sortable IDs that embed creation time directly into the identifier itself.

In the Macro codebase, generation is centralized through Uuid::now_v7(), a method provided by the uuid crate and wrapped by macro_uuid. This single function call appears in virtually every service that creates new records, ensuring consistency across the platform.

Architectural Benefits in Macro

Lexicographic Sorting and Query Performance

Because UUIDv7 places the timestamp in the high-order bits, generated IDs sort naturally by creation time when compared lexicographically. Macro leverages this to eliminate the need for separate created_at fields in time-series queries. For example, retrieving recent messages requires only ordering by the primary key:

// services/email_service/src/pubsub/inbox_sync/operations/upsert_message.rs
let thread_id = Uuid::now_v7(); // L606

This design reduces index width in PostgreSQL and improves cache locality, as inserts append to the rightmost edge of B-tree indexes rather than causing random page splits.

Distributed Generation Without Coordination

Macro services run across numerous containers and serverless functions. UUIDv7 allows each node to generate globally unique identifiers locally without contacting a central ID service or database sequence. In tooling/notification_sandbox/src/main.rs, the sandbox environment generates IDs at lines 301-307 using:

let entity_id = Uuid::now_v7().to_string();

This pattern appears throughout authentication flows ([services/authentication_service/src/api/oauth2/microsoft/test.rs](https://github.com/macro-inc/macro/blob/main/services/authentication_service/src/api/oauth2/microsoft/test.rs#L65)), realtime event processing ([crates/soup_realtime/src/inbound/kafka_consumer/test.rs](https://github.com/macro-inc/macro/blob/main/crates/soup_realtime/src/inbound/kafka_consumer/test.rs#L149)), and scheduled job repositories ([services/scheduled_action/src/outbound/pg_scheduled_action_repo.rs](https://github.com/macro-inc/macro/blob/main/services/scheduled_action/src/outbound/pg_scheduled_action_repo.rs)).

Embedded Timestamps for Observability

Developers can determine when an entity was created by inspecting the UUIDv7 itself, speeding up debugging and log correlation. The millisecond-precision timestamp encoded in the ID provides immediate temporal context without database lookups, which proves invaluable when tracing requests across distributed services.

Implementation in the Macro Codebase

The macro_uuid crate wraps the standard uuid crate to expose Uuid::now_v7() uniformly. Here is how Macro services typically generate and store these identifiers:

use macro_uuid::Uuid;

// Generating a new message ID
let message_id = Uuid::now_v7();

// Inserting into PostgreSQL
sqlx::query(
    "INSERT INTO messages (id, content) VALUES ($1, $2)"
)
.bind(message_id)
.bind("Hello, world!")
.execute(&pool)
.await?;

When querying recent data, Macro leverages the sortable nature:

// Fetching the 20 most recent messages
// No separate created_at column needed in ORDER BY
let recent_messages = sqlx::query_as::<_, Message>(
    "SELECT * FROM messages ORDER BY id DESC LIMIT 20"
)
.fetch_all(&pool)
.await?;

Database Performance and Indexing

Macro stores all UUIDv7 values as the native PostgreSQL uuid type (16 bytes). The time-ordered nature of UUIDv7 provides specific performance advantages:

  1. Sequential Writes – New records append to the end of the index, minimizing page splits and write amplification.
  2. Reduced Column Count – Queries ordered by creation time use the primary key directly, eliminating the need for composite indexes on (id, created_at).
  3. Cache Efficiency – Recent data clusters together in index pages, improving buffer cache hit ratios for hot datasets.

Summary

  • UUIDv7 embeds millisecond timestamps in the most significant bits, creating sortable, unique identifiers.
  • Macro generates IDs via Uuid::now_v7() from the macro_uuid crate, ensuring consistency across services.
  • Lexicographical sorting eliminates the need for separate created_at fields in time-based queries.
  • Distributed generation removes central coordination bottlenecks, fitting Macro's microservices architecture.
  • The design improves PostgreSQL index performance through sequential insert patterns.

Frequently Asked Questions

What is the difference between UUIDv4 and UUIDv7?

UUIDv4 contains entirely random data, providing uniqueness but no ordering guarantees. UUIDv7 replaces the random high-order bits with a Unix timestamp, creating identifiers that are both unique and chronologically sortable. Macro uses UUIDv7 specifically to enable efficient range queries and natural ordering without additional database indexes.

Does UUIDv7 compromise uniqueness for the timestamp?

No. UUIDv7 retains 74 bits of random data in the lower portions of the identifier after the 48-bit timestamp. This provides sufficient entropy to prevent collisions even when multiple IDs are generated within the same millisecond across distributed nodes. Macro's architecture relies on this cryptographic randomness combined with the time component.

How does Macro handle UUIDv7 in PostgreSQL?

Macro stores UUIDv7 as the native uuid column type, which PostgreSQL handles as a 128-bit value. Because the timestamp occupies the high-order bits, standard SQL ordering operators (ORDER BY id DESC) naturally return results in creation-time sequence. The database treats these identically to UUIDv4 for storage purposes but benefits from improved index locality during inserts.

Can UUIDv7 IDs be predicted or reversed?

The timestamp portion of UUIDv7 is not encrypted and can be extracted from the identifier, revealing the approximate creation time (to the millisecond). However, the embedded random bits prevent prediction of future IDs. Macro accepts this trade-off because the creation time is typically non-sensitive data, while the observability benefits outweigh the minor information leakage.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →