What is an OTP?
An OTP (One-Time Password) is a temporary code generated for user verification. It is commonly used for:
- Phone verification
- Email verification
- Password reset
- Two-Factor Authentication (2FA)
- Login verification
Since OTPs are only valid for a short period (usually 30 seconds to 10 minutes), they have different storage requirements than permanent user data.
Why Redis is Perfect for OTP Storage
Redis is an in-memory data store designed for speed and temporary data.
1. Extremely Fast
Redis stores data in RAM instead of reading from disk.
This means:
- Read operations happen in microseconds.
- Write operations are almost instantaneous.
- Perfect for authentication systems handling thousands of requests per second.
Example:
User requests OTP
↓
Store OTP in Redis
↓
User submits OTP
↓
Verify in Redis
↓
Delete OTP
The entire process is incredibly fast.
2. Built-in Expiration (TTL)
One of Redis's greatest features is automatic expiration.
Instead of manually deleting expired OTPs, simply set a TTL (Time To Live).
Example:
await redis.set(
`otp:${userId}`,
otp,
{
EX: 300 // expires after 5 minutes
}
);
After 5 minutes, Redis automatically removes the OTP.
No cron jobs.
No cleanup scripts.
No database maintenance.
3. Automatic Cleanup
Imagine sending one million OTPs daily.
If stored in a database, you'll accumulate one million new rows every day.
Soon you'll need:
- Cleanup scripts
- Scheduled jobs
- Additional indexing
- Storage optimization
Redis handles this automatically through expiration.
4. Better Performance Under Heavy Load
High-traffic applications constantly generate OTPs.
Examples include:
- Banking apps
- Ride-sharing platforms
- Food delivery services
- Social media
- E-commerce websites
Redis easily handles hundreds of thousands of operations per second.
Traditional databases become slower as tables grow.
5. Reduced Database Load
Databases should focus on storing long-term information:
- Users
- Orders
- Transactions
- Products
- Payments
OTPs are temporary.
Keeping them in Redis prevents unnecessary writes to your primary database.
Why Storing OTPs in a Database Isn't Ideal
Although storing OTPs in MySQL, PostgreSQL, or MongoDB works, it's usually not the best design.
Some drawbacks include:
Permanent Storage
Databases are designed for persistent data.
OTPs should disappear after a few minutes.
Extra Cleanup Required
You'll need scheduled jobs like:
DELETE FROM otp_codes WHERE expires_at < NOW();
This creates additional maintenance.
Increased Storage
Millions of expired OTPs consume storage unnecessarily.
Slower Queries
As the OTP table grows, searches become slower unless proper indexing is maintained.
Security Best Practices
Regardless of where OTPs are stored, follow these practices.
Hash OTPs
Instead of storing:
123456
Store:
SHA256(123456)
This prevents attackers from reading OTPs if Redis or the database is compromised.
Limit Verification Attempts
Allow only 3–5 attempts.
Example:
Attempt 1 ✅ Attempt 2 ✅ Attempt 3 ❌ Account temporarily blocked
Redis can easily track attempts with counters.
Use Short Expiration Times
Recommended TTL:
- Email OTP: 5–10 minutes
- SMS OTP: 2–5 minutes
- Login OTP: 30–120 seconds
Delete OTP After Success
Even if TTL hasn't expired, remove the OTP immediately after successful verification.
When Should You Use a Database?
A database is appropriate when you need:
- OTP audit logs
- Compliance records
- Analytics
- Historical verification reports
A common production architecture looks like this:
Redis │ ├── Active OTP ├── Retry Count ├── Rate Limit └── Auto Expire Database │ ├── Verification History ├── Audit Logs ├── Login Records └── Security Events
Redis handles active OTPs, while the database stores historical information.
Redis OTP Example (Node.js)
const otp = "834291";
await redis.set(
`otp:${userId}`,
otp,
{
EX: 300
}
);
const storedOtp = await redis.get(`otp:${userId}`);
if (storedOtp === otp) {
await redis.del(`otp:${userId}`);
}
This implementation is clean, efficient, and production-ready.
Final Recommendation
For almost every modern application, Redis is the best solution for storing OTPs. Its lightning-fast performance, built-in expiration, and automatic cleanup make it ideal for temporary authentication data.
Traditional databases are better suited for permanent records, while Redis excels at handling short-lived, high-speed data like OTPs.
If you're building a secure authentication system, the recommended architecture is simple:
- Store active OTPs in Redis
- Store verification history and audit logs in your database
- Hash OTPs before storing
- Use TTL for automatic expiration
- Delete OTPs immediately after successful verification
- Implement rate limiting and retry limits
By combining Redis with your primary database, you get the best balance of performance, scalability, security, and maintainability.
FAQ
Is Redis better than MongoDB for OTP storage?
-Yes. Redis is specifically designed for temporary, high-speed data with automatic expiration, making it a better choice for OTP storage than MongoDB.
Should I hash OTPs before storing them?
-Yes. Hashing OTPs adds an extra layer of security in case your storage system is compromised.
How long should an OTP remain valid?
-Most applications use 2–5 minutes for SMS OTPs and 5–10 minutes for email OTPs.
Can I use both Redis and a database?
-Absolutely. Store active OTPs in Redis and keep verification logs or audit history in your database. This is the architecture used by many production systems.



