
UUIDv7 was inspired by ULID. Like ULID, it is a 128-bit identifier, containing a timestamp on the left side and random data on the right side. In databases and distributed systems, a properly implemented UUIDv7 is always preferred over any other identifier type, including natural keys, autoincrement, UUIDv4, TypeID, ULID, KSUID, CUID, NanoID, and Snowflake ID.
There are notable distinctions of UUIDv7:
RFC 9562 establishes many reasonable requirements for UUIDv7 in its various sections, such as mandatory usage of a cryptographically secure pseudorandom number generator (CSPRNG). However, you need to ensure that the implementation you use satisfies these requirements in your target deployment environment
There are various field and bit layout options in different implementations designed to provide monotonicity (increasing order of generation) within a millisecond, including cases when the system clock is rolled back. For example, UUIDv7 may contain a randomly initialized counter (in some programming languages) (with the leftmost bit optionally zeroed), or a timestamp-based counter (in PostgreSQL), or both. Minor violations of monotonicity do not affect performance but may complicate debugging, pagination, log searching, and the use of time series in databases
Additionally, a mutex (in ClickHouse) or a sub-millisecond timestamp segment (in PostgreSQL, in MariaDB) may be used to ensure monotonicity when the generation rate in parallel processes is high. Server-side generation ensures better monotonicity compared to client-side generation
Extracting and using the timestamp from UUIDv7 is not recommended. Consider explicit timestamp columns. However, both the timestamp extracted from UUIDv7 and the entire UUIDv7 can be used as a partitioning key in a database
The option of shifting timestamp value by any technically feasible range (in PostgreSQL, in Percona Server for MySQL) allows you to hide the true date of record creation, prevents lock contention during parallel generation of UUIDs in several processes, and also ensures monotonicity while generation on remote clients
UUIDv7 uses the widely compatible “hex-and-dash” string format, but RFC 9562 does not prohibit UUIDv7 from using the more readable, compact, and easily copied Crockford’s Base32, as in ULID
UUIDv7 should be stored in 128-bit binary format in databases whenever possible. It reduces storage overhead by 30–40% compared to string representations, while maintaining index efficiency
Identifiers containing UUIDs used as keys may be right-extended beyond 128 bits with any metadata and checksum
UUIDv7 contains a 4-bit version (7) field (0b0111) and a 2-bit variant field (0b10)
UUIDv7 and bigint demonstrate equivalent search and write performance confirmed by benchmarks. The rate of UUIDv7 generation is always sufficient and does not affect the performance of databases.
Although UUIDv7 is twice as long as a bigint, the difference in actual disk space used is much smaller. Besides, using UUID instead of bigint eliminates the need for intermediate tables and data layers.
UUIDv7, with the same performance, eliminates the following shortcomings of auto-increment:
The need to generate new keys and synchronize them with keys from the data source when exporting and importing data, or when generating records in parallel by multiple processes
Difficulty preventing key collisions when merging data from different database tables
Possible errors due to key collisions when merging data
Disclosure of the total number of records in a database table
Ease of brute-forcing valid keys
Impossibility of global search
You can use UUIDv7 in the same column where other versions of UUID (or ULID in binary format) are already used.