UUIDs are good identifiers. They are not magic security blankets. A UUID can reduce casual guessing, but authorization still belongs on the server, and secrets should be generated as real tokens.
Key takeaways
- A UUID identifies a resource; it does not authorize access.
- UUID v4 avoids timestamp leakage, while UUID v7 reveals approximate creation time.
- Use dedicated tokens for login links, API keys and password resets.
Identifier vs secret
An identifier names something. A secret proves something. UUIDs are excellent names for records, events and objects, but they should not be the only thing standing between a user and private data.
If a request asks for /invoice/{uuid}, the server still needs to check that the signed-in user can view that invoice.
When UUIDs help privacy
UUIDs can be better than sequential IDs in public URLs because they do not reveal how many records exist or make enumeration easy. That is useful for support tickets, shared resources and customer-facing APIs.
This benefit is not the same as access control. It is defense against casual discovery, not proof of permission.
Version-specific privacy notes
UUID v4 is random and does not encode creation time. UUID v7 is time-ordered, which means someone who sees the value may infer roughly when it was created. Classic UUID v1 can carry more historical metadata concerns, especially if node information is not randomized.
Pick the version based on what the ID will reveal, not just what is trendy.
Safer token pattern
For reset links, invite links and API keys, generate a dedicated random token with enough entropy, store a hashed version where appropriate, set expiration, and verify it server-side. A UUID field can still identify the row, but the token should authorize the action.
Good split:
id: 6aa07c51-07e2-4a83-a2b1-8613b510f8f9
token: separate high-entropy secret with expiration