Estimate the scale of the system you are going to design...
We would need two APIs, one of type GET and the other of type POST.
Since we are more concerned with reads here and less about writes, we can utilize a database that employs a single leader replication technique. In a single leader replication scheme, the leader would be responsible for the writes and all of the followers would be replicas of the leader that would handle all of the read requests.
Single leader replication is utilized by relational databases like MySQL and PostgreSQL. Among those two, MySQL utilizes row locking to deal with competing processes, while PostgreSQL uses Serializable Snapshot Isolation, which is a form of optimistic concurrency control. PostgreSQL is utilized when we know that we are not going to be running into competing processes, hence, we utilize PostgreSQL as our database.
Inside our database, we can create a hash of the long URL which would be the short URL, add an index to shortURL so all the records in our database would be sorted based on the shortURL. All searches for the corresponding longURL would take O(log(n)) time, where n is the total number of records in our table.
classDiagram
class shortURL {
+int id (auto increment) PK
+String longURL
+String shortURL
}
flowchart TD
B["Client"];
C{"Load Balancer"};
D["Application Server"];
E["Redis Cache"];
F["PostgreSQL Database"];
B --> C;
C --> D;
D --> E;
D --> F;
sequenceDiagram Client->>+Server: Do you have the resource for me? Server->>+Cache: Do you have this resource for me? Cache->>-Server: Yes, here you goo. Server-->>-Client: 302 Redirect Server-->+Database: Do you have the request for me? Database-->>-Server: Yes, here you go Server-->>Client: 302 Redirect/404 Error
We have not considered the thundering herd problem, wherein a short URL can see a sudden spike in the number of users wanting to access it. Such short URLs can be written to cache first and then the database, so that redirect requests can be served using the cache, leading to fast response times and reduced load on our database.