Integrating it properly

Caching, timeouts, degradation and the health check that turns a silent wrong answer into a visible warning.

2 of 4 in the App builder path beginner 10 min

Checked against Graph Horizon (2025-12-11)

Last read 2026-08-30 Due again 2026-11-30

Every protocol claim below was read at these sources on 2026-08-30. Where they disagree with each other, the lesson says so.

The integration works. This lesson is about making it keep working when something upstream does not.

Treat it as a third-party dependency, because it is.

You are reading from a network of independent operators through a gateway. That is more robust than one vendor’s API in the ways that matter, and it is still not infinitely available and not instantaneous.

Everything you would do for any external data dependency applies:

  • Timeouts on every call. A gateway request that hangs must not hang your request handler.
  • Retries with backoff, bounded. Retrying forever turns a slow upstream into an outage of your own making.
  • A circuit breaker. If queries are failing, stop sending them for a while.
  • A fallback rendering. Decide what a screen shows when the data is unavailable, before you find out at three in the morning.

Cache aggressively, and be explicit about staleness.

Chain data does not change retroactively, which makes it unusually cacheable. Anything below a confirmed block height is stable and can be cached for a long time.

The right structure is usually two tiers: a short cache for anything touching the chain head, and a long cache for historical data.

The mistake is treating the graph as your cache. Every query costs money and latency. If a screen shows the same figures to every user, compute it once in your backend and serve it from there.

The health check that matters.

The single most valuable addition to any integration is to query indexing status alongside the data, and expose it.

You want to know two things: how far has this deployment indexed, and is it healthy. From those you can distinguish:

  • Data is fresh and complete: render normally.
  • Data is behind chain head: render with a staleness indicator.
  • Deployment has failed: render an explicit error rather than an empty state.

Read-after-write.

A user submits a transaction and immediately expects to see its effect. The indexer serving your next query may not have processed that block yet.

Options, roughly in order of preference:

  • Optimistic update. Show the expected result locally and reconcile when the index catches up. Best experience, most work.
  • Poll with a deadline. Query until the entity appears or a timeout expires, then say so honestly.
  • Tell the user. “This will appear shortly” is an acceptable answer and is better than a screen that appears to have lost their transaction.

What does not work is assuming the write is immediately readable. It is not, by construction, and no amount of retrying at zero delay changes that.

Cost control.

  • Measure per feature. Instrument query counts by screen in staging. You will find one component making far more calls than it needs.
  • Never query in a render loop. Obvious, and it still happens.
  • Paginate. An unbounded collection query grows with the data.
  • Alert on volume. A runaway client is a bill, and you want to know from a monitor rather than an invoice.
Check yourself

What single addition best prevents an application showing stale data as though it were current?

A user submits a transaction and immediately queries for its effect. What should the application do?

Which caching approach fits chain data best?