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 Monitor → HTTP / 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 Monitor → Cron 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 Monitor → TCP 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 →