Why GraphQL Must Be Monitored Differently Than REST
GraphQL breaks a central assumption of classic uptime monitoring: that the HTTP status code reflects the state of the request. With GraphQL, the actual error information lives in the response body, not in the status code. The specification allows a response to contain both a data object and an errors array — successfully resolved fields are delivered, failed ones appear as null and are described in the errors array (GraphQL Foundation). This is called partial response: a response with both data and errors at the same time is perfectly normal in GraphQL.
The consequence is concrete: a monitor that only checks whether the endpoint responds with 200 reports a healthy API — even though a central resolver is timing out and users see a half-empty page. A single endpoint is deceptive, too: unlike REST, where /users and /orders are separate URLs, all GraphQL traffic runs over one URL (usually /graphql). The distinction between working and broken operations happens not in the path but in the query itself.
This quirk is no longer a niche topic. According to Postman, 33% of teams use GraphQL (Postman State of the API 2025), and in technology-driven and mobile-first companies the share of client-facing GraphQL APIs is significantly higher. Anyone running GraphQL in production needs monitoring that looks inside the response — not just knocks on the door. The fundamentals are covered in the article API monitoring: how to watch endpoints correctly.
With GraphQL, a request can respond with HTTP 200 and still have failed — the failed fields become null, and the error sits in the errors array (GraphQL Foundation / Apollo). Monitoring that only checks the status code systematically misses such partial failures. That is why inspecting the response body is mandatory for every GraphQL check.
Query and Mutation Checks: Testing the Endpoint Functionally
The first building block of resilient GraphQL monitoring is a real query against the endpoint — not a mere connection test. A small, targeted health query returns exactly the fields whose availability is business-critical. Instead of querying the entire API, you select a few representative fields from several resolvers, so that an outage in a backend service becomes visible.
# POST /graphql with JSON body { "query": "..." }
query MonitorHealth {
viewer {
id
name
}
orders(first: 5) {
edges {
node { id total status }
}
}
catalog: products(first: 1) {
totalCount
}
}Mutations deserve special caution. A mutation changes data — a monitor that creates a real order every minute does harm. Idempotent or read-only operations, a dedicated health mutation endpoint that writes nothing permanent, or a test mutation against a sandbox environment are therefore suitable for monitoring. What matters is that the check touches the mutation path without producing side effects in production data.
A read-only health query against several resolvers. Checks whether the most important data fields are delivered and whether data has the expected structure.
An idempotent or sandbox mutation that tests the write path without changing real data. Never run destructive mutations against production.
GraphQL runs over one URL — the healthy/broken distinction happens in the query. Several named operations cover different backend services.
Many fields are only reachable with a valid token. The monitor sends a service token in the header and checks whether viewer resolves correctly.
Detecting Partial Errors: Evaluating the errors Array
The core of a GraphQL check is the evaluation of the errors array. Best-practice recommendations for GraphQL over HTTP advise sending 200 as soon as an operation has executed at all — even if errors occurred (GraphQL Foundation). The failed fields then become null, and the errors array names the exact path for each error, i.e. which field failed at which position (Apollo). A GraphQL monitor must know this structure and check it specifically.
{
"data": {
"viewer": { "id": "u_42", "name": "Example Ltd" },
"orders": { "edges": [ /* ... */, { "node": { "total": null } } ] }
},
"errors": [
{
"message": "Resolver timeout",
"path": ["orders", "edges", 2, "node", "total"],
"extensions": { "code": "DOWNSTREAM_SERVICE_ERROR" }
}
]
}Several assertions can be derived from this structure. The most important: errors must be absent or empty. If the monitor finds a populated errors array, the operation is degraded — even if the status code is 200. In addition, expected data fields can be checked via JSONPath (data.viewer.id must be present) and error codes in the extensions.code field can be classified to distinguish a validation message from a real backend outage.
How such content-based checks are built is explored in the article API monitoring with assertions and thresholds. For GraphQL, a pure availability check is not enough — only the combined evaluation of status code, errors array, and data fields yields a realistic picture of the endpoint's state.
Schema and Introspection Monitoring
GraphQL describes its own structure through the schema, which can be queried via introspection. This capability is part of the standard and practical for development — but it is also a security risk. The OWASP recommendations explicitly advise disabling introspection in production and publicly accessible environments, because it lets attackers enumerate the entire schema and specifically search for sensitive fields (OWASP GraphQL Cheat Sheet).
This results in two monitoring tasks. First, the security check: is introspection accidentally enabled in production? A monitor can send an introspection query and raise an alert if the schema is openly accessible. Second, drift detection: if the schema changes unexpectedly — a field disappears, a type changes — clients can break. Where introspection deliberately stays enabled (for example in staging), the schema can be captured regularly and compared with the expected target state.
| Check | What it detects | Recommended response |
|---|---|---|
| Introspection status | Whether the schema is openly queryable in production | Alert if introspection is active in production (OWASP) |
| Schema drift | Disappeared fields, changed types, removed operations | Notification so that clients can be adapted |
| Deprecation hints | Fields marked @deprecated that are still in use | Plan migration before the field is removed |
| Field availability | Whether a business-critical field still resolves | Immediate alert if an expected field disappears |
The OWASP GraphQL Cheat Sheet recommends disabling introspection queries and schema explorers like GraphiQL in publicly accessible environments (OWASP). A monitoring check that specifically issues an introspection request and warns on a successful response reliably uncovers this common misconfiguration — before an attacker does.
Monitoring Resolver Latency and Performance
GraphQL shifts the performance question from the URL to the individual field. Because a client can combine any number of fields in one request, the response time does not depend on the endpoint but on which resolvers are involved. A slow resolver — for example a database query without an index or a sluggish downstream service — can slow down an otherwise fast query. Best-practice sources therefore recommend observing resolver error rates and operation latency separately (GraphQL Foundation).
For monitoring this means: the end-to-end latency of the health query is the first metric, complemented by thresholds for warning and error. If the response time rises above a defined value — above 500 ms in the mockup, for example — the check is marked as degraded, long before the query runs into a hard timeout. This early warning is especially valuable because a single slow resolver is often the first sign of an emerging backend problem.
- End-to-end latency of the health query with warning and error thresholds — detects slow resolvers before they become timeouts
- Keep an eye on the N+1 problem — nested fields can trigger one backend request per element and multiply latency unnoticed
- Limit query depth and complexity — deep, nested queries strain the server and are a known DoS vector (OWASP)
- Measure latency per region — check from several locations to distinguish regional bottlenecks from global ones
- Trend over snapshot — a single slow response is noise, a rising trend over hours is a signal
A GraphQL check that combines status code, errors array, data fields via JSONPath, and resolver latency answers not just "is the API up?" but "does it deliver correct data in acceptable time?". This content-level depth is what distinguishes resilient API monitoring from a mere ping.
GraphQL Security: More Than Availability
Monitoring GraphQL has a security dimension that goes beyond pure availability. APIs became the primary attack target in 2025: the number of API attacks rose by 113% year over year, from an average of 121 to 258 daily attacks per organization, and 87% of organizations experienced an API-related security incident in 2025 (Akamai SOTI 2025). APIs now handle around 83% of web traffic, making them one of the largest attack surfaces in modern software (Akamai SOTI 2025).
GraphQL brings its own risks. The OWASP API Security Project now lists GraphQL-specific examples across the Top 10 risks (OWASP). Particularly relevant are Broken Object Level Authorization (BOLA) and Broken Function Level Authorization (BFLA): if field-level authorization does not take effect, attackers can query sensitive fields specifically via the schema enumerated through introspection. Introspection enabled in production significantly enlarges this attack surface.
Monitoring does not replace a security architecture but complements it: a check that observes introspection status, unusual error codes in the extensions field, and conspicuous latency spikes provides early signals. Combined with a clean alert configuration and resilient incident management with escalation, a technical signal turns into a manageable response — before a misconfiguration becomes an incident.
GraphQL in the Context of Modern Protocols
GraphQL is part of a broader shift in the API landscape. While REST still dominates at 93%, specialized patterns are gaining ground: webhooks (50%), WebSockets (35%), and GraphQL (33%) are increasingly used in a complementary fashion (Postman State of the API 2025). Each of these protocols places its own demands on monitoring — and none can be fully captured with a pure HTTP status check.
Real-time connections over WebSockets, for example, stay open and transmit data continuously — what counts here is not the one-off status code but the sustained connection quality. How such persistent endpoints can be monitored is described in the article on WebSocket and realtime endpoint monitoring. On the transport layer, in turn, HTTP/3 over QUIC fundamentally changes latency and connection characteristics, which requires its own check methods — details in the article on HTTP/3 and QUIC protocol monitoring.
The common denominator: modern interfaces require monitoring that does justice to the respective protocol quirks. For GraphQL that is the evaluation of the response body, for WebSockets the connection duration, for HTTP/3 the transport performance. XICTRAQ API monitoring bundles these checks under one roof, so that GraphQL, REST, and realtime endpoints can be monitored together.
Setting Up GraphQL Monitoring With XICTRAQ
The following checklist summarizes what resilient GraphQL monitoring should cover. It serves as a starting point for checking an existing endpoint or setting up new monitoring.
- Send a real query instead of just testing the connection — a health query against several resolvers covers different backend services
- Check the status code AND the
errorsarray — with GraphQL, HTTP 200 can respond despite partial failure (GraphQL Foundation) - Verify data fields via JSONPath —
data.viewer.idand other business-critical fields must be present - Monitor resolver latency with thresholds — set warning and error limits before hard timeouts occur
- Check introspection in production — alert if the schema is openly queryable (OWASP)
- Include authentication — service token in the header to realistically test protected fields
- Test mutations carefully — only idempotent or sandbox operations, never destructive writes against production
- Define escalation — notify via email, Slack, Discord, or Telegram on a degraded state
XICTRAQ API monitoring checks GraphQL endpoints at configurable intervals via a per-minute cron, sends a configurable query or mutation, and evaluates the response against your assertions. If the check detects a populated errors array, a missing data field, or an exceeded latency threshold, the endpoint is marked as degraded and a notification is triggered — through the same channels as the rest of your monitoring.
This lets GraphQL fit seamlessly into end-to-end monitoring: REST and GraphQL APIs, WebSocket connections, and classic uptime checks run under one roof, with shared alert logic and escalation. How thresholds and assertions are configured in detail is explored in the article API monitoring with assertions and thresholds — the basis for monitoring that aims not just for availability but for correctness.
This article is based on data from: GraphQL Foundation (specification, partial response, GraphQL over HTTP), Apollo GraphQL (error handling, errors array, path), OWASP (API Security Top 10, GraphQL Cheat Sheet, introspection recommendation), Akamai (State of the Internet / Apps and API Security Report 2025: +113% API attacks, 87% of organizations affected, 83% API traffic), Postman (State of the API Report 2025: API architecture distribution REST 93%, webhooks 50%, WebSockets 35%, GraphQL 33%).
Frequently Asked Questions About GraphQL API Monitoring
Why is an HTTP status check not enough for GraphQL?
errors array of the response body. Monitoring that only checks the status code usually misses such partial failures — which is why evaluating the response content is generally indispensable.What are partial errors in GraphQL?
null and are described in the errors array (Apollo). A response can therefore contain both data and errors at the same time, which is perfectly normal in GraphQL.