A Spring Boot URL Shortener application with Redis caching, MySQL persistence, Flyway database migrations, rate limiting, and click analytics.
This project converts long URLs into short, shareable links. It also tracks redirects, stores click data, applies rate limiting, and uses Redis for fast access.
The goal of this project is to showcase backend engineering practices commonly used in modern Java applications.
- π Shorten long URLs into compact short codes
- βοΈ Support custom aliases
- βͺοΈ Redirect short URLs to the original destination
- π Track click count and click analytics
- π¦ Redis-based rate limiting
- β‘ Cache original URLs in Redis for fast redirects
- ποΈ Persist URLs and click events in MySQL
- π Manage database schema with Flyway
- π³ Containerized with Docker and Docker Compose
- User sends a long URL to the shorten endpoint.
- Application generates a unique short code.
- URL data is stored in MySQL.
- Original URL is cached in Redis.
- User opens the short URL.
- Application checks Redis first.
- If found, the user is redirected immediately.
- Click event is stored for analytics.
| Category | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot |
| Build Tool | Maven |
| Database | MySQL |
| Cache | Redis |
| ORM | Spring Data JPA |
| Migration | Flyway |
| Containerization | Docker |
| Utilities | Lombok |
src
βββ main
β βββ java
β β βββ com.ragul.UrlShortener
β β βββ config
β β βββ controller
β β βββ dto
β β βββ model
β β βββ repository
β β βββ service
β β βββ exception
β β βββ util
β β
β βββ resources
β βββ application.yml
β βββ db
β βββ migration
β
βββ test
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/shorten |
Create a short URL |
| GET | /api/{shortCode} |
Redirect to original URL |
| GET | /api/stats/{shortCode} |
URL statistics |
| GET | /api/analytics/{shortCode} |
Click analytics |
| DELETE | /api/{shortCode} |
Delete URL |
{
"originalUrl": "https://example.com/articles/spring-boot",
"customAlias": "spring",
"expiresAt": "2026-12-31T23:59:59"
}{
"shortUrl": "http://localhost:8080/api/spring",
"shortCode": "spring",
"originalUrl": "https://example.com/articles/spring-boot",
"createdAt": "2026-08-01T10:30:00",
"expiresAt": "2026-12-31T23:59:59"
}Configure your environment variables:
DB_URL=jdbc:mysql://localhost:3306/url_shortener
DB_USERNAME=root
DB_PASSWORD=password
REDIS_HOST=localhost
REDIS_PORT=6379Never commit your
.envfile. Use.env.exampleinstead.
server:
port: 8080
spring:
application:
name: UrlShortener
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
jpa:
hibernate:
ddl-auto: validate
show-sql: true
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
data:
redis:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
timeout: 2000ms
url-shortener:
base-url: http://localhost:8080
short-code:
length: 6
max-attempts: 10
rate-limit:
max-requests-per-minute: 2
max-requests-per-hour: 10
minute-window: 1m
hour-window: 1h
cache:
ttl-minutes: 30git clone https://github.com/<your-username>/UrlShortener.git
cd UrlShortenerMake sure both services are running.
./mvnw spring-boot:runor
mvn spring-boot:runBuild and start all services
docker compose up --buildRun in detached mode
docker compose up -dStop containers
docker compose downFlyway automatically creates and manages the database schema.
Main Tables
url_dataclick_events
- Add authentication and user-specific URL management
- QR code generation
- Add Swagger/OpenAPI documentation
- Add unit and integration tests
- Add a dashboard UI for analytics
- Add custom domain support
- Monitoring with Prometheus & Grafana
Contributions, suggestions, and improvements are welcome.
- Fork the repository
- Create a feature branch
- Commit your changes
- Open a Pull Request
This project is licensed under the MIT License.





