Migrate
Moving a subgraph to a nest.
A nest can answer part of a subgraph's GraphQL, exactly, and refuse the rest by name. It is not a drop-in replacement, and most clients cannot adopt it by changing a URL. Before you move anything, find out which of your queries fall inside the part it answers. This page is how.
The boundary
Event-shaped fields answer. Mapping-computed ones do not.
A nest is a compiler over decoded chain events, not a second indexer. It does not run AssemblyScript. Whatever a subgraph takes straight from events, it reproduces exactly; whatever a mapping computes in order, carrying state from one event to the next, it refuses. Every field either answers exactly or is refused with a reason. There is no third behaviour: no default, no stale value, no empty list in place of an answer.
| Answers exactly | Refused by name |
|---|---|
| ids, timestamps, block numbers, log indices | prices, and anything derived from one |
| addresses, token ids, transaction hashes | priced totals: volume in USD, fees, TVL |
| values taken straight from an event's parameters | values from ordered, stateful mapping code |
| sums and counts over events, where a view reproduces them | day and hour aggregate entities |
| @derivedFrom relations between the above |
Measured
Why most clients cannot switch by changing a URL.
GraphQL has no partial answer. A query that names one field a nest cannot answer is refused whole, and the client gets an error rather than the other fields. So field coverage is an upper bound on query coverage, and a loose one.
- 70 of 184
- fields classed exact that a nest answered on the pinned Uniswap V4 port (38%)
- 41 of 93
- on Carbon, the second pinned target (44%), which has no priced fields
- 0 of 4
- fields answered in
pools(orderBy: totalValueLockedUSD)with volume and token symbol
All three were measured on 12 September 2026 and are recorded in RFC-0053's measured outcome. For a Uniswap-shaped analytics client, the honest summary is that a nest answers nothing it would ask for. For a bot, a reconciliation job or an audit trail asking for every Swap on a pool since some block, with sender, transaction hash and log index, it answers exactly over the whole history. The shape of the subgraph decides the outcome far more than anything left to build. The programme is parked: what shipped is supported, and nothing further is being added to it.
Route one
Port the subgraph, and read the report first.
port-report classifies every entity field against the mappings and writes nothing.
init --from-subgraph takes the manifest's data sources, ABIs and start blocks, and
port-emit overlays the views and prints a coverage line naming every field it cannot answer.
port-emit needs the subgraph's source, its schema.graphql and mappings, because
a deployment CID holds only compiled WASM. Check your own queries' fields against that list.
# 1. Report first. Nothing is written.
nuthatch port-report --dir path/to/subgraph > port-report.md
# 2. Scaffold from the manifest, then overlay views, calls and checks.
nuthatch init --from-subgraph <deployment CID> --dir nest
nuthatch port-emit --dir path/to/subgraph --out nest
The default binary has no GraphQL route: POST /graphql answers 404. Serving the Graph dialect
needs the separate nuthatch-graph download attached to every release since 4.11.0, described
under the graph build. The
subgraph port skill walks a coding agent through the same steps.
Route two
Start from the contract address instead.
If you own the client, it is often simpler to leave GraphQL behind. Give init the contracts
the subgraph indexed and it makes one table per event from the ABI, with no mappings and no schema to
write. Then ask in SQL, over HTTP at /sql or from an agent over MCP. Counts, sums and joins
over events are a view in views/*.sql, or a maintained entity when it must be fast.
nuthatch init 0xYourContract --chain arbitrum-one
nuthatch dev
nuthatch sql "SELECT count(*) FROM <alias>__<event>" Prices are the same problem by this route: nothing derives a USD value for you. The worked example goes from address to view to entity, and the agents page connects the result to Claude Code or Cursor.
What carries over
- Data sources, ABIs and start blocks, read from the manifest by
init --from-subgraph. - Factory templates, where a parameter names the template; the rest are listed for you to resolve.
- Introspection, filters, ordering, pagination and
_meta, in the graph build. - Event-shaped fields, exactly, over the hot store and sealed history alike.
- Queries at
/graphqland/subgraphs/id/<deployment>.
What does not
- Mapping code. AssemblyScript is never run, in indexing or anywhere else.
- Prices and priced totals such as
derivedETHandtotalValueLockedUSD. By design, not by backlog. - Day and hour aggregate entities, which have no table.
- A query that names any refused field: it fails whole.
- The GraphQL route in the default binary, and any shape not on the accepted dialect.
We can host the port
We port a subgraph that is no longer live on the network to a nest and run it on our servers, with no billing and no accounts. Its event-derived fields answer exactly and the rest are refused by name, so check your app's queries against the port before switching. The hosting offer has the terms, and the BetSwirl BNB Chain handback shows one port end to end: its client's own queries answered exactly.
Beside the network, not instead of it
A subgraph that the network still serves is usually best left there. A nest is for the case where a subgraph has stopped, or where you would rather hold your own contracts' history on your own machine. Nuthatch and The Graph sets out how the two sit together, and the comparison puts Nuthatch beside The Graph, Ponder, rindexer and Envio.