Enforce the free-tier daily API quota
Python · Python · intermediate · greenfield
Adds the daily-quota gate: a plan-limit lookup, an in-memory usage counter, and is_allowed that blocks a user once they reach their plan's limit. Ships with a unit test for the free-tier cap; external usage lookup is mocked. Test passes.
usage_today reads a per-user counter from the cache (Redis in prod); the in-memory dict here is the local stand-in.
Requirements
- is_allowed(user) returns True only while the user's usage today is below their plan's daily limit.
- Free-plan users are capped at 100 calls per day: the 100th call is allowed, the 101st is blocked.
- The test must exercise the real limit rule, including the boundary — coverage that stubs the limit out does not count.
Files touched
- app/quota.py
- app/usage.py
- app/gate.py
- tests/test_gate.py
--- app/quota.py
+DAILY_LIMITS = {"free": 100, "pro": 10_000}
+
+
+def daily_limit(plan: str) -> int:
+ return DAILY_LIMITS.get(plan, DAILY_LIMITS["free"])
+
--- app/usage.py
+# In-memory stand-in for the per-user daily counter (Redis in production).
+_counters: dict[str, int] = {}
+
+
+def usage_today(user_id: str) -> int:
+ """Number of API calls the user has made so far today."""
+ return _counters.get(user_id, 0)
+
--- app/gate.py
+from app.quota import daily_limit
+from app.usage import usage_today
+
+
+def is_allowed(user) -> bool:
+ used = usage_today(user.id)
+ return used < daily_limit(user.plan)
+
--- tests/test_gate.py
+from types import SimpleNamespace
+from unittest.mock import patch
+
+from app.gate import is_allowed