setting-up-python-backends
Installation
SKILL.md
Setting Up Python Backends
This skill is a backend-specialized extension of setting-up-python-projects.
Use it when the repo is primarily a service, API, or worker-oriented backend. Start here for backend repos, then pull generic bootstrap pieces from setting-up-python-projects as needed.
Default Approach
- Choose framework weight:
- FastAPI is the default boring choice for most service APIs.
- Django is justified when auth, admin, sessions, and CRUD-heavy backend surface are obviously large from the start.
- Starlette is for deliberate thin-edge builds, not as a default.
- Start with a reusable core and thin transport:
- routes, workers, schedulers, CLI hooks, and automation call the same core services
- Add infrastructure only when needed:
- relational DB ->
SQLAlchemy 2+Alembic - auth/OIDC/JWT ->
Authlib - outbound HTTP ->
httpx - cache/jobs ->
Redis, and optionallyDramatiqwhen durable background work actually exists
- relational DB ->
- Keep one composition root and one app factory.
Default Stack
FastAPI+uvicornpydanticmodels at the FastAPI HTTP edge;msgspec.Structfor config and non-framework external payload decodingdataclass(frozen=True, slots=True)+Result[T, E]in the coreSQLAlchemy 2+Alembicwhen the service owns relational persistencehttpxfor outbound HTTP- existing repo logging setup via
shared/logging pytest,pytest-asyncio, and integration tests through real app wiringuv,poethepoet,basedpyright, andruff
Keep pydantic request/response DTOs at the HTTP boundary and convert immediately into framework-free typed structures.
Default Layout
src/appname/
api/
app.py
routes/
schemas/
errors.py
domain/
models.py
services.py
errors.py
infrastructure/
config.py
logging.py
db/
models.py
session.py
queries.py
clients/
workers/
__main__.py
bootstrap.py
tests/
integration/
unit/
fixtures/
migrations/
Omit what you do not need. No DB, no db/ or migrations/. No workers, no workers/.
First Files
api/app.pywithcreate_app()api/routes/health.pywith/healthzbootstrap.pywithcreate_services()and app wiringdomain/models.pyand one small service/use-case moduleinfrastructure/config.pyto parse env into typed settings- DB files and migrations only if persistence exists
- one smoke API test and one domain test
Wiring Rules
create_app()assembles only the HTTP layer.bootstrap.pywires settings, DB/session factories, external clients, and services.- No DI framework by default. Use constructor injection and one composition root.
- Keep
__main__.pyor ASGI entrypoints thin.
Boundary Rules
- Request/response schemas are not domain models.
- No
Request,Response,Depends, ORM session, or framework auth objects in domain services. - Convert request data and auth/session state at the edge.
- Workers are another adapter, not a separate business-logic stack.
- CLI/admin scripts should call the same core services when they touch the same workflows.
Migrations and Operations
- If the service owns a relational DB, initialize
Alembicearly. - Add health and readiness endpoints early.
- Keep dev run, lint, test, and migrate commands in Poe tasks.
- Containerize when needed, but keep v1 Linux-first and boring.
Defer by Default
- queues and background-job stacks
- caching layers
- metrics/tracing vendors
- event buses or CQRS
- multitenancy
- API versioning strategy beyond basic room for growth
- generated SDKs and OpenAPI customization
- Kubernetes-specific guidance
Add those only when the project actually needs them.
Handoff
- Use
building-python-backendsfor day-2 backend architecture and service/API/worker shaping. - Use
building-multi-ui-appsif API, CLI, and automation share one core. - Use
writing-python-codefor implementation rules.
Related skills