System Design: Design a register API
6 min readThis post is from my series of system design for beginners. In the last blog, we learned about what is API. Now, we will implement all our learning to solve a system design problem (HLD = High Level Deisgn).
This is going to be a long read. So, here is a TOC to help you jump on the section of your interest.
TOC
1 . Problem
3 . Functional and Non-Functional Requirements
4 . HLD
5 . API Design
6 . Security
7 . Scalaibility
8 . Fault tolrance
9 . Logs/monitoring
10 . Trade-offs
11 . CAP
tldr: This blog walks through the design of a register API as part of a system design series for beginners. It covers everything from problem scoping and functional requirements to API structure, database schema, security measures, scalability, fault tolerance, and trade-offs.
Problem:
Design a register API.
Let's start
As an engineer, you will be tempted to solve the problem as soon as possible. However, to be a good engineer, break the problem, think about edge cases, think about what is missing in the problem? Remember, system design problems are high level and one line. As an engineer it is your job
1 . to make the scope small via asking questions
2 . to find out this missin use cases
3 . to think about edge cases and so on.
In short, always ask follow-up questions.
Follow-up Questions:
-
Do I need to cover the login, and auth flow?
No
-
How the registration confirmation would be? Form, SSO, OTP, email confirmation?
Email
-
How many users are we expecting?
Assume Meta, Amazon, etc Scale
-
What will happen when a user registers with an alerady registered email?
Show the error of duplication
Functional and non-functional Requirements
Functional Requirements
-
user can regiseter using name, email, and password
-
duplicate email should be handle gracefully
Non-functional requirements
-
Secure
-
scalable
-
Logs and metrics
-
Perfomant
HLD
I am from UI background, I prefer to do the UI flow first to undrstand and explain how the flow would be. For someone who is not from UI background they can do a rough sketch (ignore form details, or UI elements, etc).
After UI, I move to the HLD:
API design
For me this is the low hanging fruit as well as this is the base of this register API. As what data we are going to save.
ACTION: POST
API Endpoint: /auth/v1/register
{ name: string, email: string, password: (SALT + hashing)}
Response: 200 { message: "", description: ""}
Response: 4xx { message: "", description: ""}
Schema design
Users | |
---|---|
name | string |
string | |
password | Bcrypt/SALT + hashing |
id | UUID / AUTO_INCREMENT |
status | "pending" |
created_at | timestamp |
email confirmations | |
---|---|
id | id |
token | hash(token) |
token_expiry | timestamp |
status | "pending" |
created_at | timestamp |
updated_at | timestamp |
Confirmation email
Instead of saving confirmation email in the DB we will create email links on the fly using a service.
The benefits of this approach:
1 . We are saving space in the database
2 . As these are the short live links then we don't have to worry about cleaning the database later.
Password Storage
It is a bad practise to save the password as plain text in the database. This would be a security vulnerbitlity. Infact we should be storing the enrypted password.
For this I will use BCrypt for password encryption.
1 . It is a hashing password hashing function.
2 . it will encrypt the password to store securely in the DB.
PS: Do not use reversible encryption or store plain text passwords.
So far we have understood the design, and different components. Now, we will get into building a system - secrure, scalable, fault tolrant, and obserbility:
Security
Building a secure system is crucial. We have different components in our design which would be vulnerable for attacks. We already saw that password storage was one of those.
However, there are different components too. So, here is how we can secure our system:
1 . Rate Limiting: API /register should have rate limit eg. 6 req/min per IP
2 . Captcha or honeypot field: Add captcha or honeypot field to block spam or bots.
3 . Logs/Monitoring: Logs all the requests and moniotor them.
4 . Validation windown for tokens: have expiring window with tokens
5 . Private components: DB will be hosted in private and Services - email confirmation, cleaning service etc.
Scalability
To handle the traffic of the application, we need to take care of scalability of the design. This will help us in handle huge spike and as well as handling faults too (we will cover faults in the next section).
1 . The DB is write heavy
.
2 . we wil have single leader and follow the single leader replica
3 . we need to maintain the - consistency across the replicas
4 . Registration is a write-heavy
operation — optimize DB for inserts.
5 . Offload email sending to a message queue (e.g., SQS
, Kafka
).
6 . Use read replicas for to check for duplicated emails.
7 . Use distributed cache (e.g., Redis) for token lookups.
Fault Tolrance
What if the leader node failed? How we can sync the write and read nodes? Think about all the failures we can have in this system and how to handle these.
1 . Implement leader election for DB writes if scaling horizontally.
2 . Introduce a service to retry email delivery on failure.
3 . Token expiry must be respected to avoid abuse and provide user a way to re-generate a new confirmation link.
Logs/monitoring
Logging and monitoring is crucial for every application. I will monitor and logs:
1 . API errors and latency.
2 . Email delivery success/failure.
3 . Token usage patterns.
4 . New user registrations per day/week.
Trade-offs
1 . Use hashed token instead of storing raw token for security.
2 . Email confirmation adds friction but improves account authenticity.
3 . Caching tokens improves speed, but invalidation complexity increases.
4 . A message queue makes email delivery reliable, but adds infra overhead.
CAP (A note about CAP theorm)
This system prioritizes Consistency and Availability. No duplication, and no mistakes in email ids are allow.
Phew, so this won't be possible without amazingpeople who did 1:1 sessions with me to discuss this problem. In next blog, we will go into the LLD.
Learned something? Liked what I write? Then please share over your social media to support my content.
Happy Learning !!