Designing a Reactive, Event-Driven Email OTP Login System with CQRS and Event Sourcing
Modern authentication systems are moving beyond passwords. With the rise of passwordless authentication, One-Time Passwords (OTPs) delivered over email or SMS are becoming a trusted standard for secure and seamless user logins.
However, implementing an OTP-based login mechanism that is scalable, reactive, and audit-compliant requires more than a simple verification service. It demands an architecture that supports asynchronous workflows, event traceability, and reactive scalability — all while keeping the system maintainable and extendable.
In this post, we’ll walk through the conceptual design of a Reactive OTP Login System built using Spring Boot, CQRS (Command Query Responsibility Segregation), and Event Sourcing.
We’ll focus purely on the architecture and system flow — without diving into code — to illustrate how such a system achieves high throughput, clean separation of concerns, and full auditability.
Architectural Overview
At its core, this system adopts a Reactive CQRS + Event Sourcing design:
- Commands modify the system state (e.g., logging in a user).
- Queries fetch or compute data without altering state (e.g., generating OTP for a user).
- Events record every state transition as an immutable fact.
- Reactive Streams (Mono/Flux) ensure non-blocking, backpressure-aware execution.
Step 1: Requesting an Email OTP
The OTP generation process begins when a user initiates a login using their email.
Conceptual Flow
- The client sends a request to
/api/v1/user/request/emailloginotp/{email}. - The Query Controller constructs a
RequestEmailLoginOTPQuery, encapsulating the user’s email and tenant metadata. - The Query Dispatcher routes the query to the appropriate Query Handler.
- The Query Handler verifies whether the user exists and is active using a reactive repository.
- If valid, it invokes EmailLoginOTPService to generate a unique OTP.
- It then emits an EmailOTPSentEvent, which is published to Kafka for asynchronous notification delivery and audit tracking.
- The API responds with a confirmation that the OTP request was processed successfully.
Step 2: Validating the Email OTP (Login Process)
Once the user receives the OTP, they can authenticate using it.
Conceptual Flow
- The client submits a POST request to
/api/v1/user/validate/emailloginotpwithemailandotp. - The Command Controller validates the OTP through the EmailLoginOTPService.
- On success, it dispatches a LogInWithEmailOTPCommand to the Command Handler.
- The Command Handler performs several key actions:
- Rehydrates the user’s aggregate state from the Event Store.
- Raises a LoggedInWithEmailOTPEvent to represent successful login.
- Persists this event back to the Event Store.
- The Event Handler listens for the event, updating the read projection (user table) to reflect login status.
- The JWT Token Provider issues a new access token for the authenticated session.
- The client receives a success response along with the token.
Event Sourcing Lifecycle
Event Sourcing lies at the heart of this system.
Every change in user state — from OTP sent to login success — is captured as a domain event and stored immutably in the Event Store.
Conceptual Event Chain
| Sequence | Event Name | Description |
|---|---|---|
| 1 | EmailOTPSentEvent | OTP generated and dispatched via Kafka. |
| 2 | LoggedInWithEmailOTPEvent | User successfully logged in with the OTP. |
| 3 | AuditRecordedEvent | Login and OTP actions recorded for compliance. |
Replaying these events allows the system to rebuild state from history, ensuring full traceability and fault recovery without traditional database state dependencies.
Security and Compliance Considerations
Security is baked into every stage of the pipeline:
- OTP expiration, uniqueness, and rate limiting are handled by the
EmailLoginOTPService. - JWT tokens provide stateless, secure session management.
- Audit events ensure all critical actions are logged for compliance.
- Tenant-aware scoping enforces strict data isolation in multi-tenant setups.
By combining event logs with JWT-based access, the system achieves both security and observability.
Conclusion
Building an OTP-based authentication system using Reactive, CQRS, and Event Sourcing principles enables:
Scalable, non-blocking performance under heavy traffic
Strict auditability with event logs
Fault tolerance through event replay
Extensibility for future login channels or audit pipelines
Seamless user experience with real-time responsiveness
In essence, this architecture transforms a simple OTP mechanism into a production-grade authentication framework — one that is reactive by nature, event-driven by design, and compliant by default.