Concepts · 10 min read
What is a subgraph?
A subgraph is an open-source definition of how to index a smart contract: a manifest, a GraphQL schema, and one or more event-handler mappings. The format was introduced by The Graph and is now supported by multiple runtimes. This guide covers what subgraphs are, what running one involves, what they're good and not-so-good at, and what migrating away takes when a project outgrows them.
1. What is a subgraph?
A subgraph is a directory containing three things: a manifest that says which chain and which contracts to watch, a GraphQL schema that defines the shape of the indexed data, and one or more mapping files that translate raw chain events into entities matching that schema. When run, the subgraph reads the chain, executes the mappings on each event, and writes the resulting entities into a database. The database is then queried through an auto-generated GraphQL API.
The format was defined by The Graph and the reference runtime is graph-node, both open-source. The format has been adopted by other runtimes and hosting services since, which means a subgraph definition is reasonably portable across the systems that support it.
2. Subgraphs and The Graph
The Graph is the protocol and decentralized network that originated the subgraph format. The Graph Network is a marketplace: developers publish subgraphs to the network, indexer operators stake GRT (the network token) to serve them, curators signal which subgraphs are valuable, and delegators stake on indexers to share in rewards. Applications query the network and pay query fees in GRT.
The Graph also previously ran a Hosted Service (free, centralized subgraph hosting) which was sunset and migrated onto the decentralized network. As of 2026, the primary paths to run a subgraph are: (1) deploy to The Graph Network, (2) self-host graph-node, or (3) use a third-party hosted service such as Goldsky. The subgraph definition file is the same in all three cases.
3. The three files: manifest, schema, mappings
subgraph.yaml (the manifest). Declares which chain the subgraph indexes, which contract addresses to watch, which events and call handlers to listen for, the start block, and which schema and mapping files to use. Adding a new contract to the subgraph is a manifest edit plus the corresponding handler.
schema.graphql (the schema). Declares the entity types the subgraph will store, their fields, and their relationships. A typical schema for a DEX subgraph defines entities like Pool, Swap, Token, with relations between them. The schema also drives the generated GraphQL query API.
mapping.ts (the handlers). AssemblyScript (a TypeScript subset that compiles to WebAssembly) functions that receive decoded events and write entities. A handler for a Transfer event reads the event's from, to, and value, looks up or creates the relevant entities, and saves them. The runtime executes one handler per event, sequentially per contract.
A simple subgraph for a single ERC-20 token is around 200 lines across these three files. A subgraph for a major protocol (Uniswap, Aave) is several thousand lines and includes generated TypeScript bindings for each contract's ABI.
4. Build, deploy, query
Build. The graph-cli compiles the AssemblyScript mappings to WebAssembly and produces a deployable artifact. The CLI also generates typed bindings from contract ABIs for use in mappings.
Deploy. The compiled artifact is published to wherever the subgraph will run. On The Graph Network, this is a publish transaction onchain plus uploading the artifact to IPFS. On self-hosted graph-node, it is a deploy call to the local graph-node API. On a third-party host, it is whatever that host's deploy flow is. After deploy, the runtime begins syncing from the start block.
Query. Once synced, the subgraph exposes a GraphQL endpoint. Applications query it directly with GraphQL clients (Apollo, urql, raw fetch). Queries support filtering, sorting, pagination, and relationship traversal. The response is JSON.
Sync time. A subgraph's sync time depends on how much history it covers and how heavy its handlers are. A small subgraph for a recent contract can sync in minutes; a Uniswap-scale subgraph from genesis can take days on a self-hosted graph-node and varies on the network.
5. What subgraphs are good and not-so-good at
Where subgraphs work well. Single-chain dApp data where the schema is known up front and the access pattern is application-driven (lookup by entity ID, traverse relationships, paginate lists). GraphQL's schema-first ergonomics fit closely with the contract-event-to-entity translation a dApp typically needs. The Graph's decentralized network is a real path to durable hosting that survives a single operator going away.
Where subgraphs struggle. Cross-chain queries: subgraphs are scoped to one chain, so multi-chain applications run multiple subgraphs and merge results in the application. Analytical workloads: GraphQL is poorly suited to aggregation-heavy queries; teams that need SQL or columnar performance often move data out of the subgraph into a warehouse. Latency-sensitive applications: subgraph reindexing of unfinalized blocks can introduce more lag than a streaming-first indexer would. Backfill speed: large contracts indexed from genesis take a long time to sync; substreams-powered subgraphs improve this but require Firehose-instrumented nodes.
The choice between a subgraph and a non-subgraph indexer often comes down to whether the application's data access pattern matches GraphQL's strengths. Subgraphs are not the only way to index a contract; they're one well-known, schema-first option among several.
6. Migrating away from a subgraph
Teams move off subgraphs for a few common reasons: needing chains The Graph Network doesn't support, needing query patterns GraphQL doesn't express well, hitting backfill limits, or wanting their schema in a warehouse alongside other data sources. Migration is usually less disruptive than the team expects because the schema is the durable part.
The schema. The entity definitions in schema.graphql are the contract between the indexer and the application. Most non-subgraph indexers can produce the same entity shape, possibly with adjusted naming conventions; the application's queries don't fundamentally have to change.
The handlers. The logic in mapping.ts (decode an event, look up state, write an entity) translates directly into other frameworks' handler APIs. The AssemblyScript-to-TypeScript transition removes some constraints (real strings, real numbers, normal JavaScript libraries). The Squid SDK uses standard TypeScript, which most teams find more ergonomic than AssemblyScript for non-trivial logic.
The query API. If the application is happy with GraphQL, the target indexer can expose GraphQL too (most do). If the application wants SQL or REST, the target indexer can expose those instead.
In the SQD ecosystem: Squids. The equivalent of a subgraph in SQD is a Squid: a code-first indexer built with Squid SDK. A Squid reads decoded chain data from the SQD Network, runs developer-written handlers in standard TypeScript (not AssemblyScript), and writes entities into Postgres by default. The three pieces of a subgraph map onto a Squid cleanly:
subgraph.yaml(the manifest) becomes a Squidprocessorconfigured in TypeScript, with the same notion of which chain to watch and which contracts to index.schema.graphqlports across with minimal change; Squids consume the same GraphQL schema language.mapping.tshandlers become regular TypeScript functions: same logical shape (decode an event, look up state, save an entity), but with full TypeScript ergonomics and no AssemblyScript-specific constraints.
Squids can serve their data through GraphQL (the closest analogue to a subgraph), through direct SQL against the Postgres store, or through REST endpoints layered on top.
For a side-by-side look at how SQD compares to The Graph more broadly, including chain coverage and pricing, see SQD vs The Graph. The schema-portable, handler-rewrite pattern generalises to migrations to any non-subgraph indexer, not just Squids.
Frequently asked questions
What is a subgraph?
What is The Graph and how does it relate to subgraphs?
Can I use subgraphs without The Graph?
What is GraphQL and why do subgraphs use it?
How do I migrate a subgraph to another indexer?
Are subgraphs free?
What chains support subgraphs?
Related guides
Moving away from a subgraph?
See the SQD vs The Graph comparison for migration shape and trade-offs. The Squid and Pipes SDKs are TypeScript-native.