tutorial

WPGraphQL Monitoring with Vigilmon

WPGraphQL transforms any WordPress installation into a headless GraphQL API. If your frontend — whether Next.js, Gatsby, or a mobile app — depends on the WPG...

WPGraphQL transforms any WordPress installation into a headless GraphQL API. If your frontend — whether Next.js, Gatsby, or a mobile app — depends on the WPGraphQL endpoint, an outage there is an outage for your users. Monitoring a GraphQL endpoint is slightly different from a plain REST health check: you need to verify the API responds to a real query, not just that the /graphql URL returns 200.

This tutorial covers monitoring WPGraphQL with Vigilmon:

  • Polling the /graphql endpoint with a lightweight introspection query
  • Keyword monitoring to catch GraphQL-level errors
  • Webhook alerts for your team

Prerequisites

  • WordPress with WPGraphQL installed and activated
  • A public /graphql endpoint (default: https://yoursite.com/graphql)
  • A free account at vigilmon.online

How WPGraphQL health checks work

Unlike REST APIs, GraphQL always returns HTTP 200 — even when the query fails. The error is embedded in the JSON response body:

{
  "errors": [
    { "message": "Internal server error", "extensions": { "category": "internal" } }
  ],
  "data": null
}

This means a plain "check for HTTP 200" monitor will always show UP even when WPGraphQL is broken. The correct approach is to:

  1. Send a real GraphQL query.
  2. Assert the response body contains "data" and does not contain "errors".

Part 1: Choose a lightweight monitoring query

Use the built-in __typename field — it requires no data access, no authentication, and always succeeds if WPGraphQL is functional:

{ __typename }

The expected response:

{
  "data": {
    "__typename": "RootQuery"
  }
}

For more coverage, query a real content type you know always has data:

{
  posts(first: 1) {
    nodes {
      id
    }
  }
}

The __typename query is safer for monitoring because it cannot fail due to empty content.


Part 2: Set up HTTP monitoring in Vigilmon

WPGraphQL accepts both GET (with URL-encoded query) and POST requests. Vigilmon's HTTP monitor supports both. The simplest approach is a GET request with the query in the URL.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Choose HTTP(S) monitor.
  3. URL (GET with inline query):
    https://yoursite.com/graphql?query=%7B__typename%7D
    
    (%7B__typename%7D is {__typename} URL-encoded)
  4. Interval: 1 minute.
  5. Under Keyword assertion, add TWO checks:
    • Assert contains: "data" — confirms a successful response.
    • Assert does not contain: "errors" — catches GraphQL-level errors even on HTTP 200.
  6. Add your alert channel (email, Slack, or webhook).
  7. Click Save.

Vigilmon now verifies that WPGraphQL is up, functional, and not returning error responses — every minute, from multiple geographic locations.

If your WPGraphQL requires authentication

Some installations restrict the GraphQL endpoint to authenticated requests. In that case, create a dedicated WordPress application password:

  1. In WordPress Admin → UsersYour ProfileApplication Passwords, generate a new password.
  2. In Vigilmon, under Request headers, add:
    Authorization: Basic base64(username:application_password)
    
  3. Use __typename as your query — it requires the least privilege.

Part 3: Webhook alert endpoint

If your frontend is a Next.js or Node.js application consuming WPGraphQL, add a webhook handler to forward DOWN/UP alerts:

// pages/api/webhook/vigilmon.ts (Next.js Pages Router)
import type { NextApiRequest, NextApiResponse } from 'next';

interface VigilmonPayload {
  monitor_name: string;
  status: 'down' | 'up';
  url: string;
  response_code: number;
  checked_at: string;
}

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== 'POST') {
    return res.status(405).end();
  }

  const body = req.body as VigilmonPayload;

  if (body.status === 'down') {
    console.error('[VIGILMON] WPGraphQL DOWN', {
      url: body.url,
      code: body.response_code,
      at: body.checked_at,
    });

    const slack = process.env.SLACK_WEBHOOK_URL;
    if (slack) {
      await fetch(slack, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          text: `*WPGraphQL DOWN*: ${body.monitor_name}\nURL: ${body.url}\nTime: ${body.checked_at}`,
        }),
      });
    }
  }

  return res.status(204).end();
}

Or a standalone Node.js webhook (useful if you don't have a Next.js app):

// webhook-server.js
const http = require('http');

const server = http.createServer(async (req, res) => {
  if (req.url === '/vigilmon' && req.method === 'POST') {
    let body = '';
    req.on('data', chunk => { body += chunk; });
    req.on('end', () => {
      const payload = JSON.parse(body);
      if (payload.status === 'down') {
        console.error('[VIGILMON] DOWN:', payload.monitor_name);
      }
      res.writeHead(204);
      res.end();
    });
  } else {
    res.writeHead(404);
    res.end();
  }
});

server.listen(4000, () => console.log('Webhook listener on :4000'));

In Vigilmon, add a Webhook alert channel pointing at your handler URL.


Part 4: WordPress-side health endpoint (optional)

If you want a dedicated REST health check alongside WPGraphQL, add one via functions.php or a small plugin:

<?php
// In functions.php or a custom plugin

add_action('rest_api_init', function () {
    register_rest_route('health/v1', '/check', [
        'methods'             => 'GET',
        'callback'            => 'wpgraphql_health_check',
        'permission_callback' => '__return_true',
    ]);
});

function wpgraphql_health_check() {
    $status = 'ok';
    $checks = [];

    // Check WPGraphQL is active
    if (function_exists('graphql')) {
        $checks['wpgraphql'] = 'ok';
    } else {
        $checks['wpgraphql'] = 'plugin_inactive';
        $status = 'degraded';
    }

    // Check database
    global $wpdb;
    $db_check = $wpdb->get_var('SELECT 1');
    $checks['database'] = $db_check === '1' ? 'ok' : 'error';
    if ($checks['database'] !== 'ok') $status = 'degraded';

    $http_status = $status === 'ok' ? 200 : 503;

    return new WP_REST_Response(
        ['status' => $status, 'checks' => $checks, 'timestamp' => gmdate('c')],
        $http_status
    );
}

This exposes https://yoursite.com/wp-json/health/v1/check. Add a second Vigilmon HTTP monitor on this URL with keyword assertion "status":"ok" for belt-and-suspenders coverage.


Summary

| What to monitor | Vigilmon approach | |---|---| | GraphQL API availability | HTTP monitor on /graphql?query=%7B__typename%7D | | GraphQL-level errors | Keyword: contains "data", does not contain "errors" | | WordPress core health | Optional REST health route in functions.php | | Alerts | Webhook → Slack or Next.js API route |

WPGraphQL errors are invisible to basic uptime checks — keyword assertion is the key difference. With Vigilmon monitoring the response body, you know about GraphQL failures before your frontend users notice empty pages.

Monitor your app with Vigilmon

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

Start free →