Many solutions for this problem are quite similar and are from dropbox's engineer's presentation. I am not sure memorizing the solution and presenting it during interview would be good. So I tried to share my own solution which I could use during my interview and hope to help you and get your valuable feedbacks.
I was told product design interview focus on API and data model, and scalability is not the focus, So I will try to put my focus on API and data model. And it is said that we can assume scalability is handled. (In fact, I feel quite confuced what I can talk if I don't need to talk about scalability. Any ideas? )
Functional requirements:
- List files
- Upload files
- Download files
- Share files
- Should support both mobile devices and laptop/desktop devices
Non-functional requirements:
- High avaiability
- Eventual consistency
- Suppose 100M users and each could upload more than 10GB files every month
Out-of-scopt
- Modify files
- Support directory
Estimations: (I think this may not be necessary?)
- Total disk space for 10 years: 100M * 10GB * 12 * 10 = 12EB
- Traffic: 1EB / (3600 * 24 * 30 ) = 1TB/s
High Level Architecture:

Upload File data flow:
- User connects to a web service and register to notification service to get notification of any file update.
- User send HTTP POST request to web service upload file.
- The request is then forward to message queue.
- A file service who is available pick up a request from the message queue. And user directly upload file to file service and file service upload the file to Amazon S3, and update meta DB and user DB. After that, the file service sends a response to a response message queue.
- Notification service then pick up a response from message queue and notifies all users sharing this file.
- When user gets notification, he download the files from file server.
- If user is offline right now, the message will be kept in te queue. When user is online again, he will received the message.
Download File data flow:
- User connects to web service and register to notification service.
- User downloads recent updates from other users from notification service. Nofication service will check the user's message queue to see if any update not sent to user.
- Based on user's setting, user may decide to download or sync files that are not in his device now. The request is then sent to web service. And web service forward this message to queue.
- A file service who is available pick up a request from the message queue. And user directly download file from file service.
Share file data flow:
- User A sends a request to web service. The request is then forward to message queue and then the file service to add user B to metafile DB. And then file service sends the response to notify user B.
APIs:
- Upload File: HTTP POST /api/upload ( local_file_path, user_id, time_stamp, [shared_user_ids ], remote_file_name)
- Download File: HTTP GET /api/download?user_id= & file_id=
- List File: HTTP GET /api/download?user_id= & time_stamp=
- Sync File: HTTP PUT /api/sync ( user_id, file_id, [shared_user_ids] )
Data Model:
Metafile DB:
file_id | user_id | permission | created_time | file_name | file_size
Amazon S3:
file_id is used to locate files on Amazon S3
User DB:
user_id | user_name | disk_quata | disk_usage
Client side devices:
- A very straightforward design is each API corresponds to a user interface. User specifically use each function when needed. However that is not user friendly. We may like some UI like what dropbox does. That is, we map a local folder to user's cloud drive and when we want to upload a file, we drag the file and drop it in the folder. In that case, we need to detect user's action to this folder. When a file is dropped inside, it involes the upload process.
- We also need to maintain a local DB to track which files are already downloaded which are not. When download files, we first list all files the user has. And user could decide either to download all not downloaded files or download only the files he needs.
To chunk file or not?
Since we don't need to support modifying a file, chunk seems not necessary. The only concern is when user is uploading a large file and he got disconnected. In that case, maybe we should chunk the file so that we can upload chunk by chunk. Another way is to use FTP but I am not quite famaliar with.
Communication between internal services:
The communication between internal services can use either GraphQL or gRPC which can save more traffic than HTTP GET and POST.
Communication between user and notification service can use web socket as it is more efficient to send message to user than using HTTP polling. Long polling could also be an option but it is still not as efficient as web socket as when there is no update, it still need to keep polling periodically.