MQ Mail - Backend Architecture Design Attachment
MQ Mail - Backend Architecture Design Attachment
MQ Mail - Backend Architecture Design Attachment
Context
This interview is a roleplay. We (your interviewers) have recently launched a consumer email
product in the market, MQ Mail (to compete with GMail), and need your support in improving our
backend to meet the expected increase in consumer demand.
Since we want to compete against Gmail, we have come up with the following Service Level
Objectives.
● 99.99% availability to users
● Inbox view in <1000ms at 95th percentile and <500ms at 50th percentile
Send
Our 3rd-party partner exposes an endpoint “/send” which accepts JSON encoded emails via an
HTTP POST. “/send” returns a 201 response if the message will be successfully delivered and
a 5XX upon failure. These responses are definitive.
$ curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: <something>" \
--data '{ \
"id": "some-mq-generated-unique-id", \
"to":"foo@bar.com", \
"from": "baz@mqmail.com", \
"subject": "Test", \
"message": "Test test." \
}' https://api.3rd-party-service.net/send
Receive
Our 3rd-party partner receives (via SMTP) all email for our registered domain (mqmail.com) and
notifies us upon each email receipt via webhook: a JSON encoded HTTP POST. They will
retry the webhook for up to 24 hours until receiving a 2XX response from our server.
Example simulated webhook request:
$ curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: <something>" \
--data '{ \
"id": "some-3rd-party-generated-unique-id", \
"to":"baz@mqmail.com", \
"from": "foo@bar.com", \
"subject": "Test", \
"message": "Test test." \
}' https://api.mqmail.com/receive
MQ Mail Backend
We have built a simple backend, which consists of an application server (which serves requests
from the frontend via RESTful APIs), deployed as a Docker container in “the cloud”, and a single
relational database server.
Database Schema
We have 2 tables in our database. users, which stores the consumer email accounts, and
emails, which stores the emails sent and received.
users table
emails table
Authentication and Authorization
Our frontend manages authentication and authorization. For the sake of this discussion we can
assume that each request our backend receives has been appropriately validated and includes
a simple, performant way to extract a user_id from it.
Sending Email
Our backend receives an HTTP POST to send an email from our frontend and:
1. Generates a unique id for the email
2. Formats and sends an HTTP POST to the 3rd-party “/send” endpoint
3. Upon success:
a. Inserts an emails row into our database
b. Sends a 201 response to our frontend
4. Upon failure:
a. Sends a matching 5XX response to our frontend
Receiving Email
When our 3rd-party partner receives an email to our domain on our behalf, they forward it to our
backend via an HTTP POST (webhook) and:
1. Searches for a matching user record based on the “to” field in the JSON body
2. Upon finding a matching user:
a. Generates a unique id for the email
b. Inserts an emails row into our database
c. Sends a 201 response to the 3rd-party
Known Limitations
Feature Limitations
By design, MQ Mail currently does not support:
1. Multiple recipients
2. Cc, Bcc
3. Attachments
Performance Limitations
Our system has performed well enough (we think) so far (we have signed up roughly 10K users
in the 3 months since our launch) but we are concerned about performance as we grow. Our
goal is to reach GMail size (100M users) over the next year. There are two specific areas that
concern us:
1. Application server availability, latency and load
2. Database reads and writes, specifically from and to our emails table
Major Bugs
We have intermittently heard complaints from our users about seeing duplicate inbound emails.
It isn’t reproducible but we do see the duplicate entries in our database in each case (with
similar timestamps).
We’ve also heard a few reports of users seeing “strange” error messages when attempting to
send an email. In each of these cases, when debugging, we have found that the email was
actually sent to (and received by) the intended recipient. However, the email was not stored in
our database and not visible in the user’s outbox.