Estimate the scale of the system. Consider daily active users, read/write ratio, storage requirements, bandwidth, and any relevant QPS calculations...
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...
2 Rest endpoints:
POST - / -> create an url, accept a JSON body with {alias: "examplealias", url: "targeturl"}
return the shortened URL if successful
409 and an error if the alias already exists
GET /{alias} -> returns 404 if not existing
301 with url in location if successful
We'll have a:
Only one table, with two fields
alias | url
alias is a key in that database
The server logic is pretty basic: it exposes the API in a stateless way.
This makes the server a perfect candidate for horizontal scaling. This can be achieved by hosting the DB behind a loadbalancer. The server can then be a VM or a container. If the server is a VM we can configure the server to be into an Autoscale group, if it's a container, say in a Kubernetes Cluster we can employ an HPA to scaleup pods as we go. Good proxy metrics to scale up, from more direct to less, are: rps/connections active/CPU. Memory is less important, as modern.
Dynamodb scales autonomously, and the example is pretty simple. We are going to recover always based on Primary Index, so no need to configure Global Secondary Index or Local Secondary Index.