Case study · API keys · rate limits · logs
API Management Platform
Developer console for an API product: API keys, per-key rate limits and a searchable log of every request.
Keys are stored as hashes and shown once; logging is batched off the request path.
- Type
- Personal open-source project
- Automated tests
- 38 (pytest)
- Built with
- Python · FastAPI · SQLAlchemy
- Live demo
- Runs locally — not hosted

Overview
What it does
Register, issue API keys, call a protected API with them, and see every request that was made — with its status, latency and the reason it was refused. It isn't an API gateway; it's the part of one that has to be right: key handling, quota enforcement and an audit trail you can query.
Problem
API products need keys that can't be leaked from the database, limits one customer can't use up for another, and logs that don't slow down the API they measure.
Solution
Keys are 256-bit random values stored only as SHA-256 digests. A middleware authenticates, applies a per-key sliding window and attaches X-RateLimit headers; request logs go onto an in-memory queue and are written in batches by a background task.
Screenshots
From the running application
Architecture
How the pieces fit
- Client → Key middleware
- Developer console → Management API
- Key middleware → Rate limiter
- Rate limiter → /v1 endpoint
- Rate limiter → Log queue
- Log queue → Database
- Management API → Database
- Core service
- External system
- Storage / entry point
Core features
What's in it
API keys
dev_live_… keys shown once, stored as a digest with a display prefix; revoke keeps history, delete keeps logs.
Per-key rate limits
Sliding 60-second window, X-RateLimit-Limit/Remaining/Reset on every response and Retry-After on 429.
Request logs
Key, method, path, status, latency, client IP and refusal code — never request bodies.
Usage analytics
Requests today/this month, success rate, average latency and a 24-hour chart, computed from the log table.
Two auth schemes
X-API-Key for machines on /v1, an HttpOnly session for humans on /api — a leaked key can't mint keys or read logs.
One error envelope
Every failure, including validation errors, leaves as {"error": {"code", "message"}}.
Technical decisions
Interesting problems, and how they're solved
- 01
Sliding window, per key
One customer's burst can't spend another's budget, and a caller can't double the quota by straddling a minute boundary.
- 02
Logging off the request path
A non-blocking queue, one batched INSERT per flush, and dropped-and-counted logs if the queue fills — never a slower API.
- 03
Digest lookup
The raw key is never stored, logged or compared as a string; the digest makes the lookup one indexed query.
def check(self, key: str, limit: int) -> RateLimitResult:
now = time.monotonic()
hits = self._hits[key]
# Drop everything that has fallen out of the window.
cutoff = now - self.window
while hits and hits[0] <= cutoff:
hits.popleft()
if len(hits) >= limit:
retry_after = max(1, int(self.window - (now - hits[0])) + 1)
return RateLimitResult(
allowed=False,
limit=limit,
remaining=0,
reset_after=retry_after,
retry_after=retry_after,
)
hits.append(now)
reset_after = max(1, int(self.window - (now - hits[0]))) if hits else self.window
return RateLimitResult(
allowed=True,
limit=limit,
remaining=max(0, limit - len(hits)),
reset_after=reset_after,
)Stack & skills
Built with
Technology
- Python
- FastAPI
- SQLAlchemy
- asyncio
- PyJWT
- React
- TypeScript
- Vite
- Tailwind CSS
What this project demonstrates
- API design
- Rate limiting
- Key management
- Async background tasks
- Observability
Repository & demo
Run it yourself
Register a local account, create a key and use make traffic to generate real requests against the demo API.
No public live demo is hosted. Everything below runs locally with Python 3.12+ and Node 20+.
$ git clone https://github.com/Moeijiro/api-management-platform.git
$ cd api-management-platform
$ make install
$ make api
$ make web
$ make traffic # generate sample requests
Have a project in mind?
I build APIs, automation systems, Discord integrations and full-stack applications. Tell me what it should do and I'll tell you how I'd build it.



