A scalable URL shortening service built with FastAPI, SQLModel, and PostgreSQL.
This service is built using a modern tech stack with clean architecture principles:
- Backend: FastAPI framework for high-performance API endpoints
- Database: PostgreSQL with SQLModel ORM for data persistence
- Migration: Alembic for database migrations
- Containerization: Docker and Docker Compose for easy deployment
- Project Structure:
app/models: Data models and schemasapp/services: Business logic and service layerapp/controller: API route definitions and controllersapp/database: Database connection and configurationapp/migrations: Database migration scriptsperformance_tests: k6 performance teststests: Unit and integration tests
The application follows a layered architecture separating concerns:
- REST API endpoints in controllers
- Business logic in services
- Data access through models
- PostgreSQL for persistent storage
- Docker and Docker Compose
-
Clone the repository
git clone <repository-url> -
Deploy with Docker Compose
docker compose up --build -
The application will be available at:
- API: http://localhost:8000
- API Documentation: http://localhost:8000/docs
-
To stop and clean up
docker compose down -v
The service provides the following key endpoints:
GET /{short_code}- Redirect to the original URLPOST /api/urls/shorten- Create a shortened URLGET /api/urls- Get all URLs (with pagination)GET /api/urls/{short_code}- Get URL informationPUT /api/urls/{short_code}- Update a short URLDELETE /api/urls/{short_code}- Soft delete a URLGET /api/analytics/urls- Get most clicked URLsGET /api/analytics/urls/{short_code}- Get analytics for a specific URLGET /api/analytics/summary- Get analytics summary
Complete API documentation is available at the Swagger UI endpoint when the service is running.
For local development without Docker:
- Set up a PostgreSQL database
- Configure environment variables in
.env - Install dependencies:
poetry install - Run migrations:
alembic upgrade head - Start the application:
uvicorn app.main:app --reload
The project includes both unit/integration tests and performance tests.
The tests use an in-memory SQLite database for isolation from the production database:
poetry run pytest
For more information, see the tests/README.md
The project includes performance tests using k6.
- Install k6: https://k6.io/docs/getting-started/installation/
-
Make sure the application is running
-
Run the test:
k6 run performance_tests/simple_test.js -
Run with in-memory database:
poetry run python performance_tests/run_with_inmemory.py -
For more options and details, see the performance_tests/README.md
During development, the following assumptions were made:
- The service is meant to be self-contained and deployable as a standalone application
- Short codes are 6-character alphanumeric strings by default
- Soft deletion is preferred over hard deletion to preserve analytics data
- PostgreSQL is suitable for the expected scale and performance requirements
- The service does not implement authentication/authorization (could be added in future iterations)