A lightweight URL shortening service built with Spring Boot 4.1.
This project demonstrates the implementation of a RESTful API using:
- Base62 encoding
- Cache Aside pattern with Redis
- PostgreSQL persistence
- Docker Compose
- Unit, Controller and Integration Tests with Testcontainers
βββββββββββββββ
β Client β
ββββββββ¬βββββββ
β
POST /shorten
GET /{code}
β
ββββββββββΌβββββββββ
β Spring Boot API β
ββββββββββ¬βββββββββ
β
βββββββββββ΄ββββββββββ
βΌ βΌ
PostgreSQL Redis
Persistent Store Cache
The following example shows the complete request flow:
- Create a shortened URL
- Access the generated short URL
- Receive an HTTP 302 redirect
- Observe the Cache-Aside flow (Redis β PostgreSQL β Redis)
flowchart LR
Client[Client]
subgraph App[Spring Boot Application]
Controller[UrlController]
Service[UrlShortenerService]
Repository[ShortUrlRepository]
Encoder[Base62Encoder]
end
DB[(PostgreSQL)]
Redis[(Redis)]
Client -->|POST /shorten| Controller
Controller -->|call| Service
Service -->|read / write| Repository
Repository -->|SQL| DB
Service -->|Generate Base62 code| Encoder
Service -.->|not used| Redis
sequenceDiagram
participant Client
participant Controller
participant Service
participant PostgreSQL
Client->>Controller: POST /shorten
Controller->>Service: shorten(url)
Service->>PostgreSQL: URL already exists?
alt Yes
PostgreSQL-->>Service: existing code
else No
Service->>Service: generate Base62 code
Service->>PostgreSQL: persist URL
end
Service-->>Controller: shortUrl
Controller-->>Client: 200 OK
sequenceDiagram
participant Client
participant Service
participant Redis
participant PostgreSQL
Client->>Service: GET /{code}
Service->>Redis: query
alt Cache HIT
Redis-->>Service: URL
else Cache MISS
Service->>PostgreSQL: query
PostgreSQL-->>Service: URL
Service->>Redis: update cache
end
Service-->>Client: 302 Redirect
- Java 21
- Spring Boot 4.1
- Spring MVC
- Spring Data JPA
- Spring Data Redis
- PostgreSQL
- Redis
- Docker Compose
- JUnit 5
- Mockito
- MockMvc
- WebTestClient
- Testcontainers
src
main
βββ config
βββ controller
βββ dto
βββ entity
βββ repository
βββ service
βββ util
test
βββ controller
βββ integration
βββ service
# Clone the Repository
git clone https://github.com/wekers/shortURL.git
cd shortURL/Copy the example environment file:
cp .env.example .envEdit the .env file if you wish to change the PostgreSQL credentials.
docker compose --env-file .env up -dCheck containers:
docker psLoad the environment variables:
- For Bash/Zsh:
export $(grep -v '^#' .env | xargs)- For Fish shell (use a helper file):
source load-env.fishRun the application:
./mvnw spring-boot:runRedis Stack Web UI:
curl -X POST http://localhost:8080/shorten \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/products/electronics/notebooks/gaming/high-performance-model-2026"}'Response:
{
"shortUrl": "http://localhost:8080/fxSM"
}curl -v http://localhost:8080/fxSMResponse:
HTTP/1.1 302 Found
Location: https://example.com/products/electronics/notebooks/gaming/high-performance-model-2026
./mvn test| Type | Frameworks |
|---|---|
| Unit | JUnit + Mockito |
| Controller | MockMvc |
| Integration | WebTestClient + Testcontainers (PostgreSQL + Redis) |
- URL Shortening
- PostgreSQL
- Redis
- Docker Compose
- Unit Tests
- Controller Tests
- Integration Tests
- Testcontainers
- GitHub Actions
- Build Badge
- API documentation (OpenAPI / Swagger)
- Metrics with Micrometer + Prometheus
- Docker image publishing
- Deployment to a cloud provider
MIT


