API Gateway

API Gateway · Rate Limiting · Analytics · Cloudflare Workers

Auto-refreshes every 30s

—
Requests (24h)
—
Error Rate
—
Avg Latency
—
Active Keys (24h)
Requests per hour — last 24h  ■ errors

Top Endpoints

PathHits

Recent Requests

MethodPathStatusms
Request
Response
Fire a request to see the response.
Request Log
Waiting for requests…
An API Gateway is a single entry point that sits in front of your backend services. Every client request flows through it — the gateway handles cross-cutting concerns (authentication, rate limiting, logging, routing) so individual services don't have to. This one runs entirely on Cloudflare Workers at the edge — no origin server, sub-millisecond cold starts.
Request Flow
Client │ X-API-Key: demo-key-alpha ▼ Gateway Worker (api.zyxwonderland.xyz) ├─ 1. Auth check — valid key → keyed tier | no key → anon tier | bad key → 401 ├─ 2. Rate limit — keyed: 120 req/min | anon: 20 req/min | over limit → 429 ├─ 3. Route match — /api/hello, /api/time, /api/echo, /api/slow, /api/fail ├─ 4. Handler — generate response, measure latency └─ 5. Log to DO — method, path, status, latency, key_id, timestamp │ ▼ AnalyticsDO (Durable Object — SQLite) └─ /analytics/summary, /analytics/timeseries, /analytics/recent
API Routes
MethodPathAuthDescription
GET/api/helloOptionalReturns a greeting and timestamp
GET/api/timeOptionalReturns current UTC time (ISO + Unix)
ANY/api/echoOptionalReflects method, path, query params, and body
GET/api/slowOptionalSimulates 200–800ms upstream latency
GET/api/failOptionalAlways returns 500 (for testing error logging)
GET/analytics/summaryNoneAggregated metrics for the last 24h
GET/analytics/timeseriesNoneHourly request counts (last 24h)
GET/analytics/recentNoneLast 20 logged requests
Rate Limit Headers
Every API response includes X-RateLimit-Limit and X-RateLimit-Remaining. Limits reset every 60 seconds. Authenticated requests (X-API-Key) get 120 req/min; anonymous requests get 20 req/min. Exceeding the limit returns 429 Too Many Requests.
Demo API Keys
Two demo keys are configured: demo-key-alpha and demo-key-beta. Use either in the X-API-Key header or in the Test Console above. All requests — keyed or anonymous — are logged to the dashboard.
Data Model — AnalyticsDO SQLite Schema
Table: requests id INTEGER PRIMARY KEY AUTOINCREMENT method TEXT NOT NULL -- GET, POST, PUT, DELETE path TEXT NOT NULL -- /api/hello, /api/echo, … status INTEGER NOT NULL -- 200, 400, 429, 500, … latency_ms INTEGER NOT NULL -- wall-clock handler time key_id TEXT NOT NULL DEFAULT '' -- empty string = anonymous ts INTEGER NOT NULL -- Unix ms Indexes: (ts) · (path, ts) · (status, ts) Rate-limit counters (DO KV storage, not SQLite) Key: rl:{identity}:{minute-slot} Value: request count in that minute window Slot: Math.floor(Date.now() / 60000) TTL: previous slot deleted on each write
Design Decisions
Why Durable Objects instead of Workers KV for analytics?
KV is eventually consistent and optimised for reads at the edge. Writing per-request metrics to KV would be expensive and could return stale counts. A Durable Object serialises all writes through a single instance with a SQLite database — reads and writes are always consistent, and SQL aggregations (GROUP BY, COUNT, AVG) are fast.
Why per-minute rate limiting with DO storage?
Each rate-limit check is a single DO storage read + write. Using the current minute as a slot key means counters reset automatically — no background cleanup job needed. The previous slot is pruned on each write to keep storage bounded. The DO's single-instance guarantee means two concurrent requests cannot both read "count = 0" and both increment to 1; writes are serialised.
Fire-and-forget logging.
The gateway logs each request with stub.fetch(…) without awaiting the result. This keeps response latency unaffected by the write path — the Worker returns the response to the client immediately. The Cloudflare runtime keeps the Worker alive long enough to complete the background fetch before the isolate is terminated.