How to generate a verification code/number?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
A verification code should be easy for a user to enter but hard for an attacker to guess. That means the problem is not just generating a random number; it also involves choosing the right entropy source, setting an expiration time, storing the code safely, and limiting retry attempts.
Use A Cryptographically Secure Random Source
For verification codes, avoid ordinary pseudo-random generators intended for simulation or games. In Python, the simplest secure choice is secrets.
This generates a six-digit numeric code using a cryptographically suitable random source.
If you want an alphanumeric code with ambiguous characters removed, define an explicit alphabet.
This avoids confusing characters such as 0, O, I, and 1.
Numeric Codes Versus Alphanumeric Codes
A numeric six-digit code is common because it is easy to type, especially on mobile keyboards. The tradeoff is the smaller search space.
A few practical options are:
- 6-digit numeric for SMS or email verification
- 8-digit numeric when you want more guessing resistance
- 6 to 8 character alphanumeric when user entry conditions allow it
The right choice depends on your attack model and user experience requirements.
Expiration And Attempt Limits Matter As Much As Randomness
A well-generated code is still weak if it never expires or can be guessed indefinitely.
A typical verification flow should include:
- code expiration, for example 5 to 10 minutes
- a small attempt limit per code
- rate limiting per account, phone number, email, or IP address
- invalidation immediately after successful use
Without those rules, even a strong random code becomes much easier to brute-force.
Store A Hash, Not The Plain Code
If your application stores verification codes server-side, store a hash rather than the raw code whenever practical. That way, a database leak does not immediately expose every active code.
Then compare the hash of the submitted code instead of comparing raw strings stored in the database.
For short-lived OTP-style codes, hashing is not a complete defense by itself, but it is still a sound storage practice.
A Minimal End-To-End Example
This example generates a code record and validates a submitted value.
This keeps the example runnable while showing expiration and attempt tracking.
Do Not Confuse Random Codes With TOTP
If you want authenticator-app style one-time codes, that is usually a TOTP problem rather than a "generate a random code and store it" problem. TOTP systems derive time-based codes from a shared secret and current time window.
So there are two common architectures:
- server-generated random code stored temporarily and delivered by SMS or email
- TOTP code derived independently by both client and server from a shared secret
Do not mix them casually. They solve related but different verification flows.
Delivery Security Still Matters
Even a perfectly generated code is only as secure as its delivery channel. Email and SMS are common, but each has real security limitations.
That means code generation is only one part of the design. Account recovery rules, session binding, and anti-abuse controls matter just as much.
Common Pitfalls
- Using
random.randintinstead of a cryptographically secure source. - Storing the raw verification code in the database without need.
- Forgetting expiration and attempt limits.
- Choosing a code length based only on convenience and not on brute-force risk.
- Treating SMS or email delivery as if it were inherently secure enough to ignore the rest of the system design.
Summary
- Use a cryptographically secure random source such as Python's
secrets. - Pick a code format that balances usability and guessing resistance.
- Expire codes quickly and limit retry attempts.
- Prefer storing a hash instead of the raw code.
- Distinguish between server-generated random codes and TOTP-based verification flows.
Related reading
- How to generate access token for an AWS Cognito user?
- How to generate an MD5 checksum of a file?
- How to get active user's UserDetails
- How to get bearer token from header of a request in java spring boot?
- How to get kafka offset with Kafka SSL&ACL
- How to get Python requests to trust a self signed SSL certificate?
- How to get token from service account?
- How to handle HTTP OPTIONS requests in Spring Boot?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.