The trick is in the key layout. Conceptually:
quota:{tenant}:{feature}:2026-05
When a new month starts, you write to a new key. You don't wipe the old one. "Reset" becomes a naming switch, not a data migration. No month-end task can fail, and you don't have to think about timezone edges either.
Per-feature matters because feature cost varies wildly. If you only meter the total, heavy features crowd out light ones, and everyone ends up feeling like the limit is unfair.
The discipline in quota.py is small but strict:
- Check the limit before doing the work
- Only record after the operation actually succeeds
- Keep the key format fixed — no variants
- On failure, do not write a guess
"No drift" isn't an algorithmic property. It's a write-semantics property. The moment your counter writes are scattered across modules — each doing it slightly differently — you've already lost.
This design is not universal. It fits products with low-to-medium complexity, multi-tenant but with bounded concurrency. If you later outgrow it, swapping in a real metering pipeline is a clean migration, because the surface is small.
My one piece of advice: get the quota schema right in the first version. Adding it later almost always drags pricing, routing, and error semantics into the rewrite with it.
Related
Source: foxck016077/apify-gmail-inbox-intel — MIT, per-feature quota design in Apify KV store without DB migrations, cron jobs, or drift-prone counters.
Cold-start follow-up: the actor that uses this KVS quota pattern went live on Apify Store 4 days ago — the funnel data and what I would change, in case the quota pattern is the easy part and the launch funnel is the hard part for you too.
Discussion question: For per-feature quotas, would you trade strict real-time accuracy for simpler KV-based durability, or do you require stronger consistency guarantees?
Update (May 19): This quota pattern ships in the Actor — live at apify.com/foxck/gmail-inbox-intel (free MIT, paste 3 OAuth fields, get stalled threads ranked). Day 6 of the open-build: the companion PDF switched to pay-what-you-want from 1ドル.
Day 7 update (later May 19): I shipped a product pivot — the Gumroad listing above is now a Self-Host Bundle for engineers (full Actor source + docker-compose.yml + 5-min OAuth setup), PWYW from 5ドル suggested 19ドル. The original PDF still ships inside as a bonus. Same URL.
Day 7 write-up with the funnel audit that triggered the pivot: funnel audit found 7 of 9 articles had no buy link, then I pivoted the product.
Sample report preview: Friday Triage gist — anonymized 10-thread example of the 99ドル Done-For-You triage output. Grounded in r/sales 1tdngew (49 comments on re-engaging cold prospects) and r/smallbusiness 1td0827 (60-comment thread, top reply at 61 score: "holding 50 open loops in your head").
More from the shop:
Read the latest checkpoint: Day 16 — +51 reader spike in 85 min, 0 sales
Day 18 — pbot v1 dev preview shipped
After 18 days of this ZERO-TEN cold start: 9ドル PDF killed at Day 17, pivoted to pbot — a one-click personal knowledge bot you install on your own machine. Talk to it from LINE / Telegram / Zalo on your phone.
v1 dev preview is real: 93 MB macOS .dmg packaged, 15k-chunk SQLite FTS5 queries in 0-3 ms, Anthropic real calls with source citations, daemon auto-start on boot. Day 18 deep dive: the 7-line bigram fix for Chinese search.
Join the pbot waitlist (29ドル · first-100 get -30% → 20ドル) →