fastapi
Technical notes on web development, DevOps, and AI integration.
17 articles
- 17:58backend
An Honest Contract for Batch Ingest Endpoints
One success number for a whole batch hides partial failure. Per-item created/updated/unchanged/rejected status makes it visible.
TL;DR: The new POST endpoint replaces a single batch status with per-item outcomes plus a summary so partial failures are visible. Guards cap payload size and item count, rate-limit per source, and fail closed with proper status codes including constant-time auth. Each item is marked created, updated, unchanged or rejected via a content hash, with an audit row for every request.
#fastapi#api#rest-api - 23:55security
A Rate Limit Alone Was Not Enough for This Login Endpoint
Sliding window dual keying plus dummy-hash timing equalization: two separate defenses for one login endpoint.
TL;DR: A live smoke test confirmed the login rate limiter kicks in with HTTP 429 and a Retry-After header on the eleventh attempt per minute. The real fix pairs that throttling with timing equalization, running bcrypt against a dummy hash so response speed never reveals whether an account exists. Docs endpoints are now dev-only, and duplicate registrations return 409.
#security#fastapi#python - 17:43backend
A FastAPI Skeleton of Layer Contracts, Not Empty Folders
Four folders with empty __init__.py files carry real contracts: layer boundaries, a unit of work per request, JWT tenant claims, and the 72-byte bcrypt gate.
TL;DR: Four seemingly empty folders establish layered contracts in a FastAPI skeleton, keeping business logic, technical details, and HTTP translation cleanly separated. A yield-based dependency handles transactions per request, committing only on success so multi-table use cases stay atomic. Multi-tenancy rides in JWT claims, bcrypt limits get enforced at the validation gate, and swappable signal sources await future needs.
#fastapi#python#jwt - 02:34backend
Semantic Search on a 1GB VPS Without a Vector DB
Pure-Python cosine, vectors in MariaDB postmeta, embeddings computed locally. Semantic features with no new service on a small server.
TL;DR: Running a blog on a 1GB VPS rules out a vector database, so the author computes bge-m3 embeddings locally via Ollama and stores them as JSON in MariaDB postmeta. Related-article matching and dup-checks use pure-Python cosine similarity, fast enough for around 100 articles. Lesson: for small blogs, skip Qdrant or pgvector until scale demands it.
#python#fastapi#embedding - 21:51ai
What a Security Audit Found in My Chat AI
A security audit uncovered 11 findings in the chat AI pipeline, from cache keys to prompt injection.
#prompt-injection#redis#fastapi - 20:07ai
The follow-up question my AI chat couldn't answer
Chat follow-up questions without server sessions: history lives in localStorage, gets resent per ask, and the backend rebuilds the prompt under a char budget.
#fastapi#llm#stateless - 19:34ai
The AI chat now knows what I am working on
The blog's AI chat now answers 'what are you working on' from local commit history: a narrow port, a version namespace bump, and term mining.
#fastapi#redis#cache-invalidation - 14:57backend
Answers That Survive an LLM Outage
When the LLM router died, a meta fallback event arrived and the visitor still got an answer. Here's the three-part chain behind it.
#fastapi#redis#llm - 14:34backend
The AI Search Had to Learn Its Own Site
Typing hai used to kill the AI search with no_results. The culprit was MariaDB's fulltext word-length floor, not a broken prompt.
#fastapi#mariadb#llm