Skip to content

PipeLieDev/pe-hackathon

Repository files navigation

MLH PE Hackathon: URL Shortener API

A resilient URL shortener service built for production.

URL Shortener Demo

Tech Stack:

Flask Peewee ORM Docker Kubernetes PostgreSQL uv Grafana Prometheus Valkey

CI Status:

codecov Build and push Docker image Run tests and collect coverage

Index

Prerequisites

1. uv

A fast Python package manager that handles Python versions, virtual environments, and dependencies automatically — no manual python -m venv needed.

macOS / Linux

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows (PowerShell)

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Note

For other install methods, see the uv installation docs.

uv Cheatsheet

Command What it does
uv sync Install all dependencies (creates .venv automatically)
uv run <script> Run a script inside the project virtualenv
uv add <package> Add a new dependency
uv remove <package> Remove a dependency

2. Docker & Docker Compose

Required for running infrastructure services (PostgreSQL, Valkey) and the full monitoring stack.

Configuration

Copy .env.example to .env before running anything:

cp .env.example .env
Variable Default Description
DATABASE_HOST localhost PostgreSQL host
DATABASE_PORT 5432 PostgreSQL port
DATABASE_NAME hackathon_db Database name
DATABASE_USER postgres Database user
DATABASE_PASSWORD postgres Database password
REDIS_URL Valkey/Redis connection URL (optional)
LOG_LEVEL INFO Logging verbosity

Quick Start

Option 1: Local Development

Runs only PostgreSQL + Valkey via Docker. You run the Flask app yourself with uv.

1. Start dev dependencies

docker compose -f compose.dev.yml up -d

2. Install dependencies

uv sync

3. Configure environment

cp .env.example .env

4. Run the server

uv run run.py

5. Verify

curl http://localhost:5000/health
# → {"status":"ok"}

6. Stop when done

docker compose -f compose.dev.yml down

Option 2: Full Stack with Monitoring

Everything containerized: app, nginx, Prometheus, Grafana, Loki, and Alertmanager.

1. Start all services

docker compose up --build -d

2. Verify

curl http://localhost/health
# → {"status":"ok"}

3. Stop when done

docker compose down

Note

Access the app at http://localhost via nginx. Monitoring URLs are listed in the Monitoring & Observability section.

API Endpoints

Full interactive docs available at /apidocs/ via Swagger UI, or try the live API at https://pipeliedev.github.io/pe-hackathon/

API Demo

Endpoint Method Description
/health GET Health check
/metrics GET Prometheus metrics
/users POST Register a user
/users GET List users
/urls POST Create a shortened URL
/urls GET List URLs
/urls/<short_code> GET Redirect to original URL
/urls/<short_code>/stats GET Get URL statistics
/events GET List analytics events

Project Structure

mlh-pe-hackathon/
├── app/
│   ├── __init__.py          # App factory, Prometheus metrics
│   ├── database.py          # DatabaseProxy, BaseModel, connection hooks
│   ├── cache.py             # Valkey/Redis caching layer
│   ├── logging.py           # Structured JSON logging
│   ├── models/
│   │   ├── user.py
│   │   ├── url.py
│   │   └── event.py
│   └── routes/
│       ├── __init__.py      # register_routes()
│       ├── users.py
│       ├── urls.py
│       └── events.py
├── tests/                   # Unit & integration tests
├── monitoring/              # Prometheus, Grafana, Alertmanager configs
├── k8s/                     # Kubernetes manifests
├── compose.yml              # Full stack (app + monitoring)
├── compose.dev.yml          # Dev only (DB + Valkey)
├── locustfile.py            # Load testing
└── scripts/seed.py          # Seed data script

Running Tests

Make sure dev dependencies are running before starting. If not, run docker compose -f compose.dev.yml up -d first.

1. Create test database (first time only)

docker exec pe-hackathon-db-1 psql -U postgres -c "CREATE DATABASE hackathon_test_db;"

2. Run all tests

uv run pytest

3. Run with coverage (70% minimum required)

uv run pytest --cov=app --cov-report=term-missing --cov-fail-under=70

4. Unit tests only (no DB needed)

uv run pytest tests/unit

5. Integration tests only

uv run pytest tests/integration

6. Run a specific test

uv run pytest tests/integration/test_users.py::test_name -v

Load Testing

uv run locust -f locustfile.py --headless -u 50 -r 10 --run-time 60s --host http://localhost:5000

Monitoring & Observability

Available when running the full stack via docker compose up --build.

Service URL Notes
App http://localhost Via nginx load balancer
Prometheus http://localhost:9090
Grafana http://localhost:30030 Default credentials: admin / admin
Alertmanager http://localhost:9093
Loki http://localhost:3100

Grafana Dashboards

Pre-configured dashboard includes: request rate by HTTP method, p99 latency, error rates, and application resource usage.

Grafana Dashboard

Alert Rules

Alert Condition
HighErrorRateCritical Error rate > 5%
HighAppCPU CPU usage > 80%
HighMemory Memory usage > 80%
NoRequests No traffic for 5 minutes

Deployment

Kubernetes (production)

See k8s-setup.md for the full K3s cluster setup guide.

Deploy

kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/postgres-cluster.yaml
kubectl apply -f k8s/app-deployment.yaml
kubectl apply -f k8s/app-service.yaml

Deploy monitoring

./scripts/deploy-monitoring.sh

Check status

kubectl get pods -n url-shortener

Rollback

kubectl rollout undo deployment/url-shortener -n url-shortener
kubectl rollout status deployment/url-shortener -n url-shortener

License

MIT

About

URL Shortener. MLH Production Engineering Hackathon

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors