Hasura – Logging, Metrics and Tracing

August 8, 20263 min readUpdated 8/21/2026

Hasura sits between your clients and your database, which makes it the best place in the stack to find out why something is slow — and a place where the default logging tells you almost nothing useful.

Choose your log types

The engine emits several categories and you pick which are on:

HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
HASURA_GRAPHQL_LOG_LEVEL: info

What each is worth:

startup — on always. It reports inconsistent metadata at boot, which is lesson 3’s silent failure becoming visible.

http-log — one line per request with status and duration. This is your access log.

query-log — the GraphQL document and the generated SQL. The most useful of the lot for debugging and the most expensive: it logs query text on every request. Worth having in staging permanently and in production when you are hunting something.

webhook-log — Action and event-trigger calls. When emails stop going out, this is where the failure is, not in your application logs.

websocket-log — subscription connect and disconnect. The place to confirm the token-expiry problem from lesson 7.

Reading an http-log line

{
  "type": "http-log",
  "detail": {
    "operation": {
      "query_execution_time": 0.0234,
      "request_id": "b1b7...",
      "user_vars": {"x-hasura-role": "customer"},
      "operation_name": "SearchListings"
    },
    "http_info": {"status": 200, "url": "/v1/graphql"}
  }
}

Two fields do most of the work. operation_name is only there if your clients name their operations — and without it every line says null and you cannot tell which query is slow. Name every query and mutation in your client. It costs nothing and it is the difference between an actionable log and noise.

request_id is what ties a GraphQL request to the Action it triggered and to your backend’s own logs. Propagate it.

Health and metrics

curl -s http://localhost:8081/healthz         # OK
curl -s http://localhost:8081/v1/version     # {"server_type":"ce","version":"v2.42.0"}

/healthz is what your orchestrator should probe. Note that it reports the engine, not the database — an engine that has lost Postgres can still answer OK briefly, so pair it with a real query for a deep check.

A Prometheus metrics endpoint exists on the paid tiers. On Community Edition, build your dashboards from the structured logs — every one is JSON, so shipping them to Loki, Elastic or CloudWatch and aggregating query_execution_time by operation_name gets you most of the value.

Tracing across the boundary

The question that matters in production is usually “where did those two seconds go?” — and for a request that hits an Action, the answer spans two services.

Hasura forwards trace context on Action and event-trigger calls. If your handler continues the trace rather than starting a new one, you get a single span tree covering the GraphQL request, the SQL, the webhook and whatever the webhook did. If it does not, you get two unrelated traces and the correlation is manual.

The cheap version, if you have no tracing at all: log request_id on both sides. It is not a flame graph but it answers the question.

What to actually watch

Four things, roughly in order of how often they are the answer:

Slow operations by name. Aggregate query_execution_time by operation_name and watch the 95th percentile, not the mean. One expensive nested query hides completely in an average.

Connection pool saturation. Requests queuing for a connection look like slow queries but are not — see lesson 14. If latency rises across every operation at once, suspect the pool before the SQL.

Event-trigger failures. They retry silently and then stop. Watch webhook-log for non-2xx, and check the processed-events table.

Inconsistent metadata after deploys. Query get_inconsistent_metadata in your pipeline and fail the deploy on a non-empty result. Otherwise the API shrinks quietly and you find out from a customer.

Observability in v3 (DDN)

On the v3 sections. Everything marked v3 (DDN) is taken from the official Hasura DDN documentation as read on 2026-08-21 and was not run locally — it shows configuration, never claimed output. The v2 material was executed against a running engine.

v3 treats this as a first-class part of the product rather than a log configuration. The DDN console includes traces and analytics directly, and observability is a documented section of the platform rather than a set of environment variables.

The immutable-build model helps in a way that is easy to overlook: because every build has a unique endpoint and an identity, a regression can be attributed to a specific build rather than to “some metadata change last Tuesday”.

Next

Lesson 17 puts it somewhere that is not your laptop.