Production-style FastAPI service showcasing: OpenAPI, Postgres migrations, Redis caching, background jobs, JWT+RBAC auth, rate limiting, tests, Docker Compose, CI, and basic observability (logs/metrics/tracing).
cp .env.example .env
docker compose up --build- API:
http://localhost:8000 - Swagger UI:
http://localhost:8000/docs - Metrics:
http://localhost:8000/metrics - Frontend console:
http://localhost:5173
If you see exec /app/scripts/entrypoint.sh: permission denied, it’s usually because the dev volume mount (.:/app) overrides the executable bit; docker-compose.yml runs it via sh to avoid that.
Requirements: Python 3.11+, Postgres, Redis.
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
alembic upgrade head
uvicorn app.main:app --reloadNote: Python 3.14 is not supported by some common ecosystem packages yet; use Python 3.11–3.13.
If you run pytest from a global Python installation, ensure you’ve installed project deps first (prefer a venv).
Run a worker (background jobs):
celery -A app.worker.celery_app worker -l info- Auth: JWT access tokens; org-scoped RBAC (
owner,admin,member) - DB: Postgres + Alembic migrations
- Redis: caching + fixed-window rate limiting + Celery broker/backend
- Background jobs: webhook processing via Celery
- Observability:
- structured JSON logs (request id)
- Prometheus metrics at
/metrics - OpenTelemetry tracing (optional OTLP exporter; defaults to console exporter)
- optional Sentry error reporting
- Request body limit:
MAX_REQUEST_BODY_BYTES(defaults to1_000_000) enforced viaContent-Lengthwhen present. - Pagination:
GET /orgs/{org_id}/membersandGET /orgs/{org_id}/subscriptionssupportlimit/offsetand returnx-total-count. - Filtering:
GET /orgs/{org_id}/subscriptions?status=active|canceled|past_due. - Webhook idempotency:
/webhooks/stripededupes byWebhookIn.id(preferred) orx-provider-event-id, else a stable payload hash.
- Logs are JSON to stdout; each response includes
x-request-id. - Metrics are exposed at
/metrics(Prometheus scrape target). - Tracing: set
OTEL_EXPORTER_OTLP_ENDPOINT(for examplehttp://localhost:4317) to export spans over OTLP/gRPC. - Sentry: set
SENTRY_DSNto enable error reporting (optional).
/livez: process is up./readyz: dependencies reachable (Postgres + Redis).
See .env.example.
- Secrets: prefer SSM Parameter Store / Secrets Manager; avoid putting secrets directly into Terraform state or CI logs.
- Rotation: rotate
JWT_SECRET_KEYby updating the secret and deploying new tasks; plan a phased rollout if you need to honor existing tokens. - Database and Redis: use managed services (RDS / ElastiCache) in production; provide
DATABASE_URLandREDIS_URLaccordingly.
Minimal ECS/Fargate Terraform is in infra/aws-ecs/README.md:1.
- Register an org + owner user:
curl -sS -X POST http://localhost:8000/auth/register \
-H 'content-type: application/json' \
-d '{"org_name":"Acme","email":"[email protected]","password":"changeme"}'- Use the returned
access_token:
TOKEN="..."
curl -sS http://localhost:8000/me -H "authorization: Bearer $TOKEN"- Add a member (RBAC: admin+; owner needed to assign
owner):
ORG_ID="..."
curl -sS -X POST "http://localhost:8000/orgs/$ORG_ID/members" \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"email":"[email protected]","password":"changeme123","role":"member"}'- Example webhook (enqueue job → updates DB; expects
metadata.org_id):
curl -sS -X POST http://localhost:8000/webhooks/stripe \
-H 'content-type: application/json' \
-d '{"type":"customer.subscription.created","data":{"object":{"id":"sub_123","metadata":{"org_id":"'"$ORG_ID"'"}}}}'Tests expect Postgres + Redis (CI uses service containers).
docker compose up -d postgres redis
pytest -qOr run tests inside the container:
docker compose run --rm --build testIf DATABASE_URL/REDIS_URL are not set, tests will attempt to start ephemeral Postgres+Redis via testcontainers
(requires Docker running and pip install -r requirements.txt).
Run the minimal admin console UI (register/login, members/subscriptions, send test webhook):
docker compose up --build -d frontendOpen http://localhost:5173.
See CHANGELOG.md:1.
GitHub Actions workflow: .github/workflows/ci.yml