Four requirements
State four requirements explicitly, because each classic solution fails a different one.
Your identifiers must be unique across every machine, with no duplicates ever. They should sort roughly by time, so ordering by identifier approximates ordering by creation, which hands you free pagination cursors and index locality.
They should be compact, ideally 64 bits, because they become primary keys and foreign keys and parts of addresses, by the billion. And generating one must need no coordination, so a machine mints tens of thousands a second locally without a single network call.
Score the database counter first. It aces three of those and fails distribution, because one sequence lives on one machine, which makes it a single point of failure and a ceiling on writes a second, and any multi-writer setup forks it.
Keep it for a single-database app, and abandon it the day you shard.
Why the obvious answers fail
Score the random identifier next, which fails sortability, and understand that the damage is physical, not aesthetic.
A random 128-bit key inserts at a random position in your index, so under load every insert touches a different page. Your working set becomes the whole index, page splits multiply, and your buffer pool thrashes.
Compare sequential keys, which append to the same rightmost pages. Benchmarks routinely show random keys inserting several times slower once the index outgrows memory, and 128 bits doubles the storage of every key besides.
Note the newer variant standardised in 2024, which puts a timestamp at the front and fixes the locality problem while keeping the 128-bit weight.
Score a bare timestamp last, which fails uniqueness. Two machines in the same millisecond collide, and a busy machine needs thousands of identifiers per millisecond regardless.
Read what that leaves you: keep the timestamp for sortability, then pack in just enough extra bits to make simultaneous generation safe. That packing is the next lesson.
Worked example
A marketplace team splits their monolith's orders into a service with 4 shards of Postgres, a relational database, and each shard keeps its own auto-increment starting at 1. Orders 1, 2, 3 now exist four times, one per shard, and the collision surfaces in the warehouse system, which uses order ID as its key and starts merging different customers' orders into one box. Emergency fix: offset each shard's sequence (shard 2 starts at 2 with increment 4, the old Flickr trick), which stops collisions but breaks ordering, since shard load determines which IDs get minted fast. Pagination by ID starts interleaving old and new orders. Dmitri, the tech lead, concludes they have been paying down one missing decision for a month, and the team adopts a 64-bit time-based scheme so IDs are unique and sortable regardless of which shard writes them.