Loading...
- when user request short url he/she provides long url as param and get short url as response
- when user send request to short ulr he/she automatically redirected to long url
- url maximum length 2MB (2 million characters)
- availability - high, 99.99% of all time
- scalability - high, up to 5K RPS
- security - medium, authentication and authorization + data encryption in transit and rest
- extensibility - low
Maximum 5K RPS, no load spikes
Maximum 1K short urls per user
Maximum 1M User Base
API design
### Base URL
https://api.shorturl.com/v1
```
### Authentication
All endpoints (except redirect) require authentication via Bearer token:
```
Authorization: Bearer <jwt_token>
```
---
## Endpoints
### 1. Create Short URL
```http
POST /urls
```
**Request Body:**
```json
{
"original_url": "https://example.com/very/long/url",
"short_code": "abc123" // optional - auto-generated if not provided
}
```
**Response (201 Created):**
```json
{
"id": 12345,
"user_id": 67890,
"original_url": "https://example.com/very/long/url",
"short_code": "abc123",
"short_url": "https://short.ly/abc123",
"created_at": "2024-01-15T10:30:00Z",
"expires_at": "2024-12-31T23:59:59Z",
"is_active": true
}
```
**Error Responses:**
- `400 Bad Request` - Invalid URL format or short_code already exists
- `401 Unauthorized` - Invalid or missing authentication
- `422 Unprocessable Entity` - Validation errors
### 2. Get User's URLs (List)
```http
GET /urls
```
**Query Parameters:**
- `page` (default: 1) - Page number
- `limit` (default: 20, max: 100) - Items per page
- `is_active` (optional) - Filter by active status
- `sort` (default: created_at) - Sort field (created_at, expires_at)
- `order` (default: desc) - Sort order (asc, desc)
**Example:**
```http
GET /urls?page=1&limit=10&is_active=true&sort=created_at&order=desc
```
**Response (200 OK):**
```json
{
"data": [
{
"id": 12345,
"user_id": 67890,
"original_url": "https://example.com/very/long/url",
"short_code": "abc123",
"short_url": "https://short.ly/abc123",
"created_at": "2024-01-15T10:30:00Z",
"expires_at": "2024-12-31T23:59:59Z",
"is_active": true
}
],
"pagination": {
"current_page": 1,
"per_page": 10,
"total_pages": 5,
"total_count": 47
}
}
```
### 3. Get Specific URL
```http
GET /urls/{id}
```
**Response (200 OK):**
```json
{
"id": 12345,
"user_id": 67890,
"original_url": "https://example.com/very/long/url",
"short_code": "abc123",
"short_url": "https://short.ly/abc123",
"created_at": "2024-01-15T10:30:00Z",
"expires_at": "2024-12-31T23:59:59Z",
"is_active": true
}
```
**Error Responses:**
- `404 Not Found` - URL doesn't exist or doesn't belong to user
### 4. Redirect endpoint
```http
GET /{shortCode} → 301 Redirect to original URL
```
## Data model
sql
CREATE TABLE urls (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(id),
original_url TEXT NOT NULL,
short_code VARCHAR(10) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP NOT NULL,
is_active BOOLEAN DEFAULT true
);
CREATE INDEX idx_short_code ON urls(short_code);
CREATE INDEX idx_user_id ON urls(user_id);
CREATE INDEX idx_expires_at ON urls(expires_at);
## Core Fields
**Identity & Relationships:**
- `id` - Primary key (auto-incrementing big integer)
- `uuid` - Alternative unique identifier (randomly generated)
- `user_id` - Foreign key linking to the users table (who created this short URL)
**URL Data:**
- `original_url` - The full URL being shortened (unlimited length)
- `short_code` - The unique shortened identifier (max 10 characters, like "abc123xyz")
**Lifecycle Management:**
- `created_at` - When the short URL was created
- `expires_at` - When it stops working (required field)
- `is_active` - Manual on/off toggle for the URL
</pre><p></p><p><br></p>
Two-tier system with load balancing at both levels
In the API Layer (Tier 1), client requests enter through an API Server Load Balancer which distributes traffic across three API server instances for horizontal scaling and high availability.
The Data Layer (Tier 2) features a database load balancer that directs write operations to the Primary Database while routing read operations to a Read Replica, implementing a read/write split pattern.
This design provides scalability through multiple API servers, reliability through load balancing, and optimized database performance by separating read and write operations.
The separation of concerns between tiers allows each layer to scale independently according to demand.
Client Layer
Clients: End users accessing the service through web browsers or API integrations
Content Delivery Network (CDN)
CDN/Edge Cache:
Caches static content (CSS, JS, images) and frequently accessed shortened URLs
Reduces latency by serving content from geographically distributed edge servers
Handles redirect requests without hitting backend services for popular URLs
Provides DDoS protection and traffic filtering
API Gateway Layer
Load Balancer
Distributes incoming traffic across multiple API Gateway instances
Implements health checks and failover mechanisms
Provides SSL termination and basic security filtering
Ensures high availability and prevents single points of failure
API Gateway
Central entry point for all API requests
Handles request routing to appropriate microservices
Implements rate limiting and throttling
Manages API versioning and request/response transformation
Provides centralized logging and monitoring
Enforces security policies and CORS handling
Application Layer (Microservices)
Auth Service
Handles user authentication
Manages JWT token generation and validation
Implements OAuth integration for third-party logins
Manages user sessions and access control
Provides user registration and profile management
URL Service (Core Service)
Primary business logic for URL shortening
Generates unique short codes using algorithms (Base62 encoding, hash functions)
Handles URL validation and sanitization
Manages URL expiration and custom aliases
Processes redirect requests and URL resolution
Implements collision detection and resolution
Analytics Service
Tracks click events and user interactions
Generates usage statistics and reports
Processes real-time analytics data
Provides insights on geographic distribution, referrers, and device types
Manages dashboard data aggregation
Caching Layer
Redis Cluster
High-performance in-memory cache for frequently accessed URLs
Stores short URL → long URL mappings for fast lookups
Implements cache-aside pattern with TTL (Time To Live)
Handles session storage and temporary data
Database Layer
DB Load Balancer
Routes read queries to replica databases
Directs write operations to the master database
Implements connection pooling and query optimization
Provides automatic failover capabilities
PostgreSQL Master
Primary database for all write operations
Stores URL mappings, user data, and analytics records
Handles ACID transactions and data consistency
Manages database schema and constraints
Implements backup and recovery procedures
PostgreSQL Replica
Read-only copies of the master database
Handles read queries to reduce master database load
Provides data redundancy and disaster recovery
Enables horizontal scaling of read operations
Maintains eventual consistency with master
Background Services
Cleanup Service
Automated maintenance tasks
Removes expired URLs based on TTL settings
Cleans up orphaned data and temporary records
Performs database optimization and maintenance
Manages log rotation and archival
Handles batch processing of cleanup operations
Metrics Collector
Aggregates analytics data from various sources
Processes click events and user behavior data
Generates periodic reports and summaries
Feeds data to monitoring and alerting systems
1 Postgres Write Database + 1 read replica
32 CPU cores
30 GB memory
SSD 10TB
If main database instance fails automatic failover will promote read replica into main and switch write/read traffic to it.
Once failed database instance is recovered then automatic failover mechanism will switch back.
- add premium plan with maximum 1 million urls per user