- What GraphQL is and why it was designed as an alternative to REST
- How Salesforce's GraphQL API works — the schema, queries, and mutations
- The over-fetching and under-fetching problems GraphQL solves in the Salesforce REST API context
- Current limitations of Salesforce GraphQL versus the REST and SOQL APIs
- Which use cases GraphQL is well-suited for in the Salesforce ecosystem
- Performance characteristics and rate limit implications of the GraphQL API
Why GraphQL Exists
GraphQL was developed by Facebook in 2012 and open-sourced in 2015 to solve a fundamental REST API problem: the impedance mismatch between what an API returns and what the client actually needs. REST APIs return fixed resource shapes — a GET /accounts/{id} returns a predefined set of Account fields. If the mobile app only needs three of those thirty fields, it is still fetching all thirty (over-fetching). If it also needs the related Contacts, it makes a second API call (under-fetching, leading to the N+1 query problem).
GraphQL addresses this with a client-driven query model: the client specifies exactly which fields it needs, including related resources, and the server returns only those fields. A single GraphQL query can retrieve an Account with its primary Contact and open Opportunities — without the client knowing the server's object model in detail, and without making three separate REST API calls.
For the Salesforce use case, this is genuinely valuable for front-end applications (Lightning web components, mobile apps, external portals) that need to compose custom views of Salesforce data efficiently. The traditional alternative — a custom REST endpoint built in Apex that assembles the specific data shape needed by the UI — still works but requires Apex development for every new UI requirement. GraphQL shifts that composition responsibility to the query layer.
Salesforce GraphQL API Architecture
The Salesforce GraphQL API is available at /services/data/v{version}/graphql. It uses the same OAuth 2.0 authentication as the REST API and respects the same object-level and field-level security (FLS) permissions. The GraphQL schema is auto-generated from the Salesforce org's metadata — every object and field accessible to the authenticated user is available in the GraphQL schema without any additional configuration.
Queries are the primary operation for reading data. A GraphQL query specifies the object type, the fields to retrieve, and optional filter and sort parameters. Mutations handle DML operations — creating, updating, and deleting records. Unlike REST where the operation type is conveyed by the HTTP method (GET, POST, PATCH, DELETE), GraphQL uses a single HTTP POST endpoint for all operations, with the operation type and parameters in the request body.
// Salesforce GraphQL query — Account with related Contacts
POST /services/data/v60.0/graphql
Content-Type: application/json
Authorization: Bearer {token}
{
"query": "query GetAccountWithContacts($acctId: ID!) {
uiapi {
query {
Account(where: { Id: { eq: $acctId } }) {
edges {
node {
Id
Name
Industry
AnnualRevenue { value }
Contacts {
edges {
node {
Id
FirstName
LastName
Email { value }
Title { value }
}
}
}
}
}
}
}
}
}",
"variables": { "acctId": "001XXXXXXXXXXXX" }
}
The Problems It Solves vs The Problems It Creates
GraphQL solves the multi-object fetch problem elegantly. The query above retrieves an Account and all its Contacts in a single HTTP request — without a second API call for the Contacts related list. In REST, this would require a GET /accounts/{id} followed by a GET /accounts/{id}/contacts — two API calls, two network round trips, and the client assembling the response. GraphQL eliminates this overhead for UI-rendering scenarios.
GraphQL also solves the field selection problem for bandwidth-constrained clients (mobile apps on cellular, high-traffic APIs where payload size affects cost). A mobile app that only needs Account Name and Industry from an Account record can request exactly those two fields, receiving a response roughly 10x smaller than the full REST Account response. For an app making thousands of Account queries, this reduces bandwidth materially.
The problems GraphQL creates are query complexity management and the N+1 query problem in the server implementation. When a GraphQL query requests a list of 100 Accounts and for each Account requests its Contacts, the naive server implementation makes 100 separate database queries — one for each Account's Contacts. Salesforce's implementation uses DataLoader batching to mitigate this, but deep nested queries with large collections can still generate significant server-side processing. Query depth and complexity limits exist to prevent abuse.
Current Limitations of Salesforce GraphQL
Salesforce's GraphQL API, while growing, has significant limitations compared to the REST and SOQL API as of 2026. Aggregate queries (COUNT, SUM, AVG, GROUP BY) are not supported — reporting use cases requiring aggregations must use the SOQL-based REST API or Reports API. SOQL features like HAVING clauses, complex subqueries, and polymorphic fields are either not supported or have limited support in GraphQL.
Bulk operations — creating, updating, or deleting hundreds or thousands of records — are not appropriate for GraphQL. GraphQL mutations operate on individual records or small batches. High-volume DML operations must continue to use the Bulk API 2.0. GraphQL is optimised for the query-and-display use case, not the data processing use case.
Rate limits for GraphQL are shared with the REST API limits — each GraphQL request counts as one API call against the 24-hour limit. However, because a well-designed GraphQL query can replace multiple REST calls, the net API call consumption can be lower for GraphQL-native applications. The inverse risk: a poorly designed GraphQL query with deep nesting that generates many server-side sub-queries can have disproportionate impact on server load even with normal API call count.
When to Use Salesforce GraphQL
GraphQL is well-suited for Lightning web component data fetching where the component needs to retrieve composite data (parent + children + related) in a single network request. The @wire adapter for GraphQL in LWC allows declarative data fetching with the GraphQL query syntax, providing better field-level control than the equivalent @wire adapters for specific Salesforce APIs. For complex UI components that currently make multiple wire calls or use imperative Apex, GraphQL wire can reduce both Apex development and API call overhead.
External mobile applications built by front-end teams unfamiliar with SOQL benefit significantly from GraphQL — the query model is familiar to React Native and Flutter developers, and the type system auto-generated from Salesforce metadata provides developer-friendly schema documentation. The GraphQL schema serves as the contract between Salesforce and the mobile app without requiring the mobile team to understand Salesforce's object model deeply.
GraphQL is not appropriate as the primary API for integration middleware, ETL operations, bulk data export, or analytics queries requiring aggregation. These use cases should continue to use the REST API with SOQL queries or the Bulk API 2.0. The decision is clear: UI-facing, field-selective, relationship-traversing queries benefit from GraphQL. Data-volume, analytics, and automation use cases do not.
Key Takeaways
- GraphQL solves over-fetching (receiving fields the client doesn't need) and under-fetching (needing multiple API calls for related data) by allowing clients to specify exactly what fields and related resources they need in a single query.
- Salesforce GraphQL auto-generates its schema from the org's metadata and respects all existing FLS and object-level security — no additional configuration is required to start querying accessible objects.
- A single GraphQL query can traverse parent-child relationships and retrieve nested data without multiple API round trips — the primary value for UI-rendering scenarios.
- Aggregate queries (SUM, COUNT, GROUP BY), complex SOQL subqueries, and bulk DML operations are not supported by Salesforce GraphQL. These use cases must continue using the REST SOQL API or Bulk API.
- GraphQL is best suited for Lightning web components with complex data requirements and external mobile/web applications built by front-end teams — not for integration middleware, ETL, or analytics workloads.
- GraphQL introspection exposes the full object and field schema to authenticated callers — consider carefully before enabling on externally-accessible Salesforce APIs.
Test Your Understanding
1. A React Native mobile app displays a sales rep's Account list with the rep's name, Account Name, last activity date, and count of open Opportunities. The current implementation makes three REST API calls per Account to assemble this view. What does GraphQL provide here?
2. A data analyst wants to use the Salesforce GraphQL API to generate a report showing total Opportunity value by Account industry, grouped by fiscal quarter. Is GraphQL appropriate for this use case?
3. A GraphQL query requests 500 Accounts, and for each Account requests all related Contacts. If each Account has an average of 8 Contacts, how many database-level sub-queries does a naive GraphQL server implementation execute for this request?
Discussion & Feedback