GraphQL in Production · Security, Observability and Evolution

Observability for GraphQL

Per-operation and per-field metrics, tracing and error tracking.

HTTP-level metrics are useless when every request is POST /graphql 200. Instrument by operation name (rate, errors, latency percentiles), track field-level resolver timings to find slow fields, export OpenTelemetry spans for parsing, validation and resolvers (sampled — per-field spans are expensive), and record errors[] with extensions.code. Schema registries (Apollo GraphOS, Hive) aggregate field usage, which tells you what can be safely deprecated.

What to measure

Signal Why Tooling
Operation-level RED metrics Which client operations are slow/failing Prometheus/OTel by operationName
Field resolver timing Find slow fields/N+1 Apollo tracing, Hive, OTel
Field usage stats Safe deprecation decisions Schema registry
Error codes Classify failures extensions.code in logs/metrics
# OpenTelemetry span names (graphql semantic conventions)
graphql.parse
graphql.validate
query ProductPage            (graphql.operation.name=ProductPage, graphql.operation.type=query)
  └─ resolve Product.reviews  (sampled)

Common pitfalls

  • Anonymous operations polluting metrics.
  • Tracing every field at 100% sampling.
  • Ignoring partial errors because HTTP status is 200.

Key points

  • Metrics by operation name
  • Field-level timing and usage
  • Errors with codes

Further reading: OpenTelemetry: GraphQL semantic conventions

Practice questions

Why are standard HTTP dashboards misleading for GraphQL?

Answer

All traffic hits one endpoint and usually returns 200 even with errors, so latency/error rates must be broken down by operation name and errors[] contents.

How does field usage data help schema evolution?

Answer

It shows which clients still request deprecated fields, so you know when removal is safe and whom to contact.

Open in the app to mark lessons complete, take notes and track your progress.