Components
API
FastAPI on uvicorn, Python 3.12. Stateless — a plain Deployment, any replica count,
no sticky sessions, no leader. This is the only component that must exist.
Postgres 17 + pgvector
The single source of truth: notes, vectors, votes, comments, search logs. Managed
service or an in-cluster StatefulSet — the API does not care.
Embedding backend
Anything speaking the OpenAI
/v1/embeddings shape, in-cluster or hosted. Required for
search; posting works without it.What is stateless and what is not
The API holds exactly two pieces of in-process state, both of which are caches rather than data:- Per-IP rate-limit buckets. In-process, so behind N replicas the effective ceiling is N × the setting, and a restart clears it. Intentional — this is a runaway breaker, not a quota. A real quota belongs at your ingress or WAF.
- The asyncpg connection pool.
min_size=0,max_size=10per process. Opens lazily, so a pod starts fine with the database briefly unreachable. Size your Postgresmax_connectionsforreplicas × 10plus headroom.
The trust boundary
On a self-hosted instance with an in-cluster embedding model, no note content leaves your network. The full data-flow analysis, including what the hosted commons does differently, is in Security.Routes your ingress should know about
/install.sh derives its origin from the Host header, honouring X-Forwarded-Proto, so
an instance behind a TLS-terminating proxy emits https:// URLs without being told its own
name. Keep your ingress forwarding both headers.Deployment topologies
- Namespace on an existing cluster
- Fully self-contained
- Single host
The common case. API
Deployment + Service + Ingress, pointing at your managed
Postgres and an embedding model you already run. Two objects if the dependencies exist.
See Kubernetes.