How to Query a Subgraph (The Graph + GraphQL Guide).
Article Structure

If you work with blockchain data, learning how to query a subgraph is a key skill. A subgraph lets you read indexed blockchain data through a GraphQL API instead of scanning raw blocks. This guide walks you step by step through how to query a subgraph using The Graph, from basic concepts to real code examples.
What a Subgraph Is and Why You Query It
A subgraph is a public or private API that indexes on-chain data and exposes that data through GraphQL. Developers define which contracts, events, and entities matter, and the indexing service stores them in a queryable form.
Instead of calling a blockchain node directly, you send a GraphQL query to the subgraph. The subgraph returns structured data such as users, swaps, pools, or NFTs in a single response. This saves time, bandwidth, and client-side processing.
Most subgraphs live on The Graph Network or on hosted services. You query them the same way: by sending a POST request with a GraphQL query to the subgraph’s HTTP endpoint.
How Subgraphs Fit into Your Data Stack
Subgraphs sit between raw blockchain nodes and your app logic. Nodes handle consensus and low-level RPC calls, while subgraphs give you clean, indexed entities. This split lets you keep your app code simple and focus on business rules instead of parsing logs and blocks.
Core Pieces You Need Before Querying a Subgraph
Before you learn how to query a subgraph, gather a few key details. These details define where you send requests and what you can ask for.
- Subgraph URL (endpoint) – The HTTP or HTTPS address where you send GraphQL queries.
- Schema – The GraphQL schema that lists types, fields, arguments, and relationships.
- Example queries – Sample queries from the subgraph page or docs that show how data is structured.
- Authentication (if needed) – An API key or header if the endpoint is not fully public.
Most public subgraphs show the endpoint and schema in their UI. On The Graph’s hosted service, you usually see a “Query URL” and a “Playground” where you can test queries in the browser.
Checking Access and Limits Before You Start
Before you put a subgraph into production, check rate limits and access rules. Some providers limit queries per minute or require an API key. Knowing these limits early helps you design caching, batching, and retries without surprises later.
Understanding the GraphQL Basics Used in Subgraphs
Subgraphs use standard GraphQL, so you only need a few basic ideas to start. GraphQL is strongly typed and lets you choose exactly which fields to return.
Each subgraph defines types such as User, Pool, or Token. These types often match entities from the blockchain. Each type has fields such as id, balance, or timestamp.
In a query, you choose a root field, like users or swaps, pass arguments such as first or where, and list the fields you want in the response. The server returns a JSON object that matches your requested shape.
Key GraphQL Arguments You Will Use Often
Most subgraphs support a small set of useful arguments across many root fields. You will see first and skip for pagination, orderBy and orderDirection for sorting, and where for filters. Learning these arguments once gives you a pattern you can apply to most entities.
Step-by-Step: How to Query a Subgraph
This section gives you a clear process you can reuse for any subgraph. Follow each step in order, from finding the endpoint to reading the JSON response.
-
Find the subgraph endpoint
Go to the subgraph’s page on The Graph or another host. Look for a field called “Query URL” or “Endpoint.” It usually looks like an HTTPS URL ending with/graphqlor the subgraph name. -
Open the GraphQL playground (optional but helpful)
Many subgraphs offer a GraphQL playground in the browser. This lets you test queries without writing code. Paste the endpoint into a GraphQL client like Apollo Sandbox or use the built-in explorer if the host provides one. -
Inspect the schema and types
Use the schema explorer in the playground to see available types. Look at root query fields such asusers,transactions, ortokens. Open a type to see which fields you can request, such asid,owner,value, and timestamps. -
Write a simple GraphQL query
Start with a small query that fetches a few entities. For example, to fetch the first 5 users:{ users(first: 5) { id createdAt } }This query asks the subgraph for five user entities and returns only the
idandcreatedAtfields. -
Add filters, ordering, and pagination
Most subgraphs support arguments likewhere,orderBy,orderDirection,first, andskip. For example:{ swaps( first: 10 orderBy: timestamp orderDirection: desc where: { amount_gt: "1000000000000000000" } ) { id user amount timestamp } }This query asks for the latest 10 swaps with an amount greater than a threshold, ordered by time.
-
Send the query with curl or a tool like Postman
Once the query works in the playground, send it with a HTTP POST request. Withcurl:curl -X POST \ -H "Content-Type: application/json" \ -d '{"query":"{ users(first: 5) { id createdAt } }"}' \ https://api.thegraph.com/subgraphs/name/your/subgraphReplace the URL with your subgraph endpoint and adjust the query string. Make sure you escape quotes properly or use a separate file if the query is long.
-
Integrate the query in your application code
After testing, add the query to your app using your language of choice. The next section shows code examples in JavaScript and TypeScript.
By following these steps, you create a repeatable process for any new subgraph. You only need to change the endpoint and the query structure based on the schema.
Choosing Between Playground, CLI, and Code
Each tool has a good use case. The playground is ideal for discovery and quick tests, CLI tools work well in scripts and debug sessions, and application code handles production traffic. Most teams start in the playground, move to CLI for automation, and then embed final queries in services.
Code Example: Query a Subgraph with JavaScript (fetch)
Most modern JavaScript runtimes support fetch. You can use it in Node.js (with recent versions) or in the browser to query a subgraph.
Here is a simple example that shows how to query a subgraph and log the result. Replace the endpoint and query with values from your project.
const SUBGRAPH_URL = "https://api.thegraph.com/subgraphs/name/your/subgraph";
const QUERY = `
{
users(first: 5) {
id
createdAt
}
}
`;
async function querySubgraph() {
const response = await fetch(SUBGRAPH_URL, {
method: "POST",
headers: {
"Content-Type": "application/json"
// Add auth header here if needed, e.g. "Authorization": "Bearer <API_KEY>"
},
body: JSON.stringify({ query: QUERY })
});
if (!response.ok) {
console.error("Subgraph query failed:", response.status, response.statusText);
return;
}
const json = await response.json();
if (json.errors) {
console.error("GraphQL errors:", json.errors);
return;
}
console.log("Subgraph data:", json.data);
}
querySubgraph().catch(console.error);
This pattern works for any GraphQL query. You can move the query into a separate file, use variables, and add error handling depending on your needs.
Handling Errors and Timeouts in JavaScript
In real apps, wrap your fetch call in try/catch and add a timeout. You can use AbortController in the browser or a library in Node.js. Timeouts stop hung requests and prevent your UI or job runner from waiting forever on a slow subgraph.
Using GraphQL Variables for Cleaner Subgraph Queries
GraphQL variables help you reuse queries and avoid string concatenation. Instead of hardcoding values into the query, you define variables in the query and pass values in a separate object.
Here is a query that uses variables to fetch a list of swaps for a given user address. The same pattern works for any filter supported by the subgraph schema.
const SUBGRAPH_URL = "https://api.thegraph.com/subgraphs/name/your/subgraph";
const QUERY_WITH_VARS = `
query SwapsByUser($user: String!, $limit: Int!) {
swaps(
first: $limit
orderBy: timestamp
orderDirection: desc
where: { user: $user }
) {
id
amount
timestamp
}
}
`;
async function getSwapsByUser(userAddress, limit = 10) {
const response = await fetch(SUBGRAPH_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: QUERY_WITH_VARS,
variables: {
user: userAddress.toLowerCase(),
limit
}
})
});
const json = await response.json();
return json.data?.swaps ?? [];
}
Variables make your code safer and easier to maintain. You change values in one place instead of building strings manually, and your GraphQL client can often validate the shape of the variables.
When to Use Variables Versus Separate Queries
Use variables when the query shape stays the same but values change, such as user IDs, time ranges, or limits. Use separate queries when you need different fields or filters. This split keeps your code base organized and avoids giant multi-purpose queries that are hard to reason about.
How to Query a Subgraph from Backend Services
Backend services often query subgraphs to power APIs, analytics, or scheduled jobs. The pattern is the same: send a POST request with a query and optional variables, then process the JSON response.
In backend environments, you may also need to handle rate limits, timeouts, and retries. Use a HTTP client with timeout support and wrap calls in retry logic if the service is critical.
For TypeScript backends, you can generate types from the GraphQL schema. Tools like GraphQL Code Generator read the schema and your queries, then output TypeScript types so responses are strongly typed in your code.
Designing a Backend Layer Around Subgraph Calls
A simple pattern is to wrap subgraph calls in a dedicated module or service. That module handles retries, logging, metrics, and caching. Other parts of your backend call clean functions like getUserPositions instead of building GraphQL queries directly.
Common Issues When Querying a Subgraph and How to Fix Them
Even if you know how to query a subgraph, you may hit common issues. Most problems fall into a few simple categories that you can check quickly.
First, schema mismatches cause many errors. If you request a field that does not exist or pass a wrong argument, the GraphQL server returns an error message listing the problem. Open the schema explorer again and confirm the field name and type.
Second, rate limits or network errors can cause timeouts or 429 responses. In that case, reduce the size of each query, add pagination, and add a short delay or retry logic. For heavy analytics, spread requests over time instead of pulling everything at once.
Debugging Failed Subgraph Queries
When a query fails, start by logging the full error response from the server. Check the errors field in the JSON and compare your query against the schema. If the query is valid but performance is poor, try reducing fields, tightening filters, or splitting a large query into several smaller ones.
Best Practices for Efficient Subgraph Queries
Good query design keeps your app fast and reduces load on the subgraph. A few simple habits help a lot, especially as data grows.
Request only the fields you actually use. GraphQL lets you be very specific, so avoid asking for entire entities if you only need one or two fields. This reduces payload size and speeds up responses.
Use pagination instead of requesting thousands of records in one query. Combine first and skip, or use cursor-based pagination if the subgraph supports it. For example, fetch 100 items at a time and loop until you reach your target.
Comparing Query Patterns for Different Use Cases
Different apps use subgraphs in different ways. The table below compares common query patterns and where each one fits best.
Common Subgraph Query Patterns and Use Cases
| Use Case | Query Pattern | Key Tips |
|---|---|---|
| Dashboards and UIs | Small, frequent queries with tight filters and pagination. | Cache recent results in memory and keep fields minimal. |
| Analytics Jobs | Batch queries that walk through data in chunks. | Use first/skip or cursors and add delays. |
| Alerting Systems | Targeted queries for latest events or state changes. | Poll on recent timestamps and store last processed ID. |
| APIs Built on Top | Backend layer that aggregates several subgraph calls. | Normalize data, add caching, and expose a simpler REST or GraphQL API. |
Choosing the right pattern for each use case keeps subgraph load under control and improves user experience. You can even mix patterns in one project, such as dashboards for users and batch jobs for internal reports.
Putting It All Together
To recap, learning how to query a subgraph comes down to a clear sequence: find the endpoint, read the schema, write a small GraphQL query, test in a playground, then send it from code using POST requests. Once you master that pattern, you can work with almost any subgraph on any network.
From there, you can refine your queries with filters, ordering, and variables, and you can add error handling and pagination. As your project grows, you may also generate types and share query modules across services. The same core ideas apply whether you build dashboards, analytics, or full dApps on top of subgraphs.
Next Steps for Advancing Your Subgraph Skills
After you are comfortable with basic queries, explore more advanced topics. You can learn about derived fields, indexing strategies, and how to write or update your own subgraphs. These skills help you move from consumer to contributor and give you more control over the data your apps rely on.


