User want to be able to enter a URL and received a shortened one
User wants to access a link via shorted url
High-Availability
Low-Latency
Reliability - After creating the URL must exist
Global
Unique
URL length of 6-12
10.000.000 daily; Seconds in a day = 100.000;
Writes = 10/s
Read = 1000/s
Original Url Average Size = 100
Shortened = 8
MetaData = View, User, lock access, = 1kb
Total we can consider 2Kb;
Storage
2KB * 10Mi * 365 = 730GB of storage
The system would need authentication for the creation route and maybe for reading if is an private URL
POST /url
Description: Creates a new url
Header: Authorization JWT
Body: {
URL: string,
expiration: number,
private: bool,
}
Response {
shortenedUrl: string
}
GET /url/:shortenedUrl
Description: fetch the original link
Header: (Optional) Authorization JWT
Response: {
originalUrl: string
}
-- Adicionatal Routes
GET /url/list
Description: Fetch the created links sorted by created at
Header - Authorization JWT
Params: { first, skip }
Response {
data: [
{
id: ...,
URL: string,
views: number
}
]
}
PUT /url/:shortenedUrl/permission
Header - Authorization JWT
Description: Update the permission of a given url
Body {
allowed: [
//list of allowed user
]
}
Response {
ok: ..
}
// url
{
id: number,
title: string
description: string
originalUrl: string
shortenedUrl: string,
private: false,
views: number,
allowedUsers: [id] @reference to the userId
}
The system will be composes by The client accessing the by an load balancer or an API gateway. The API gateway will be responsible to block high limits rating from users as also DDos attacks
One path way connecting into the server into the database, a nosql database. We need to scale, so It could be lambda functions because It will handle properly the large amount of the request
For the read part, is desirable to have a CDN content for caching the content of the most access URLs. Also a redis cache for updating the views an latter update the database
I didn't added to the high level design. But we could use another queue attached to dynamo and with a worker to backup longechunks of data every minute in a read only replica
We need to also add to this design another job for removing expired URLs or that can be archived with TLL in dynamo
Creating a post
Client Trigger via Load balancer, in this stage the user is identify via an API Gateway by an authentication service like coginito, and we can record the request limit and also the auth of the user.
Next, the URL shortening service is called;
Before processing, the provided URL needs to be check if is valid or return 403 error;
the process of URL been encode is executed and the new URL data is stored in the dynamodb.
Some notification can be attached to this event of creation complete so other services could handle this event.
For reading the URL the user makes a request to the CDN, if not find, then goes to the LB to be served by the URL shorten service. The service can directly fetch by the database or we could use the redis cache as a second cache layer for better latency. But before redirect we need to check if the link is valid, if not we could flag as "broken" and give a time of the event, so that a job latter could see if the link resides in that state. If yes it must be remove, else we keep
There is a lot of bottle necks like:
Rate limit
Cost in scale the lambda.
The design dosent cover things like monitoring;
Privacy and expiration; We would need jobs for timely remove the URL or remove the access of some URLs;
Better attacks and security handle;
How do we check if the URL still exists and is not a dead URL?