Case · Backend · Python
catalog-api: a catalog API with search
A product catalog API on Python 3.12 and FastAPI: SQLite with FTS5 full-text search (bm25 ranking), facets by category, price, availability, tags and attributes, cursor pagination, ETag, CSV import and export, price history, API keys with roles and an audit log. The storefront and the admin panel are served by the app itself, with no framework. A side project.
- Python
- FastAPI
- SQLite
- FTS5
- pytest
- ruff
- mypy
- bandit
- Docker
- GitHub Actions
01 · How it looks
Screenshots


02 · About
What it is and why
catalog-api is a product catalog API on Python 3.12 and FastAPI with a storefront and an admin panel served by the app itself. A side project.
The storage is SQLite: full-text search through FTS5 with bm25 ranking, facets by category, price, availability, tags and attributes, signed cursor pagination. Access is by API keys with the roles admin, editor and reader: a key is shown once and only its hash is stored. The demo mode SEED_DEMO=1 brings up 300 synthetic products.
Limitations
There is no live version: Cloudflare does not run a Python server with SQLite. Run it locally, in Docker or on your own VPS.
The request limiter lives in process memory: with several workers the limit multiplies. SQLite is built for a single writer process. There is no Russian morphology and no typo correction.
Images are not re-encoded and metadata is kept as is. Facets are not disjunctive; the total is counted exactly on every request, which has to be replaced at millions of products.
Demo keys are public and work only with SEED_DEMO=1. Not checked: running behind a real reverse proxy with TLS, browsers other than Chromium, and screen readers. The load measurement is a single one, on one machine.
What is inside
- FTS5 search with bm25, facets, sorting and cursor pagination; ETag for conditional requests
- CSV import and export, price history, image upload with signature and limit checks, an audit log
- API keys with roles, a request limiter, strict security headers; OpenAPI in dev mode and off in production
- A storefront and an admin panel without a framework, sitemap, robots, llms.txt and OG tags
- 511 tests, 96% coverage; ruff, mypy --strict, bandit, pip-audit and gitleaks are clean
- Load measurement: 339 requests/s, p95 50 ms at 8 connections (Windows, a single process)
- A Docker image on python:3.12-slim, user uid 10001, a HEALTHCHECK, graceful shutdown on SIGTERM
03 · How to run
Run it locally
git clone <repository on request> catalog-api
cd catalog-api
python -m venv .venv && .venv/bin/pip install --require-hashes -r requirements.lock
SEED_DEMO=1 python -m app # http://127.0.0.1:8110, admin at /admin04 · Code
The repository is private
The source is in a private repository. Message me on Telegram and I will open access.
Request the code