You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A high-performance URL shortening platform built with FastAPI, designed to scale from day one. Architecture mirrors real-world systems like Bitly and TinyURL with an emphasis on low-latency redirects, async analytics, and Redis-first caching.
Batch size and flush interval are configurable via ANALYTICS_BATCH_SIZE / ANALYTICS_FLUSH_INTERVAL.
Caching Strategy
Key Pattern
Content
TTL
url:{short_code}
Serialized URL payload
1 hour (2Γ for hot URLs)
hot:{short_code}
Click counter
1 hour (rolling)
qr:{short_code}
Base64 PNG
24 hours
analytics:summary:{code}
Aggregated stats
5 minutes
ratelimit:{id}:{endpoint}
Sorted set (timestamps)
Window duration
analytics:queue
List of click events
β
Hot URL detection: when a link crosses HOT_URL_CLICK_THRESHOLD clicks, its Redis TTL is doubled automatically, preventing popular links from ever expiring from cache.
Rate Limiting
Implemented as a sliding window using Redis sorted sets, which avoids the burst-at-boundary problem of fixed windows:
On each request:
1. ZREMRANGEBYSCORE key -inf (now - window) # remove stale entries
2. ZCARD key # current count
3. If count < limit: ZADD key {now} {uuid} # admit request
4. Else: reject 429 # deny request
Limits (configurable):
Authenticated users: 100 req / 60s
Anonymous: 20 req / 60s
Registration: 10 attempts / hour
Login: 20 attempts / 5 minutes
Tech Stack
Component
Technology
Framework
FastAPI 0.115
Runtime
Python 3.12 + uvicorn
Database
PostgreSQL 16 via asyncpg
ORM
SQLAlchemy 2.0 (async)
Migrations
Alembic
Cache
Redis 7 (redis[asyncio])
Auth
JWT (python-jose) + bcrypt (passlib)
Validation
Pydantic v2
QR Codes
qrcode + Pillow
UA Parsing
user-agents
Logging
structlog (JSON in prod)
Testing
pytest-asyncio + httpx
Container
Docker + Docker Compose
Project Structure
app/
βββ api/v1/endpoints/ # Thin route handlers β no business logic
β βββ auth.py
β βββ urls.py
β βββ analytics.py
β βββ qr.py
β βββ health.py
βββ analytics/ # Event value objects + background processor
βββ cache/ # Redis client, URL cache, rate limiter, analytics queue
βββ core/ # Security, exceptions, structured logging
βββ db/ # SQLAlchemy base + async session factory
βββ dependencies/ # FastAPI dependency injection (auth, db, cache)
βββ middleware/ # Request logging with request-ID tracing
βββ models/ # SQLAlchemy ORM models
βββ repositories/ # Data access layer (no business logic)
βββ schemas/ # Pydantic v2 request/response models
βββ services/ # Business logic layer
βββ tasks/ # Background worker lifecycle
βββ tests/ # pytest-asyncio test suite
βββ utils/ # Short code generation, URL validator, UA parser
Quick Start
With Docker (recommended)
# 1. Clone and configure
cp .env.example .env
# Edit .env β at minimum set SECRET_KEY to a strong random value# 2. Start all services (Postgres, Redis, API)
docker compose up --build
# 3. Run migrations (first time only β handled by the `migrate` service)
docker compose run --rm migrate
# 4. API is live at http://localhost:8000# 5. Interactive docs at http://localhost:8000/docs (DEBUG=true only)