Query Overview
Graph Node provides a rich GraphQL API for each deployed subgraph without requiring any additional code. The API is automatically generated from the subgraph’s schema and supports:- Filtering: Filter entities by any field
- Sorting: Order results by any field
- Pagination: Efficient cursor-based and offset-based pagination
- Nested queries: Load related entities in a single query
- Time-travel: Query historical state at any block
- Full-text search: Search text fields with ranking
- Aggregations: Compute sums, counts, averages, etc.
All queries are read-only. Graph Node does not support mutations via GraphQL - data is only modified by indexing blockchain events.
Query Endpoints
Subgraphs are queryable via HTTP POST to:GraphQL Playground
Open the endpoint in a browser to access GraphiQL, an interactive query playground with:- Schema documentation
- Autocomplete
- Query validation
- Result visualization
Query Structure
Queries follow standard GraphQL syntax and are automatically validated against the subgraph’s schema.Basic Query
Nested Queries
Load related entities in a single request:Query by ID
Fetch a specific entity by its ID:Query Features
Filtering
Graph Node generates comprehensive filter arguments for every entity field:Comparison Operators
Comparison Operators
Available for numeric, string, and byte fields:
field: Equalsfield_not: Not equalsfield_gt: Greater thanfield_gte: Greater than or equalfield_lt: Less thanfield_lte: Less than or equalfield_in: In arrayfield_not_in: Not in array
String Operators
String Operators
Additional operators for string fields:
field_contains: Contains substringfield_not_contains: Does not contain substringfield_starts_with: Starts with prefixfield_not_starts_with: Does not start with prefixfield_ends_with: Ends with suffixfield_not_ends_with: Does not end with suffix
Logical Operators
Logical Operators
Combine multiple conditions:Implementation:
and: All conditions must match (implicit)or: At least one condition must match
store/postgres/src/relational_queries.rs translates to SQL WHERE clauseRelationship Filters
Relationship Filters
Filter by related entity fields using SQL generation: Generates JOINs to related tables
_ suffix:Sorting
Sort results by any field:orderBy: Field to sort byorderDirection:asc(ascending) ordesc(descending)
Pagination
Graph Node supports two pagination strategies:Forward Pagination
Forward Pagination
Use Limitation: Large offsets are inefficient (must scan all skipped rows)Best for: Small datasets or low page numbers
first and skip for offset-based pagination:Cursor-Based Pagination
Cursor-Based Pagination
Use Benefit: Consistent performance regardless of page depthBest for: Large datasets and deep pagination
first with where filter for efficient pagination:Time-Travel Queries
Query historical state at any block number:store/postgres/src/block_range.rs
Full-Text Search
Search text fields with relevance ranking (when enabled in schema):docs/aggregations.md
Aggregations
Compute aggregate values across entities:count: Number of entitiessum: Sum of numeric fieldsavg: Average of numeric fieldsmin: Minimum valuemax: Maximum value
docs/aggregations.md
Meta Field
Query indexing metadata:- Check indexing progress
- Verify data freshness
- Detect indexing errors
Query Processing Pipeline
Graph Node translates GraphQL queries into SQL through several stages:1. Parsing and Validation
The GraphQL query is parsed into an AST and validated:- Query syntax is valid GraphQL
- All fields exist in schema
- Arguments are correctly typed
- Required arguments are present
graphql/src/execution/query.rs
2. Query Planning
The query planner determines optimal execution strategy:- Entity resolution: Map GraphQL types to database tables
- Filter analysis: Identify indexes that can be used
- Join planning: Optimize relationship traversals
- Pagination strategy: Choose offset vs range-based pagination
3. SQL Generation
GraphQL query is translated to SQL:- Constructs SELECT with requested fields
- Adds JOIN clauses for relationships
- Applies WHERE filters
- Adds ORDER BY and LIMIT clauses
- Includes block range filters for time-travel
store/postgres/src/relational_queries.rs
4. Query Execution
SQL executes against PostgreSQL:store/postgres/src/query_store.rs
5. Response Formatting
SQL results are transformed into GraphQL response:- Deserialization: PostgreSQL types → Rust types → GraphQL types
- Relationship assembly: Join nested entities from separate queries
- Type coercion: Apply GraphQL type rules
- JSON formatting: Convert to GraphQL JSON response
Query Optimization
Indexing Strategy
PostgreSQL indexes are critical for query performance: Automatic indexes:- Primary key (
id) - Version ID (
vid) - Block range (
block_range) using GiST index
store/postgres/src/relational.rs:generate_indexes()
Query Complexity Limits
Graph Node enforces limits to prevent resource exhaustion:- Max query depth: Limits nested query levels (default: 8)
- Max result size: Limits returned entities (default: 1000 per query)
- Query timeout: Maximum execution time (configurable)
Query Caching
GraphNode includes query result caching:- Cache key: Query hash + block number
- Invalidation: Automatic on new blocks
- Storage: In-memory cache per query node
Prepared Statements
Frequently-executed queries use prepared statements:- Query plan reuse: Avoids repeated planning overhead
- Parameter binding: Safely inject filter values
- Connection affinity: Same connection reuses prepared statement
Pagination Performance
Best practice: Use cursor-based pagination with indexed fields for large result sets. Avoid
skip with large offsets.Query Performance Monitoring
Metrics
Graph Node exposes query metrics:query_execution_time: Query duration histogramquery_validation_time: Validation timequery_cache_hit_rate: Cache effectivenessquery_parsing_errors: Failed query parsing
http://localhost:8040/metrics
Query Logging
Enable query logging for debugging:- Query text
- Execution time
- Number of results
- SQL execution time
Slow Query Analysis
Identify slow queries:GraphQL Schema Generation
Graph Node automatically generates a rich GraphQL schema from the subgraph’s entity schema.Generated Types
For each entity, Graph Node generates: Query types:entity(id: ID!): Fetch by IDentities(...): Fetch multiple with filtering
Entity_filter: All available filters for entity
Entity_orderBy: Enum of sortable fields
graphql/src/schema/ generates schema from entity definitions
Advanced Query Patterns
Union Queries
Query multiple entity types (when schema supports interfaces):Subscriptions
WebSocket-based real-time subscriptions:ws://localhost:8001/subgraphs/name/<name>
Query Best Practices
Request Only Needed Fields
Don’t fetch unnecessary data. Specify exact fields required.
Use Cursor Pagination
Prefer cursor-based pagination over large offsets for better performance.
Limit Nested Queries
Deep nesting impacts performance. Flatten queries when possible.
Filter Early
Apply filters at the earliest level to reduce data processed.
Troubleshooting
Query Too Complex
Error: “Query exceeds maximum complexity” Solution:- Reduce query depth
- Fetch fewer entities per query
- Split into multiple smaller queries
- Increase
GRAPH_GRAPHQL_MAX_COMPLEXITY
Query Timeout
Error: “Query timeout” Solution:- Optimize filters (ensure indexed fields)
- Reduce result size with
first - Check PostgreSQL for missing indexes
- Increase
GRAPH_GRAPHQL_QUERY_TIMEOUT
Inconsistent Results
Cause: Querying during active indexing Solution:- Check
_meta.hasIndexingErrors - Wait for subgraph to sync (
_meta.block.number) - Use
block: {number: X}for consistent snapshots
Next Steps
Indexing
Understand how data is indexed before querying
Architecture
Learn about Graph Node’s overall architecture
Subgraphs
Deep dive into subgraph structure and manifests
SQL Query Generation
Technical details on SQL generation

