Skip to main content

Structured health and readiness check system for FastAPI

Project description

fastapi-watch

Structured health and readiness checks for FastAPI.

Test, Build & Publish PyPI version Supported Python versions PyPI Downloads


Add /health/* endpoints to any FastAPI app in minutes. Probes observe real traffic — no synthetic requests — and stream live results to a built-in dashboard and Prometheus endpoint.

For full documentation see DOCS.md.


Installation

pip install fastapi-watch

# With service-specific extras
pip install "fastapi-watch[postgres,redis]"
pip install "fastapi-watch[all]"

zsh users: quote extras to avoid glob expansion: pip install "fastapi-watch[redis]"

Available extras: postgres, mysql, sqlalchemy, redis, memcached, rabbitmq, kafka, mongo, celery


Quick start

from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi_watch import HealthRegistry
from fastapi_watch.probes import PostgreSQLProbe, RedisProbe

app = FastAPI()
registry = HealthRegistry(app)

# Infrastructure probes
registry.add(PostgreSQLProbe(url="postgresql://user:pass@localhost/mydb"))
registry.add(RedisProbe(url="redis://localhost:6379"), critical=False)

@asynccontextmanager
async def lifespan(app):
    # Automatically monitor every route — no decorators needed
    registry.discover_routes(tags=["api"], max_error_rate=0.05)
    registry.set_started()
    yield

app = FastAPI(lifespan=lifespan)

Every route is now monitored with real-traffic data. Health endpoints are live at /health/*.


Endpoints

Endpoint Purpose Status
GET /health/live Liveness — process is alive always 200
GET /health/ready Readiness — all critical probes passing 200 / 503
GET /health/status Full probe detail 200 / 207
GET /health/dashboard Live HTML dashboard (SSE) 200
GET /health/metrics Prometheus text format 0.0.4 200
GET /health/history Rolling result history per probe 200
GET /health/alerts Probe state-change log 200
GET /health/startup Startup gate; 503 until set_started() 200 / 503
GET /health/ready/stream SSE stream of readiness stream
GET /health/status/stream SSE stream of full probe detail stream
GET /health/maintenance Maintenance mode status 200
POST /health/maintenance Enable maintenance mode 200
DELETE /health/maintenance Disable maintenance mode 200

The prefix defaults to /health and is configurable: HealthRegistry(app, prefix="/ops/health").


Route monitoring

The fastest way to monitor your API is auto-discovery. fastapi-watch monitors real traffic — no synthetic polling, no wasted requests.

discover_routes — monitor everything at once

One call after all routers are included. Every route gets a passive probe with no decorators required.

@asynccontextmanager
async def lifespan(app):
    registry.discover_routes(
        tags=["api"],              # tag all probes for filtering
        max_error_rate=0.05,       # alert if error rate exceeds 5%
        include_paths=["/api/*"],  # whitelist — only monitor these routes
        exclude_paths=["/api/admin"],  # exclude even if include_paths matches
    )
    registry.set_started()
    yield

Auto-discovered probes use GET /items/{id} style descriptions so they're immediately recognizable in the dashboard.

watch_router — monitor a specific router

Scope monitoring to one router with its own tags, thresholds, and criticality. Call it after app.include_router.

app.include_router(users_router, prefix="/users")
app.include_router(orders_router, prefix="/orders")

registry.watch_router(users_router, tags=["users"], max_error_rate=0.01)
registry.watch_router(orders_router, tags=["orders"], critical=False)

Then filter health checks by router: GET /health/ready?tag=users

@probe.watch — full control on one route

For routes that need custom thresholds, a specific name, or tight SLOs.

from fastapi_watch import FastAPIRouteProbe

checkout_probe = FastAPIRouteProbe(
    name="checkout",
    description="Payment processing",
    tags=["payments"],
    max_error_rate=0.001,
    slow_call_threshold_ms=200,
)

@app.post("/checkout")
@checkout_probe.watch
async def checkout():
    ...

registry.add(checkout_probe)

Priority system

When all three approaches are used together, each route is monitored exactly once — the highest-priority wins:

Priority Method When to use
1 — highest @probe.watch One route needs its own thresholds or name
2 watch_router A whole router shares settings
3 — lowest discover_routes Catch-all for everything not handled explicitly

discover_routes and watch_router skip any route already covered by a higher-priority method — no conflicts, no double counting.


Tag-based filtering

All probes accept tags=[...]. FastAPI route tags (@app.get("/items", tags=["store"])) are automatically merged in. Filter any endpoint by tag:

GET /health/ready?tag=payments         # only payment probes
GET /health/status?tag=users,orders    # users OR orders probes
GET /health/status/stream?tag=payments # filtered live stream

The dashboard shows tag chips on each probe card and a clickable filter bar to isolate groups at a glance.


Infrastructure probes

from fastapi_watch.probes import PostgreSQLProbe, RedisProbe, HttpProbe, TCPProbe

registry.add(PostgreSQLProbe(url="postgresql://..."))
registry.add(RedisProbe(url="redis://..."), critical=False)
registry.add(HttpProbe(name="payments-api"), critical=True)
registry.add(TCPProbe(host="kafka.internal", port=9092))

Passive probes observe real calls — use @probe.watch on any function to track its latency, error rate, and throughput without making synthetic requests.


Alerting

from fastapi_watch.alerts import SlackAlerter, PagerDutyAlerter

registry = HealthRegistry(
    app,
    alerters=[
        SlackAlerter(webhook_url="https://hooks.slack.com/..."),
        PagerDutyAlerter(routing_key="your-routing-key"),
    ],
)

Webhook URLs are validated at construction time — private/loopback/link-local IP targets are rejected to prevent SSRF.


Security

Health endpoints are publicly accessible by default — set auth in production:

registry = HealthRegistry(app, auth={"username": "ops", "password": "secret"})

See DOCS.md — Security for auth callables, SSRF protection on webhook alerters, probe error message handling, and probe name restrictions.


License

MIT


Claude used to write README, code annotation, help with test case coverage, and clean up my messy thoughts into readable code.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_watch-1.5.11.tar.gz (114.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_watch-1.5.11-py3-none-any.whl (75.2 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_watch-1.5.11.tar.gz.

File metadata

  • Download URL: fastapi_watch-1.5.11.tar.gz
  • Upload date:
  • Size: 114.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastapi_watch-1.5.11.tar.gz
Algorithm Hash digest
SHA256 2069ba9e464362ecd47f80166e111be818663f6706175904b91fc6999e15bb92
MD5 5cd72efb4c50a3782c1ec4e1d4d89e63
BLAKE2b-256 e9803762ab53fa20f210fb7cb994d5cb547ce47e8737b8542ea77886da4bb228

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_watch-1.5.11.tar.gz:

Publisher: publish.yml on rgreen1207/fastapi-watch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastapi_watch-1.5.11-py3-none-any.whl.

File metadata

  • Download URL: fastapi_watch-1.5.11-py3-none-any.whl
  • Upload date:
  • Size: 75.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastapi_watch-1.5.11-py3-none-any.whl
Algorithm Hash digest
SHA256 1a61875b1b7a08645567c5e220ba45152eb7d46c5e8c1dff00bad3ecdfc85da7
MD5 822f09b209faa381eabd0bbe8e5d18e5
BLAKE2b-256 55af8ba3dfd72bb6fc90c8d12d1f6be5ec0ff43bb852df2a13c7fc51fa8633a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_watch-1.5.11-py3-none-any.whl:

Publisher: publish.yml on rgreen1207/fastapi-watch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page