A production-ready Flask service that exposes versioned REST endpoints for managing student records. The project was built as part of an SRE bootcamp to demonstrate Twelve-Factor App practices, clean layering, automated migrations, Postman documentation, and a comprehensive unit-test suite.
- Learning Outcomes & Feature Highlights
- Tech Stack
- Repository Layout
- Prerequisites
- Setup & Local Development
- Configuration
- Database Migrations
- Running the API
- Testing
- API Surface
- Postman Collection
- Logging & Observability
- Further Improvements
- Twelve-Factor friendly: runtime configuration via environment variables, strict separation of config vs code, explicit dependency declaration, and stateless workers.
- REST best practices: versioned routes (
/api/v1), proper HTTP verbs, structured validation errors, and idempotent update/delete handlers. - Full CRUD coverage: create, list, retrieve, update, and delete students backed by SQLAlchemy models.
- Health monitoring:
/healthcheckat the blueprint level and a root/healthcheckto integrate with container orchestration probes. - Migration-ready: lightweight script that materializes the schema through SQLAlchemy metadata.
- Automation hooks: Make targets for installing deps, running migrations, launching the server, and executing tests.
- Unit tests: pytest suite with isolated SQLite databases per test to avoid cross-test data bleed.
- Postman documentation: sharable collection covering the golden-path requests expected during the bootcamp demo.
- Python 3.12
- Flask 3.x + Flask-SQLAlchemy 3.x
- SQLite (default) or any SQLAlchemy-supported RDBMS via
DATABASE_URL - Pytest 8.x
- Make for reproducible local workflows
app/ Flask application factory, models, and routes
instance/ Local SQLite database (gitignored in real deployments)
migrations/ Simple migration scripts (db.create_all bootstrap)
postman/ Postman collection describing the REST surface
tests/ Pytest suite + fixtures
run.py Entry point used by `make run`
requirements.txt Locked dependency set
Makefile Developer workflow automation
README.md This document
- Python ≥ 3.11 (tested with 3.12)
make- A shell capable of exporting environment variables
git clone https://github.com/<your-account>/student-api.git
cd student-api
# 1. Create the virtual environment and install deps
make install
# 2. Provide configuration (see next section)
cp .env.example .env # if you create one, or export the variables manuallyTip:
make installimplicitly runspython -m venv .venv(via thevenvtarget) and then installs fromrequirements.txt. All subsequent Make targets use the same virtual environment.
The service is configured entirely via environment variables (no hard-coded secrets).
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
✅ | — | SQLAlchemy DSN (e.g., sqlite:///instance/students.db or postgresql://user:pass@host/db). |
LOG_LEVEL |
❌ | INFO |
Python logging level (DEBUG, INFO, WARNING, etc.). |
FLASK_ENV |
❌ | production |
Controls Flask debug mode; the Makefile sets this to development for make run. |
For local development you can drop a .env file (loaded via python-dotenv):
DATABASE_URL=sqlite:///instance/students.db
LOG_LEVEL=DEBUG
This project uses SQLAlchemy’s metadata to create the schema. Run the bootstrap migration whenever you change models or want a fresh database:
make migrateThe command executes migrations/create_tables.py, which builds an application context and calls db.create_all(). You can point DATABASE_URL at SQLite, Postgres, or any other supported database before running the migration.
make runThis command:
- Ensures the virtual environment exists.
- Sets
FLASK_ENV=developmentfor nicer errors. - Starts the API on
http://localhost:5000.
Alternatively, run source .venv/bin/activate && python run.py.
Unit tests are powered by pytest. Each test function receives the client fixture from tests/conftest.py, which wires up a per-test SQLite file for perfect isolation.
make test
# or
source .venv/bin/activate && PYTHONPATH=. pytest| Method | Path | Description | Success Codes |
|---|---|---|---|
| GET | /api/v1/healthcheck |
Versioned health probe | 200 |
| GET | /healthcheck |
Root health probe (no version) | 200 |
| POST | /api/v1/students |
Create a student | 201 |
| GET | /api/v1/students |
List all students | 200 |
| GET | /api/v1/students/{id} |
Fetch a student by id | 200, 404 |
| PUT | /api/v1/students/{id} |
Update name/email/age | 200, 404, 409 |
| DELETE | /api/v1/students/{id} |
Delete a student | 200, 404 |
Validation errors respond with 400 and an {"error": "..."} payload. Duplicate emails return 409 Conflict.
A ready-to-import Postman collection lives under postman/student-api.postman_collection.json. It contains requests for:
- Healthcheck
- Create/List/Get/Update/Delete student flows
Usage:
- Open Postman → “Import”.
- Select the JSON file.
- Optionally override the
baseUrlvariable (defaulthttp://localhost:5000/api/v1).
- Logging configuration is centralized in
app/__init__.py, honoring theLOG_LEVELenv var. routes_v1.pyemits structured logs for create/update/delete success paths and warns on missing/duplicate data.- When running under a process manager (Gunicorn, systemd), configure log aggregation to capture stdout/stderr.
- Add Alembic for schema diffs instead of
db.create_all(). - Introduce pagination for
GET /students. - Extend validation (e.g., email format, age bounds) using Marshmallow or Pydantic.
- Deploy behind Gunicorn with container-ready Dockerfiles and CI pipelines.
Brought to you by the SRE Bootcamp — showcasing clean REST design, Twelve-Factor discipline, and actionable observability.