Open-source API observability SDK for FastAPI and Flask
Auto-instrument your app with 2 lines of code — get latency percentiles, error rates, status distribution, top routes, and weekly AI-generated anomaly reports powered by Groq.
pip install reqlyReqly is a self-hostable APM tool — a lightweight, honestly-scoped alternative to Datadog/New Relic for Python microservices. You add one call to your app; Reqly captures every request and surfaces real-time metrics plus a weekly AI-generated anomaly report.
import reqly
from fastapi import FastAPI
app = FastAPI()
reqly.instrument(app, service_name="checkout-api")
# Every route is now tracked — latency · error rate · status codesNo decorators. No manual spans. No 50 MB agent. Just one function call.
Metrics — p50 / p95 / p99 latency per route, error rates, status code distribution (2xx / 3xx / 4xx / 5xx), top routes ranked by volume and error rate, live requests/min tile, time windows 1h / 6h / 24h / 7d, per-route drill-down.
AI Insights — weekly anomaly report using z-score detection across a day-of-week × hour-of-day seasonal baseline, with Groq (Llama 3.3-70b) writing the narrative. Falls back to plain-text stats if no API key is set.
"Your
/authendpoint degrades every Monday morning (08:00–10:00), with error rate at 18% vs. a 2% baseline and p95 latency at 1850ms vs. 320ms baseline."
SDK guarantees — fail-open (never crashes your app), non-blocking (background thread, strict HTTP timeouts), bounded queue (2 000 events max), bounded cardinality (route template /users/{id}, never raw path /users/123).
SDK Python · threading · httpx · pure ASGI middleware
Collector FastAPI · asyncpg · APScheduler · slowapi
Database TimescaleDB · hypertables · continuous aggregates
Dashboard React 19 · Vite 8 · Tailwind CSS 4 · Recharts · TanStack Query
AI Groq API · Llama 3.3-70b-versatile
AWS (optional) Lambda · EventBridge · S3 · SAM
Anomaly detection runs as a pure statistics pass first — z-score over a day-of-week × hour-of-day seasonal baseline — before the LLM ever sees the data. The LLM's job is to write a readable narrative, not to decide what's anomalous. Doing it the other way (feeding raw metrics to an LLM and asking it to spot problems) means the model can hallucinate patterns, costs money on every report even when nothing is wrong, and produces output you can't audit. Z-score is deterministic, cheap, and fast; it hands the LLM a pre-filtered list of confirmed deviations and says "explain these." If no Groq key is set, the stats output ships as plain text — the pipeline degrades gracefully without the AI layer.
Reqly runs inside your app's process. If it crashes, it must not crash your app. Every instrumentation path is wrapped so that any internal exception is caught, logged once at WARNING level, and the SDK marks itself as disabled for that request. The background flush thread uses a daemon thread (dies with the main process, never blocks shutdown) and all outbound HTTP calls to the collector carry strict connect + read timeouts — a slow or unreachable collector never blocks a request thread. The in-memory event queue is bounded at 2,000 events; under backpressure, the oldest events are dropped and counted rather than the queue growing unbounded and causing an OOM.
Reqly stores one row per request. At any real traffic volume that's millions of rows fast, and every dashboard query is a time-range aggregation (p95 latency over the last 6 hours, grouped by route). Regular Postgres handles this with a sequential scan or a partial index — both degrade as the table grows. TimescaleDB partitions the same table into time-based chunks automatically (hypertables), so a 6-hour query only touches the relevant chunks. Continuous aggregates pre-compute the per-minute rollups that power the dashboard tiles, so the heavy aggregation runs once on insert, not on every page load. The wire protocol and query language are identical to Postgres — no new ORM, no migration friction.
If Reqly stored the raw request path, /users/1, /users/2, /users/99999 would each become a distinct metric label. A table with a million users generates a million distinct "routes," storage explodes, and every aggregate query becomes meaningless. Instead, Reqly captures the framework's matched route template — FastAPI and Flask both expose this after routing — so every user lookup collapses into a single /users/{id} bucket regardless of traffic volume. Unmatched paths (404s, probes hitting non-existent routes) collapse into a single __unmatched__ bucket rather than polluting the route table with arbitrary strings. Cardinality stays O(number of routes in your app), not O(number of unique URLs ever requested).
Reqly is running live against EventFlow, a Flask event management app.
- Demo app → eventflow-g2h5.onrender.com
- Metrics dashboard → reqly-eventflow-dashboard.onrender.com
- Source → github.com/tanisheesh/EventFlow
To see live metrics: login as Administrator on EventFlow (
admin@eventhub.com/Admin@123) → click Metrics in the nav.
- Website
- PyPI —
pip install reqly - CONTRIBUTING.md — local setup with Docker
- infra/DEPLOY.md — AWS production deploy