Note: We've covered individual pieces of Alibaba Cloud. Now let's build something real. This final blog walks through a complete project from concept to optimization. By the end, you'll have a blueprint for your own applications.
Theory is great. Practice is better.
In this blog, I'm going to walk you through building a real application: A URL Shortener Service (like bit.ly or TinyURL). It's complex enough to showcase most concepts we've covered, yet simple enough to understand completely.
You'll see:
● Architecture design from scratch
● Implementation step-by-step
● Real performance bottlenecks and how to fix them
● Cost optimization strategies
● Lessons learned
Let's build something.
A URL shortening service where:
https://example.com/very/long/url/with/parameters)yourdomain.com/abc123, they're redirected to the long URL● 1 million shortened URLs created per day
● 100 million redirect requests per day
● 99.9% availability (33 minutes downtime allowed per month)
● <100ms redirect latency required
● Cost per million redirects (minimize)
● Latency (P95 < 50ms, P99 < 100ms)
● Availability (target 99.9%)
Table: URLs
├─ id (auto-increment, primary key)
├─ short_code (unique, indexed)
├─ long_url (the original URL)
├─ user_id (who created it)
├─ created_at
├─ expires_at
└─ status (active, deleted)
Table: Statistics
├─ short_code (foreign key)
├─ visitor_count (total clicks)
├─ last_accessed_at
├─ unique_visitors (rough estimate)
└─ countries (top 5)
Challenge: Generate unique, random short codes that are URL-safe.
Algorithm:
- Start with a 6-character code (allows 62^6 = 56 billion combinations)
- Use charset: 0-9, a-z, A-Z (62 characters)
- Generate randomly until collision (rare, handled by retry)
- Store mapping: short_code → long_url
Code:
const CHARSET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
function generateShortCode(length = 6) {
let code = '';
for (let i = 0; i < length; i++) {
code += CHARSET[Math.floor(Math.random() * CHARSET.length)];
}
return code;
}
async function createShortUrl(longUrl, userId) {
let shortCode;
let collision = false;
do {
shortCode = generateShortCode();
// Check if exists
const existing = await db.query('SELECT * FROM urls WHERE short_code = ?', shortCode);
collision = existing.length > 0;
} while (collision);
// Store
await db.query('INSERT INTO urls (short_code, long_url, user_id) VALUES (?, ?, ?)',
[shortCode, longUrl, userId]);
return shortCode;
}
┌────────────────────────────────────────┐
│ User's Browser │
│ GET /abc123 (browser follows redirect)│
└──────────┬─────────────────────────────┘
│
┌──────────▼──────────────────────────────┐
│ CDN (Cache redirects) │
│ Most hits stop here (80% cache hit) │
└──────────┬──────────────────────────────┘
│ (Cache miss)
┌──────────▼──────────────────────────────┐
│ Load Balancer (SLB) │
│ Distributes across servers │
└──────────┬──────────────────────────────┘
│
┌──────┴──────┐
│ │
┌──▼──┐ ┌──▼──┐
│Web1 │ │Web2 │ (Stateless)
└──┬──┘ └──┬──┘
│ │
└──────┬──────┘
│
┌──────▼──────────────┐
│ Redis Cache │
│ (hot URLs) │
└──────┬──────────────┘
│ (Cache miss)
┌──────▼──────────────┐
│ RDS Database │
│ MySQL (replicated) │
└─────────────────────┘
Async (via Message Queue):
┌──────────────────────────┐
│ Message Queue │
│ (Click events) │
└──────────┬───────────────┘
│
┌─────▼─────┐
│ Stats Job │ (Batch update statistics)
└───────────┘
# terraform/main.tf
terraform {
required_providers {
alibabacloud = {
source = "aliyun/alibabacloud"
version = "~> 1.0"
}
}
}
provider "alibabacloud" {
region = "ap-southeast-1"
}
# VPC
resource "alibabacloud_vpc" "main" {
name = "url-shortener-vpc"
cidr_block = "10.0.0.0/16"
}
# Public Subnet
resource "alibabacloud_vswitch" "public" {
vpc_id = alibabacloud_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-southeast-1a"
name = "public-subnet"
}
# Private Subnet
resource "alibabacloud_vswitch" "private" {
vpc_id = alibabacloud_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "ap-southeast-1b"
name = "private-subnet"
}
# Security Group
resource "alibabacloud_security_group" "web" {
name = "web-sg"
vpc_id = alibabacloud_vpc.main.id
description = "Web servers"
}
resource "alibabacloud_security_group_rule" "http" {
type = "ingress"
ip_protocol = "tcp"
port_range = "80/80"
cidr_ip = "0.0.0.0/0"
security_group_id = alibabacloud_security_group.web.id
}
resource "alibabacloud_security_group_rule" "https" {
type = "ingress"
ip_protocol = "tcp"
port_range = "443/443"
cidr_ip = "0.0.0.0/0"
security_group_id = alibabacloud_security_group.web.id
}
# RDS Database
resource "alibabacloud_db_instance" "mysql" {
engine = "MySQL"
engine_version = "8.0"
instance_type = "mysql.n2.small.1"
instance_storage = 20
instance_charge_type = "Postpaid"
vswitch_id = alibabacloud_vswitch.private.id
security_group_ids = [alibabacloud_security_group.web.id]
}
resource "alibabacloud_db_database" "main" {
instance_id = alibabacloud_db_instance.mysql.id
name = "urlshortener"
}
# ElastiCache (Redis)
resource "alibabacloud_kvstore_instance" "redis" {
instance_class = "redis.logic.sharding.1g.2db.0rw"
instance_type = "Redis"
engine_version = "7.0"
vswitch_id = alibabacloud_vswitch.private.id
security_group_ids = [alibabacloud_security_group.web.id]
}
# Auto Scaling Group
resource "alibabacloud_launch_template" "web" {
image_id = var.image_id
instance_type = "ecs.t6.medium"
security_group_ids = [alibabacloud_security_group.web.id]
internet_max_bandwidth_out = "10"
tag_specification {
resource_type = "instance"
tags = {
Name = "url-shortener-web"
}
}
}
resource "alibabacloud_auto_scaling_group" "web" {
min_size = 2
max_size = 10
desired_capacity = 2
launch_template_id = alibabacloud_launch_template.web.id
vswitch_ids = [alibabacloud_vswitch.public.id]
}
# Load Balancer
resource "alibabacloud_slb" "main" {
name = "url-shortener-slb"
internet_charge_type = "PayByTraffic"
address_type = "internet"
spec = "slb.s2.small"
}
resource "alibabacloud_slb_listener" "http" {
load_balancer_id = alibabacloud_slb.main.id
frontend_port = 80
backend_port = 8080
protocol = "http"
bandwidth = 1024
}
# CDN
resource "alibabacloud_cdn_domain_new" "main" {
domain_name = "short.example.com"
cdn_type = "web"
scope = "domestic"
origin_servers = {
origin_server_primary = alibabacloud_slb.main.address
}
}
// src/server.js
const express = require('express');
const redis = require('redis');
const mysql = require('mysql2/promise');
const app = express();
// Initialize connections
const redisClient = redis.createClient();
const mysqlPool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// Middleware
app.use(express.json());
// POST /shorten - Create short URL
app.post('/shorten', async (req, res) => {
try {
const { longUrl, userId } = req.body;
// Validate
if (!longUrl || !isValidUrl(longUrl)) {
return res.status(400).json({ error: 'Invalid URL' });
}
// Generate short code
let shortCode;
let exists = true;
while (exists) {
shortCode = generateShortCode();
const [rows] = await mysqlPool.query(
'SELECT * FROM urls WHERE short_code = ?',
[shortCode]
);
exists = rows.length > 0;
}
// Store in database
await mysqlPool.query(
'INSERT INTO urls (short_code, long_url, user_id, created_at) VALUES (?, ?, ?, NOW())',
[shortCode, longUrl, userId]
);
// Cache for 24 hours
await redisClient.setEx(
`url:${shortCode}`,
86400,
JSON.stringify({ longUrl, shortCode, created_at: new Date() })
);
res.json({
short_code: shortCode,
short_url: `https://short.example.com/${shortCode}`,
long_url: longUrl
});
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});
// GET /:shortCode - Redirect
app.get('/:shortCode', async (req, res) => {
try {
const { shortCode } = req.params;
// Check cache first
let cached = await redisClient.get(`url:${shortCode}`);
if (cached) {
const data = JSON.parse(cached);
// Async: Send click event to queue
await sendToQueue('click-event', {
shortCode,
timestamp: new Date(),
userAgent: req.headers['user-agent'],
ip: req.ip
});
return res.redirect(302, data.longUrl);
}
// Cache miss: Query database
const [rows] = await mysqlPool.query(
'SELECT long_url FROM urls WHERE short_code = ? AND status = "active"',
[shortCode]
);
if (rows.length === 0) {
return res.status(404).json({ error: 'Short URL not found' });
}
const { long_url } = rows;
// Update cache
await redisClient.setEx(
`url:${shortCode}`,
86400,
JSON.stringify({ longUrl: long_url, shortCode })
);
// Async: Send click event
await sendToQueue('click-event', {
shortCode,
timestamp: new Date(),
userAgent: req.headers['user-agent'],
ip: req.ip
});
res.redirect(302, long_url);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});
// GET /stats/:shortCode - Get statistics
app.get('/stats/:shortCode', async (req, res) => {
try {
const { shortCode } = req.params;
const [stats] = await mysqlPool.query(
'SELECT visitor_count, unique_visitors, last_accessed_at FROM statistics WHERE short_code = ?',
[shortCode]
);
if (stats.length === 0) {
return res.json({ visitor_count: 0, unique_visitors: 0 });
}
res.json(stats);
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
// Background job: Process click events
async function processClickEvents() {
while (true) {
try {
// Get batch of events from queue
const events = await getFromQueue('click-event', 100);
if (events.length === 0) {
await new Promise(resolve => setTimeout(resolve, 1000));
continue;
}
// Group by short code
const grouped = {};
events.forEach(event => {
if (!grouped[event.shortCode]) grouped[event.shortCode] = [];
grouped[event.shortCode].push(event);
});
// Update database
for (const [shortCode, events] of Object.entries(grouped)) {
const count = events.length;
const uniqueCount = new Set(events.map(e => e.ip)).size;
await mysqlPool.query(
`UPDATE statistics
SET visitor_count = visitor_count + ?, unique_visitors = ?, last_accessed_at = NOW()
WHERE short_code = ?`,
[count, uniqueCount, shortCode]
);
}
} catch (error) {
console.error('Error processing click events:', error);
}
}
}
// Utility functions
function generateShortCode(length = 6) {
const charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let code = '';
for (let i = 0; i < length; i++) {
code += charset[Math.floor(Math.random() * charset.length)];
}
return code;
}
function isValidUrl(string) {
try {
new URL(string);
return true;
} catch (_) {
return false;
}
}
async function sendToQueue(queueName, message) {
// Implementation depends on message queue choice
// (SQS, RabbitMQ, Alibaba Cloud Message Queue, etc.)
}
async function getFromQueue(queueName, limit) {
// Implementation depends on message queue choice
}
// Start server
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
// Start background job
processClickEvents();
});
Problem: Every redirect requires a database query. At 100M redirects/day, that's 1,157 queries/second!
Solution: Redis cache
// Before: 1,157 db queries/second
const [rows] = await mysqlPool.query('SELECT ...');
// After: ~924 db queries/second (20% cache hit)
// Most requests hit Redis (in-memory, <1ms)
let cached = await redisClient.get(`url:${shortCode}`);
if (!cached) {
const [rows] = await mysqlPool.query('SELECT ...');
}
Impact:
● Cache hit = <1ms latency
● Database query = 5-10ms latency
● Cost reduction: 80% fewer database queries
Problem: Writing to database on every click degrades latency
Solution: Batch processing with message queue
// Before: Write to DB on every request
await mysqlPool.query('UPDATE statistics SET visitor_count = visitor_count + 1 ...');
// Adds 5-10ms to redirect latency
// After: Send event to queue (1ms), process asynchronously
await sendToQueue('click-event', { shortCode, ... });
// Adds <1ms to redirect latency
Impact:
● User-facing redirect latency reduced 80%
● Database write load smoothed out
● Statistics eventually consistent (acceptable for this use case)
Problem: Users in Europe take 200ms+ to reach Asia servers
Solution: CDN + Regional servers
# Deploy in multiple regions
resource "alibabacloud_slb" "sg" {
name = "url-shortener-sg"
region = "ap-southeast-1" # Singapore
}
resource "alibabacloud_slb" "de" {
name = "url-shortener-de"
region = "eu-central-1" # Frankfurt
}
Configure DNS to route users to nearest region (GeoDNS). CDN caches redirects globally.
Impact:
● P95 latency: 200ms → 50ms
● P99 latency: 500ms → 100ms
● Availability: 99.9% (region failure isolated)
| Component | Spec | Monthly Cost |
|---|---|---|
| ECS (2-4 instances) | t6.medium, auto-scaling | $120 |
| RDS | db.t3.small, replicated | $60 |
| Redis | 1GB cache | $40 |
| Load Balancer | Standard SLB, 1M requests | $50 |
| CDN | 100M requests | $300 |
| Data transfer | Inter-region | $100 |
| Total | ~$670/month |
$670 / 3,000M = $0.22 per million redirects
Current: t6.medium (2 vCPU, 4GB RAM) = $30/month each
Analysis: Actual usage
● CPU: 15% average, 40% peak
● Memory: 2GB average, 3GB peak
Optimize: t6.small (1 vCPU, 2GB RAM) = $15/month each
Savings: $15/month × 2 instances = $30/month (4.5%)
Current: Single RDS db.t3.small ($60/month)
Problem: Analytics queries slow down production
Solution: Read replica ($40/month)
Benefits:
● Zero impact on production latency
● Analytics queries fast
● Total cost: +$40
Worth it? Yes—better insight into system.
Current: Cache everything, 24-hour TTL
Optimization: Smart TTL
● Popular URLs (>1000 clicks): 24-hour TTL
● Medium URLs (100-1000): 12-hour TTL
● Unpopular URLs (<100): 1-hour TTL
Cost impact: 15% fewer cache misses
Savings: $300 × 0.15 = $45/month (6.7%)
Current: Replicating between regions (expensive)
Optimization: Keep hot data in CDN, cold data in archive
Cost savings: $50/month (50%)
| Optimization | Savings |
|---|---|
| Instance right-sizing | $30 |
| Smart CDN TTL | $45 |
| Data transfer optimization | $50 |
| Total | $125 (18.7%) |
New monthly cost: $545 ($0.18 per million redirects)
Dashboards:
├─ System Health
│ ├─ CPU Utilization: 15% avg, 40% peak (target: <70%)
│ ├─ Memory: 2GB avg, 3GB peak (target: <80%)
│ ├─ Disk: 8GB used, 20GB available (target: <80%)
│ └─ Network: 100Mbps avg, 500Mbps peak
│
├─ Application
│ ├─ Redirect latency: P50=20ms, P95=45ms, P99=95ms
│ ├─ Error rate: 0.01% (target: <0.1%)
│ ├─ Shorten latency: P50=50ms, P95=100ms, P99=200ms
│ └─ Cache hit ratio: 80% (target: >75%)
│
├─ Database
│ ├─ Connections: 45/50 (target: <80%)
│ ├─ Query latency: P50=2ms, P95=8ms, P99=20ms
│ ├─ Replication lag: 0s (target: <1s)
│ └─ Slow queries: 0 (target: 0)
│
└─ Cost
├─ Daily spend: $18 (on pace for $540/month)
├─ Cost per million redirects: $0.18
└─ Cost trend: -2% vs last month
Trigger: CPU > 70% for 5 minutes
Action: Page on-call engineer, prepare to scale
Trigger: Cache hit ratio < 70%
Action: Investigate cache issues, potential memory pressure
Trigger: Error rate > 0.5%
Action: Page engineer, check logs
Trigger: Daily cost > $25
Action: Investigate cost anomalies
✅ Cache everything cacheable
✅ Async everything non-critical
✅ Monitor early, often
✅ Right-size, don't over-provision
✅ Plan for failure
✅ Automate, don't click
● Clone the repository template
● Deploy infrastructure with Terraform
● Run application locally
● Create a few short URLs
● Set up monitoring and alerts
● Configure CDN
● Implement cache layer
● Set up CI/CD pipeline
● Optimize costs
● Deploy to multiple regions
● Advanced analytics
● Custom domain support
● GraphQL API
● Real-time collaboration
● ML-powered recommendations
● Mobile app
Congratulations! You now have:
✅ Real project experience: You've designed and deployed a production-grade application
✅ Performance optimization mindset: You identify bottlenecks and fix them systematically
✅ Cost consciousness: You optimize not just for speed, but for efficiency
✅ Full-stack knowledge: From infrastructure to code to monitoring
This series started with "getting started," and now you're ready to build for real.
Cloud computing isn't magic. It's:
● Architecture: Thinking about how components interact
● Automation: Removing manual steps and human error
● Monitoring: Knowing what's happening in real-time
● Optimization: Making systems faster and cheaper
You've learned all of these in this series.
The beautiful part? Everything you've learned applies to other projects too. The principles of scaling, security, and cost optimization are universal.
So take what you've learned here. Build your next project. Measure it. Optimize it. Share what you learn with others.
That's how we grow as engineers.
__
What will you build next? Comment below. I'd love to hear about your projects and help you troubleshoot along the way.
Series Complete! Thank you for joining me on this journey through Alibaba Cloud. Remember: The cloud is just someone else's computer—but configured really, really well.
Keep building. 🚀
Disclaimer: The views expressed herein are for reference only and don't necessarily represent the official views of Alibaba Cloud.
Automation and DevOps on Alibaba Cloud: CI/CD and Infrastructure as Code
19 posts | 0 followers
FollowNeel_Shah - August 8, 2025
Data Geek - April 25, 2024
Alibaba Cloud Community - December 12, 2023
Alibaba Clouder - February 14, 2020
Alibaba Cloud Community - August 15, 2025
Alibaba Cloud Native - September 12, 2024
19 posts | 0 followers
Follow
Application High Availability Service
Application High Available Service is a SaaS-based service that helps you improve the availability of your applications.
Learn More
Elastic High Performance Computing
A HPCaaS cloud platform providing an all-in-one high-performance public computing service
Learn More
Remote Rendering Solution
Connect your on-premises render farm to the cloud with Alibaba Cloud Elastic High Performance Computing (E-HPC) power and continue business success in a post-pandemic world
Learn MoreMore Posts by Farah Abdou