Skip to content

ADR-0004. Trạng thái OTP trong Redis (theo TTL), không lưu PostgreSQL

TrườngGiá trị
Trạng tháiAccepted
Ngày2026-02-12
Người quyết địnhPhat Nguyen
Thay thế-

Bối cảnh

  • Luồng OTP có trạng thái tạm thời với ngữ nghĩa TTL chặt chẽ:
    • Mã đã hash (TTL 10 phút)
    • Bộ đếm số lần thử (khoá sau 5 lần thử)
    • Thời gian chờ sau mỗi lần gửi (60s)
    • Bộ đếm hạn ngạch hàng ngày
  • Lưu trong PostgreSQL nghĩa là: dọn dẹp TTL kiểu cron, khoá khi tăng bộ đếm, bảng phình to vì hàng triệu bản ghi đã hết hạn.

Quyết định

Toàn bộ trạng thái OTP lúc chạy nằm trong Redis với key được phân vùng tên:

KeyTTLMục đích
{ns}:otp:{identifier}5-15 phútMã đã hash
{ns}:lock:{identifier}10-15 phútKhoá tài khoản
{ns}:session:{token}1-24 giờToken phiên đã xác thực
{ns}:cooldown:{identifier}60sThời gian chờ gửi lại
{ns}:daily:{identifier}24 giờHạn ngạch hàng ngày

Namespaces: verify-email, verify-phone, forgot-password, phone-auth, add-phone, add-email.

Mã được hash bằng Bun.password trước khi lưu.

Hệ quả

ƯuNhược
Hết hạn theo TTL - không cần job dọn dẹpLuồng OTP hỏng hoàn toàn nếu Redis ngừng hoạt động
INCR liền mạch cho bộ đếmTrạng thái chỉ tạm thời - mất khi xoá sạch Redis
Đọc dưới mili-giâyHash mã làm tăng CPU mỗi lần xác minh
Không phình bảng PostgreSQLDấu vết kiểm toán các lần thử OTP không được lưu

Tình huống lỗi

Nếu Redis không khả dụng:

  • Yêu cầu OTP mới trả về 503 Service Unavailable
  • Việc xác minh JWT hiện có vẫn hoạt động (cache nằm phía service anh em)
  • Token OTP đã phát trước đó vẫn xác minh được nếu được cache phía client, nhưng xác minh phía server thất bại

Phương án đã xem xét

Phương ánƯuNhượcLý do từ chối
PostgreSQL với dọn dẹp cronDấu vết kiểm toánTranh chấp khoá trên bộ đếm; độ trễ khi dọn dẹp; phình bảngSai đánh đổi
Chỉ trong bộ nhớ (mỗi instance)Nhanh nhấtKhông sống sót qua lần khởi động lại; không mở rộng ra N podVận hành mong manh
Lai (ghi DB + cache Redis)Kiểm toán + tốc độPhối hợp ghi képPhức tạp không đáng

Tham chiếu

  • BaseOTPBasedMFAService (lớp cơ sở trừu tượng)
  • EmailOtpService, PhoneOtpService (lớp cụ thể)
  • BindingKeys.APPLICATION_REDIS_BULLMQ

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.