A cloud bill is an architecture diagram you can read in dollars. Most of the ugly ones come from the same mistake: a third-party call, a render, or a query sitting inside the user request path, where its cost multiplies by traffic instead of by work.
How we actually work
Cost must not scale with traffic. Kickoff polls its data vendor once in the background; every user reads the cache. A single upstream call returns every live match. The API bill therefore tracks how much football is being played, not how many people are watching — 100 users and 100,000 users cost the same. That property is stated in the codebase as a rule with the one line of code that would destroy it called out by name.
Cache TTLs come from the value, not from a config convention. How long an answer stays true depends on the answer. A finished match is final forever. The same call for a match in play is worth thirty seconds. A lineup is frozen once announced, but an empty one means “not announced yet” and must be re-asked. Head-to-head is history and cannot change at all — it was being re-fetched on every view until it wasn’t. Concurrent requests for the same key are deduplicated, so ten people opening the same match at kickoff produce one upstream call.
The measured result on Kickoff’s two most expensive page types:
| Page | Vendor calls per view, before | After |
|---|---|---|
| Match | 6 | 0 on a warm cache |
| Team | 6 | 0 on a warm cache |
Build-time cost counts too. Prerendering every competition × season on Kickoff would have meant ~500 upstream requests per deploy — enough to exhaust a small plan’s monthly quota before a single user arrived. Those render on first request instead, so you pay only for what someone opens.
Swappable infrastructure by interface, not by rewrite. Memory cache and Redis
sit behind one Cache interface. SQLite and Postgres behind one DATABASE_URL.
Whinchat’s store-and-forward relay moves to Postgres with the API contract
unchanged. Local development needs no cloud account; production changes a
selector, not a codebase.
Migrations, not auto-create, once the schema matters. Clepora carries 43 versioned Alembic migrations, each one dry-run inside a transaction against the live schema before it is applied. Schema change is a reviewable artifact.
Health you can act on. /api/health exposes poller state, cache hit rate,
scheduled-job history and automated monitor findings. A cache hit rate drifting
toward zero means pages have gone back to costing a vendor request per reader —
that is a number someone should see before the invoice does.
Containers and pipelines as the default. Docker and Compose for local parity
(Postgres, Redis, MinIO, workers, app), GitLab CI for build and test, pinned
requirements with lockfiles, gitleaks in the pipeline.
What that produces
| Product | Infrastructure |
|---|---|
| Kickoff | Cache-first architecture, cron-driven polling, 65 competitions, 103 E2E tests |
| Clepora | Docker Compose stack, 43 Alembic migrations, work split across render/publish/live worker queues, GitLab CI |
| Whinchat | Python + SQLite spine that boots on the standard library alone and lifts to Postgres unchanged |
Engage us for
- Cloud cost review — find the calls sitting in the request path and get them out.
- Deployment & CI/CD — containerize, pipeline, migrate, monitor.
- Architecture review — before you commit to a design whose bill you cannot predict.