Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
Administrative endpoints
Main endpoint
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
I think the basic design in the diagram could suffice. The administrative endpoints should be fairly low volume. I don't foresee users creating a lot of shortlinks all the time. These endpoints should simply take the CRUD operations and utilize the database directly.
For the database I think we could use postgres. It's a great general purpose database an I know it well. The main table will be a shortlink table.
create table shortlink (
id serial primary key;
shortcode text;
redirect_url text not null;
user_id text not null;
created_at timestamptz;
last_updated_at timestamptz;
);
Generally the POST /api/v1/shortlinks endpoint should insert the row. Since we're using serial, the id should auto increment. The shortcode should be a base62 encoding of the id and we can update the row to set shortcode value once we get back the id value from the initial insert. We will also want to index the shortcode column for fast lookups.
The main endpoint will need to scale horizontally and be highly available. There are a few approaches we could take to scale it, but I think to start, we could just use a basic web server and implement an in-memory LRU cache. For big events this could provide a very fast response where many users are requesting the same shortlink because it would be able to skip going to the database and return an in-memory redirect url. For shortlinks not in the LRU cache, we would go to the database and then store in the LRU cache.
To achieve HA, we could use a cloud provider like GCP or AWS. We could use an orchestration layer like k8s or utilize managed services to host our webserver(s). We could also put together a disaster recovery plan that includes automatic failover to other AZ's or regions.
If we're worried about the webservers eventually not being able to hold a large enough LRU cache in memory to be practical, we could start to look at other caching alternatives. Redis or memcached. We could also explore edge servers and more advanced caching options.
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
We should be able to scale our servers out horizontally pretty easily as well. We could set up autoscaling and put a load balancer in front of them. And since our database would not be used for the majority of requests, it should be able to keep up pretty easily.
If we need to scale our database for some reason, we could put readonly replicas in place. Since there really isn't a requirement that the replication complete quickly, this should work nicely. For example, if the replicas take 30 seconds to be consistent, this should be fine.
If we're worried about spamming with bad shortlinks, we could put some kind of firewall in front of the ingress that could automatically block requests from IPs where they've made 10 bad requests in a minute, or something along those lines.