A high-performance URL shortening service built in C++, implemented in 4 progressive phases β from a core in-memory engine to a full-featured service with rate limiting, analytics, and distributed hashing.
- Phase 1 β Core Engine
- Phase 2 β Rate Limiting, URL Expiry & Thread Safety
- Phase 3 β Consistent Hashing & Distribution
- Phase 4 β Advanced Features
- Getting Started
- Project Structure
Status: β Complete
The foundation of the service. All components are in core/.
| File | Responsibility |
|---|---|
Idgenerator.h/.cpp |
Atomic counter-based unique ID generation (thread-safe) |
Base62Encoder.h/.cpp |
Converts numeric IDs β short alphanumeric codes ([a-zA-Z0-9]) |
LRUCache.h/.cpp |
O(1) in-memory cache with LRU eviction |
urlrespository.h / urlRepository.cpp |
Storage layer mapping short codes β long URLs |
urlshortenerservice.h / urlshortservice.cpp |
Main orchestrator |
1. shortenUrl("https://google.com")
ββ> ID: 1 β Base62: "1" β store("1", "https://google.com") β return "1"
2. redirect("1")
ββ> Check LRU cache β miss β fetch from repository β warm cache β return URL
- URL-safe characters only (
[a-zA-Z0-9]) - 62^7 = 3.5 trillion possible short codes
- No special characters needing URL encoding
Status: β Complete
Token Bucket Algorithm β per IP address:
- Each IP gets a bucket of
maxTokens(default: 5 burst) - Tokens refill at
refillRateper second (default: 2/sec) - Request is blocked if bucket is empty
RateLimiter limiter(5.0, 2.0); // 5 burst, 2 tokens/sec refill
limiter.allowRequest("192.168.1.1"); // true or falseEach URL entry now stores an optional expiry timestamp:
// Expires in 60 seconds
service.shortenUrl("https://promo.com", 60 /*ttlSeconds*/);
// No expiry (permanent)
service.shortenUrl("https://google.com");When redirect() is called on an expired URL, it returns "" and auto-deletes the entry.
LRUCacheβstd::mutexon allget()/put()/remove()callsUrlRepositoryβstd::mutexon allsave()/find()callsRateLimiterβstd::mutexon bucket accessAnalyticsTrackerβstd::mutexon hit recording
Status: β Complete
Distributes short codes across multiple storage nodes with minimal reshuffling when nodes are added/removed.
service.addNode(1);
service.addNode(2);
service.addNode(3);
service.printNodeAssignment("abc"); // β Node 2
service.printNodeAssignment("xyz"); // β Node 1Virtual nodes (default: 3 per real node) ensure even distribution.
User Request
β
βΌ
ββββββββββββββββ
β Geo DNS β β Routes to nearest region
ββββββββββββββββ
β
ββββββββββββ¬βββββββββββ¬βββββββββββ
βΌ βΌ βΌ βΌ
βββββββββββ βββββββββββ βββββββββββ βββββββββββ
β Node 1 β β Node 2 β β Node 3 β β Node N β
βββββββββββ βββββββββββ βββββββββββ βββββββββββ
Status: β Complete
// Use a human-readable alias instead of auto-generated code
service.shortenUrl("https://linkedin.com/in/akshay", 0, "", "akshay");
service.redirect("akshay"); // β https://linkedin.com/in/akshayDuplicate aliases are rejected with a warning.
Tracks click counts per short code. Prints a sorted report:
π Analytics Report (Top 5 URLs):
βββββββββββββββ¬ββββββββββββ
β Short Code β Clicks β
βββββββββββββββΌββββββββββββ€
β 1 β 25 β
β akshay β 5 β
β 2 β 8 β
βββββββββββββββ΄ββββββββββββ
ASCII art placeholder for QR code generation. In production, integrate with libqrencode.
QRCodeStub::printQR("akshay");
// Prints ASCII QR art + full URL- C++ compiler with C++17 support (GCC 7+, Clang 5+, MSVC 2017+)
cd url-shortener-cpp
g++ -std=c++17 main.cpp core/*.cpp -o app.exe./app.exeThe demo runs all 4 phases sequentially, showing:
- Basic shorten + redirect
- LRU cache hits
- Rate limiting (blocked requests)
- URL expiry (TTL)
- Consistent hash node assignments
- Custom aliases
- QR code ASCII art
- Analytics dashboard
url-shortener-cpp/
βββ core/
β βββ Base62Encoder.h/.cpp # Phase 1 β Base62 encoding
β βββ Idgenerator.h/.cpp # Phase 1 β Unique ID generation
β βββ LRUCache.h/.cpp # Phase 1+2 β LRU cache (thread-safe)
β βββ urlrespository.h # Phase 1+2 β Storage layer (with TTL)
β βββ urlRepository.cpp # Phase 1+2 β Storage implementation
β βββ RateLimiter.h/.cpp # Phase 2 β Token bucket rate limiter
β βββ consistenthashing.h/.cpp # Phase 3 β Consistent hash ring
β βββ AnalyticsTracker.h/.cpp # Phase 4 β Click analytics
β βββ QRCodeStub.h # Phase 4 β QR code ASCII stub
β βββ urlshortenerservice.h # All phases β Main orchestrator header
β βββ urlshortservice.cpp # All phases β Main orchestrator impl
βββ main.cpp # Full demo (all 4 phases)
βββ app.exe # Compiled binary
| Operation | Latency | Notes |
|---|---|---|
| Cache Hit | < 1ms | LRU in-memory |
| Cache Miss + Repo | ~1ms | In-memory repo |
| URL Creation | < 1ms | Atomic counter + Base62 |
| Rate Check | < 0.1ms | Token bucket |
Built with β€οΈ and C++17