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 địnhidentity-team
Thay thế

Bối cảnh

  • Flow 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ử (lockout sau 5 lần thử)
    • Cooldown 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à: TTL qua cleanup kiểu cron, lock khi tăng counter, bloat bảng từ hàng triệu bản ghi đã hết hạn.

Quyết định

Toàn bộ trạng thái OTP runtime nằm trong Redis với namespace key:

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}60sCooldown 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 cleanupFlow OTP sập cứng nếu Redis down
INCR atomic cho counterState là ephemeral — mất khi Redis flush
Đọc dưới mili-giâyHash mã làm tăng CPU mỗi lần verify
Không bloat bảng PostgreSQLAudit trail của các lần thử OTP không được lưu

Chế độ thất bạ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 hữu vẫn hoạt động (cache nằm phía sister)
  • Token OTP đã phát trước đó vẫn xác minh được nếu 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 cleanup cronAudit trailLock contention trên counter; latency của cleanup; bloatSai trade-off
Chỉ trong-bộ-nhớ (per-instance)Nhanh nhấtKhông sống sót qua restart; không scale ra N podVận hành mong manh
Hybrid (ghi DB + cache Redis)Audit + tốc độPhối hợp double-writePhức tạp không đáng

Tham chiếu

  • BaseOTPBasedMFAService (lớp cơ sở abstract)
  • EmailOtpService, PhoneOtpService (cụ thể)
  • BindingKeys.APPLICATION_REDIS_BULLMQ

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