How can I generate a unique ID in Python?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Generating identifiers sounds simple until you need the IDs to stay unique across processes, machines, or time. In Python, the right approach depends on what you need: randomness, reproducibility, readability, or database friendliness.
Choosing the Right Kind of Identifier
There is no single best format for every system. A good ID strategy starts with the use case.
- Use
uuid.uuid4()when you want a practically unique random identifier. - Use a database auto-increment column when a local integer key is enough.
- Use hashes when the same input should always produce the same ID.
- Use timestamps only when collisions are controlled carefully.
For many applications, Python's uuid module is the safest default.
Using UUIDs in Python
The uuid module is built into the standard library. The most common option is version 4, which is based on random bytes.
This produces values such as 2c02d4f2-8f5c-4c5c-a021-8f1623ee3f90. The object can be stored directly in some systems, but many applications convert it to a string before serialization.
If you need the raw hexadecimal form without dashes, use hex.
That is often convenient for URLs, filenames, or log correlation IDs.
Deterministic IDs with Hashing
Sometimes randomness is not what you want. If the same input should always map to the same identifier, hashing is a better fit.
This does not guarantee universal uniqueness, but strong hash functions make accidental collisions extremely unlikely for normal applications. Deterministic IDs are useful when you want idempotent imports or stable cache keys.
Be careful not to confuse hashing with secrecy. A hash of predictable input can still be guessed.
Simple Incrementing IDs
For small single-process programs, a counter may be enough.
This is easy to understand, but it only works safely when one process owns the sequence. If multiple workers run at once, you need a shared store such as a database sequence or Redis counter.
Timestamp-Based IDs
Timestamps can be useful when you want IDs that sort by creation time.
This is compact and sortable, but not automatically collision-free. Two calls can happen so close together that collisions become possible, especially across machines. Many systems combine a timestamp with randomness.
That hybrid format is common in event systems and operational tooling.
Practical Recommendations
If you are unsure, start with uuid.uuid4() and keep the identifier opaque. Opaque IDs are easier to change later because other parts of the system do not depend on embedded meaning.
If storage size matters, decide whether you want the canonical string form, the hex form, or raw bytes. Databases often store UUID values more efficiently in binary form than as long text strings.
Also think about how the ID will be exposed. A public API token, a database primary key, and a temporary filename may each need a different format even inside the same application.
Common Pitfalls
A common mistake is using random.randint() as if it guarantees uniqueness. It does not. It only produces values from a range, so collisions are inevitable once enough IDs are generated.
Another issue is relying on timestamps alone in concurrent systems. They may appear unique during testing but fail under load or across multiple hosts.
Developers also sometimes leak implementation details by encoding business meaning into IDs. For example, using an email address or sequential number in a public URL can expose information you did not intend to share.
Finally, avoid inventing a custom scheme unless you have a clear need. Standard UUIDs are boring in a good way: they are well understood, portable, and hard to misuse.
Summary
- '
uuid.uuid4()is the safest default for general-purpose unique IDs in Python.' - Use hashes when the same input must always produce the same identifier.
- Counters are fine for single-owner sequences but not for distributed generation.
- Timestamps alone are not enough when collisions matter.
- Keep IDs opaque unless the system truly benefits from embedded meaning.
- Choose a format that fits storage, sorting, and exposure requirements.

