tutorial

Monitoring Strawberry GraphQL Python Server with Vigilmon

Strawberry GraphQL gives you type-safe Python APIs — but you need external monitoring to know when they go down. Here's how to add health checks and uptime alerts to your Strawberry server with Vigilmon.

Strawberry is a modern Python GraphQL library that uses Python's type hints to generate your schema — no SDL files, no code generation step. It integrates cleanly with FastAPI, Django, Flask, and ASGI frameworks. But clean integration doesn't include uptime monitoring: a crashed worker, a failed import, or an expired SSL cert won't alert you automatically. Vigilmon watches your Strawberry endpoints, verifies GraphQL execution, and pages you before users hit errors.

What You'll Set Up

  • HTTP uptime monitor for the Strawberry GraphQL endpoint
  • A /health route that verifies the schema and ASGI app status
  • GraphQL execution probe to confirm resolvers are reachable
  • SSL certificate monitoring for production domains
  • Heartbeat for background task workers

Prerequisites

  • Python 3.10+ with Strawberry GraphQL installed
  • A running Strawberry server (FastAPI, Django, or ASGI)
  • A free Vigilmon account

Step 1: Add a Health Endpoint

Strawberry's GraphQL view handles POST /graphql. Add a separate /health route so Vigilmon can probe with a simple GET without sending a GraphQL body.

FastAPI (most common setup)

import strawberry
from strawberry.fastapi import GraphQLRouter
from fastapi import FastAPI
import time

@strawberry.type
class Query:
    @strawberry.field
    def hello(self) -> str:
        return "world"

schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(schema)

app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

START_TIME = time.time()

@app.get("/health")
async def health():
    return {
        "status": "ok",
        "uptime_seconds": round(time.time() - START_TIME, 1),
        "schema": "loaded",
    }

Django

# urls.py
from django.urls import path
from django.http import JsonResponse
import time

START_TIME = time.time()

def health(request):
    return JsonResponse({
        "status": "ok",
        "uptime_seconds": round(time.time() - START_TIME, 1),
    })

urlpatterns = [
    path("health", health),
    path("graphql", GraphQLView.as_view(schema=schema)),
]

ASGI / Starlette

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route, Mount
from strawberry.asgi import GraphQL
import time

START_TIME = time.time()

async def health(request):
    return JSONResponse({"status": "ok", "uptime": round(time.time() - START_TIME, 1)})

app = Starlette(routes=[
    Route("/health", health),
    Mount("/graphql", GraphQL(schema)),
])

Step 2: Add a Schema Validation Check

A deeper health check that actually executes a minimal Strawberry query verifies the schema is not just imported but functional:

import strawberry
from strawberry.scalars import JSON

@app.get("/health")
async def health():
    try:
        # Execute the minimal introspection query against the schema directly
        result = await schema.execute_async("{ __typename }")
        if result.errors:
            return JSONResponse(
                {"status": "error", "detail": str(result.errors[0])},
                status_code=503,
            )
        return {"status": "ok", "uptime_seconds": round(time.time() - START_TIME, 1)}
    except Exception as exc:
        return JSONResponse({"status": "error", "detail": str(exc)}, status_code=503)

schema.execute_async for ASGI apps, schema.execute_sync for synchronous Django views.


Step 3: Add Vigilmon Monitors

Monitor 1: Health Endpoint

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter: https://api.yourdomain.com/health
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

Monitor 2: GraphQL Execution Probe

Strawberry returns HTTP 200 for GraphQL execution errors — verify with a direct POST:

  1. Click Add MonitorHTTP / HTTPS.
  2. Set Method to POST.
  3. Set URL to https://api.yourdomain.com/graphql.
  4. Add header Content-Type: application/json.
  5. Set Request body to {"query":"{ __typename }"}.
  6. Set Expected HTTP status to 200.
  7. Optionally set Response must contain to "data".
  8. Click Save.

Step 4: Monitor SSL Certificates

Python ASGI servers (Uvicorn, Hypercorn, Gunicorn) are typically deployed behind nginx or Caddy for TLS termination. SSL certificate renewals can fail silently:

  1. Open the health endpoint monitor in Vigilmon.
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

Step 5: Heartbeat for Celery and Background Workers

Strawberry APIs commonly pair with Celery for async tasks (sending emails, processing uploads, running scheduled jobs). If a Celery worker crashes, it fails silently. Use a Vigilmon heartbeat:

  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set the expected ping interval to match your task frequency.
  3. Copy the heartbeat URL.
  4. Call the heartbeat URL at the end of each task:
import requests

@celery_app.task
def process_data():
    # ... task logic ...
    do_the_work()

    # Signal success to Vigilmon
    requests.get(
        "https://vigilmon.online/heartbeat/YOUR_KEY",
        timeout=5,
    )

For scheduled Celery beats, add the heartbeat call inside the task body so it only pings on successful completion — a stuck task won't ping.


Step 6: Gunicorn / Uvicorn Worker Health

Strawberry FastAPI apps typically run under Uvicorn or Gunicorn with multiple workers. If a worker exits without restarting, the remaining workers serve traffic but at reduced capacity. Add a TCP port monitor as a secondary check:

  1. Click Add MonitorTCP Port.
  2. Set Host to your server IP.
  3. Set Port to 8000 (or whichever port Uvicorn binds to).
  4. Set Check interval to 1 minute.
  5. Click Save.

This catches cases where all workers die and the port stops accepting connections, even if nginx is still running.


Step 7: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add Slack, email, or PagerDuty.
  2. Set Consecutive failures before alert to 2 — Uvicorn workers restart on failure and a single probe may catch the restart window.
  3. Suppress alerts during deployments:
# Pause monitoring during rolling restart
curl -X POST https://vigilmon.online/api/maintenance \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"monitor_id": "YOUR_MONITOR_ID", "duration_minutes": 5}'

# Deploy
uvicorn app:app --reload

Summary

| Monitor | Target | What It Catches | |---|---|---| | Health endpoint | /health | Process crash, import error | | GraphQL POST | /graphql with { __typename } | Resolver failure, schema error | | SSL certificate | API domain | TLS cert expiry | | TCP port | :8000 (Uvicorn) | All workers down | | Cron heartbeat | Celery task | Worker crash, missed schedule |

Strawberry's type-safe schema generation catches many bugs at development time — Vigilmon catches the ones that slip through to production. With a health endpoint, a live GraphQL probe, and Celery heartbeats in place, you'll have full visibility into your Python GraphQL stack.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →