A template, not a framework: my default Python backend
Every new service I built started with the same ritual: set up the layers, create configs with env prefixes, wire up DI, configure structured logs, remember the outbox, and rebuild the documentation so it would not fall apart by week three. At some point I realized I was dragging the same decisions from project to project, and collected them into a public template: s1t-python-backend-templates.
I built it for the highest useful ratio of functionality to code. It already has what I usually need at the start, but you can fork it, rename it, and remove whatever does not belong in your project.
Two independent services
The monorepo contains two complete services. They share infrastructure, Postgres and Valkey, but do not depend on each other in code. One is a dense backend with an API, non-trivial logic, and event work; the other is a small event-driven microservice that consumes events and handles heavy work in the background.
litestar_backend --- video_uploaded --> event_microservice
<-- video_status ----
litestar_backend: an HTTP API on Litestar with Postgres, a transactional outbox, a composite auth chain (users with argon2id, JWT, API keys, an admin token), an admin panel with a live log viewer, an SSE feed, and Prometheus metrics. event_microservice: a FastStream consumer and a SAQ worker that splits heavy work into jobs and publishes statuses back. Each service is a standalone uv project with its own lock file and Dockerfile: you could move it to a separate repository without changing a line.
The video pipeline is not the product. It is an end-to-end example that shows how the pieces work together.
Structure and checks
Both services keep their layers and bounded contexts strictly separated.

A proper pre-commit setup, ruff, mypy, import-linter, and tests enforce that separation. The same checks run in the Docker gate and CI, so a quick import cannot quietly break a boundary between layers or contexts.
Async, threads, and processes where they belong
It mattered to me that the template shows all three ways of doing work in Python, each where it fits. The API and the consumer live on asyncio. In the worker, CPU tasks go to a process pool, blocking I/O goes to threads, light tasks stay async. Job completion is joined in Valkey, and the status flies back as a single event. No need to reinvent this in every project: three job types sit next to each other, copy the one you need.
Patterns, each end-to-end
Transactional outbox, inbox dedup (at-least-once delivery plus deduplication by event_id gives an exactly-once effect), a composite auth chain, keyset pagination with opaque cursors, an integration-event envelope with event_id/version/occurred_at, graceful drain of background tasks. This is not a README list of pattern names: each one is implemented properly in application context, explained in the docs, and covered by tests. There are ~364 tests across four levels, from unit tests on the domain without mocks to e2e on the full application with testcontainers.
Docs as part of the product
I am especially proud of the documentation. It has a strict, clear structure: architecture.md describes the monorepo as a whole, contract/ pages hold the wire facts, and ADRs live in trees for the project, services, and contexts. That makes it easy to navigate instead of searching the entire repository for the same answer. Doc drift from code is treated as a bug. For daily work there is a Taskfile, pre-commit with gitleaks, docker-compose with bind mounts, and the .env.example / .env.full.example pair.
If this is what you need
MIT license, a Use this template button on the repository, and a landing page with an interactive layer map: sense1tapo4ek.github.io/s1t-python-backend-templates. If you are starting a Python service, take the template and remove what you do not need. If you find a gap, an issue will make it better.