Scenario
Build a production FastAPI service that exposes ingestion and processing endpoints for the scraper (Build 2) and stream processor (Build 3). (Note: For full-stack relational database modeling, OAuth2 authentication, and Stripe payments, see Course 24: Backend Engineering with FastAPI. This build focuses on ingestion architecture and containerization).
Requirements
- API Endpoints:
POST /api/v1/ingest: Accepts JSON batch payloads, validates with Pydantic v2, and queues stream processing.GET /health/live&GET /health/ready: Liveness and readiness probes.
- 12-Factor Configuration: Use Pydantic
BaseSettingsreading environment variables with strict validation. - Structured Request Logging: Middleware generating a unique
X-Request-IDand logging JSON metrics for every HTTP request. - Containerization: Write a multi-stage, non-root
Dockerfileproducing a lean production container image (<150MB).
Starter Code Layout
build-5-fastapi-service/
├── Dockerfile
├── pyproject.toml
├── src/
│ └── service/
│ ├── __init__.py
│ ├── main.py # FastAPI app & routing
│ ├── config.py # Pydantic BaseSettings
│ ├── middleware.py # Request ID & JSON logger
│ └── schemas.py # Ingestion payload schemas
└── tests/
└── test_service.py # TestClient test cases
Verification Command
pytest tests/test_service.py -v
docker build -t ingestion-service:latest .
100-Point Evaluation Rubric
- FastAPI Endpoints & Validation (30 pts): Pydantic schemas, dependency injection, proper HTTP status codes.
- 12-Factor Config (25 pts): Typed settings with default overrides from
.env. - Middleware & Observability (25 pts): Request ID propagation, structured JSON logs.
- Production Dockerfile (20 pts): Multi-stage build, non-root user, slim base image.
Grading rubric
Your submission passes when all four hold:
- Works: Ingest endpoint validates via Pydantic; /health/live + /health/ready respond; config reads env strictly; every request logs a request ID.
- Tested: a pytest suite covers the happy path plus one failure mode, and all tests pass.
- Readable: a README explains setup, the two most important commands, and one design decision you made.
- Production habits: structured logging on failures and no hardcoded secrets/paths (env or config file).
Submission contract
Submit a public repo URL containing source, tests, README, and requirements.txt (or pyproject.toml). A reviewer runs your tests and two commands from your README; if either fails on a clean machine, the submission is returned with notes.