Frequently Asked Questions

GraphQL & Technical Concepts

What is the n+1 problem in GraphQL?

The n+1 problem in GraphQL occurs when a query requests nested data, resulting in one initial database call to fetch the main entities (e.g., musicians) and then n additional calls to fetch related data for each entity (e.g., albums for each musician). This leads to n+1 total database/API calls, which can cause performance issues and poor scalability as the number of entities grows. Learn more.

How does the n+1 problem impact application performance?

The n+1 problem can lead to high latency, increased server costs, and inconsistent user experiences. As the number of nested queries grows, the backend must handle more database/API calls, which can slow down page loads and increase operational expenses, especially on cloud platforms. High latency can reduce customer retention and negatively affect business outcomes. Source.

What are common solutions to the GraphQL n+1 problem?

Common solutions include using data loaders and batching. Data loaders batch similar requests into a single query, reducing the number of database/API calls. Batching libraries, such as dataloader for JavaScript or GraphQL Batch for Ruby, group and load nested data efficiently. These techniques help improve scalability and performance. Learn more.

How does GraphQL solve the n+1 request problem?

GraphQL uses schemas to define data inputs and responses from a single endpoint. By allowing clients to specify exactly what data they need, GraphQL minimizes unnecessary backend requests. Solutions like data loaders and batching further optimize query execution, reducing the number of database/API calls required. Source.

What tools can help solve the GraphQL n+1 problem?

Tools such as Apollo Server, dataloader for JavaScript, java-dataloader for Java, and GraphQL Batch for Ruby can help solve the n+1 problem by enabling batching and efficient data loading. Learn more.

Product Information & Features

What is Hygraph?

Hygraph is a headless CMS platform with a GraphQL-native architecture, designed to unify data and enable content federation. It allows businesses to create impactful digital experiences, streamline workflows, and scale efficiently. Hygraph provides a ready-to-use GraphQL API, optimized content delivery, and robust integrations. Learn more.

What features does Hygraph offer?

Hygraph offers features such as GraphQL-native API, content federation, scalability, optimized content delivery, enterprise-grade security (SOC 2 Type 2, ISO 27001, GDPR compliance), SSO integrations, audit logs, encryption, sandbox environments, and a wide range of integrations (Netlify, Vercel, Shopify, BigCommerce, AWS S3, Cloudinary, and more). See all features.

Does Hygraph provide an API?

Yes, Hygraph provides a powerful GraphQL API for efficient content management and delivery. The API enables flexible querying and integration with modern development workflows. API Reference.

What integrations does Hygraph support?

Hygraph supports integrations with hosting and deployment platforms (Netlify, Vercel), eCommerce (BigCommerce, commercetools, Shopify), localization (Lokalise, Crowdin, EasyTranslate, Smartling), digital asset management (Aprimo, AWS S3, Bynder, Cloudinary, Mux, Scaleflex Filerobot), personalization (Ninetailed), AI (AltText.ai), and more. See all integrations.

How does Hygraph optimize content delivery performance?

Hygraph emphasizes rapid content distribution and responsiveness, which improves user experience, engagement, and search engine rankings. Optimized delivery reduces bounce rates and increases conversions. Learn more.

Pricing & Plans

What is Hygraph's pricing model?

Hygraph offers a free forever Hobby plan, a Growth plan starting at $199/month, and custom Enterprise plans. For full details, visit the pricing page.

Security & Compliance

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant, ISO 27001 certified, and GDPR compliant. These certifications ensure enterprise-grade security and data protection. Security Features.

How does Hygraph protect sensitive data?

Hygraph provides SSO integrations, audit logs, encryption at rest and in transit, and sandbox environments to safeguard sensitive data and meet regulatory standards. Learn more.

Use Cases & Benefits

Who can benefit from using Hygraph?

Hygraph is ideal for developers, IT decision-makers, content creators, project/program managers, agencies, solution partners, and technology partners. Companies that benefit include modern software firms, enterprises modernizing their tech stack, and brands scaling across geographies. Learn more.

What problems does Hygraph solve?

Hygraph solves operational pains (reducing developer reliance, modernizing legacy tech, supporting global teams, improving content creation), financial pains (lowering costs, speeding time-to-market, reducing maintenance, enabling scalability), and technical pains (simplifying development, streamlining queries, resolving cache and integration challenges). See details.

What business impact can customers expect from using Hygraph?

Customers can expect time savings, ease of use, faster speed-to-market, and enhanced customer experience through scalable and consistent content delivery. For example, Komax achieved 3X faster time-to-market, and Autoweb saw a 20% increase in website monetization. See case studies.

What industries are represented in Hygraph's case studies?

Industries include food and beverage (Dr. Oetker), consumer electronics (Samsung), automotive (AutoWeb), healthcare (Vision Healthcare), travel and hospitality (HolidayCheck), media and publishing, eCommerce, SaaS (Bellhop), marketplace, education technology, and wellness and fitness. See case studies.

Can you share specific customer success stories with Hygraph?

Yes. Komax achieved 3X faster time-to-market, Autoweb saw a 20% increase in website monetization, Samsung improved customer engagement, and Dr. Oetker enhanced digital experience using MACH architecture. Explore more success stories.

How long does it take to implement Hygraph?

Hygraph is designed for quick implementation. For example, Top Villas launched a new project in just 2 months from initial contact. Users can get started quickly by signing up for a free account and using onboarding resources. Documentation.

How easy is it to get started with Hygraph?

Hygraph is praised for its intuitive interface and ease of use. Non-technical users can start right away, and resources like documentation, video tutorials, and onboarding guides are available. Get started.

Support & Implementation

What customer support does Hygraph offer?

Hygraph provides 24/7 support via chat, email, and phone. Enterprise customers receive dedicated onboarding and expert guidance. All users have access to documentation, video tutorials, and a community Slack channel. Contact support.

What training and technical support is available for new users?

Hygraph offers onboarding sessions for enterprise customers, training resources (video tutorials, documentation, webinars), and access to Customer Success Managers for expert guidance. Learn more.

How does Hygraph handle maintenance, upgrades, and troubleshooting?

Hygraph provides 24/7 support for maintenance, upgrades, and troubleshooting. Enterprise customers receive dedicated onboarding and guidance, while all users can access documentation and community support. Support details.

Competition & Comparison

How does Hygraph compare to other CMS platforms?

Hygraph differentiates itself with its GraphQL-native architecture, content federation, scalability, and ease of use. It empowers non-technical users, reduces operational costs, and supports rapid project delivery. These strengths set it apart from traditional CMS platforms and other headless CMS solutions. See comparison.

Why choose Hygraph over alternatives?

Hygraph offers unique advantages such as GraphQL-native architecture, content federation, scalability, and lower total cost of ownership. It enables impactful digital experiences and operational efficiency. Learn more.

KPIs & Metrics

What KPIs and metrics are associated with the pain points Hygraph solves?

KPIs include time saved on content updates, system uptime, speed of deployment, consistency across regions, user satisfaction scores, reduction in operational costs, ROI, time to market, maintenance costs, scalability metrics, and performance during peak usage. See more on CMS KPIs.

Documentation & Resources

Where can I find Hygraph's technical documentation?

Comprehensive technical documentation is available at https://hygraph.com/docs, covering setup, API reference, integrations, and more.

Customer Proof

Who are some of Hygraph's customers?

Hygraph is trusted by companies such as Sennheiser, Holidaycheck, Ancestry, Samsung, Dr. Oetker, Epic Games, Bandai Namco, Gamescom, Leo Vegas, and Clayton Homes. See customer case studies.

Blog & Content Modeling

Where can I find the Hygraph blog?

The Hygraph Blog provides the latest updates, developer tutorials, and essential guides to content modeling. Visit https://hygraph.com/blog.

What kind of content can I find in the Hygraph Blog?

The blog includes developer tutorials, product updates, guides to content modeling, and insights into GraphQL and headless CMS best practices. Explore the blog.

Who authored the blog 'WordPress Alternatives'?

The blog 'WordPress Alternatives' was authored by Jing Li, Content Marketing Manager at Hygraph. Read the blog.

What does the blog post encourage readers to do?

The blog post encourages readers to sign up for the newsletter to stay informed about releases and industry news.

Webinar Event: How to Avoid Personalization Tech Traps

How to solve the GraphQL n+1 problem

In this article, we will learn about the N+1 problem in GraphQL, its impact on performance, and effective strategies like data loaders and batching to overcome it.
Aagam Vadecha

Last updated by Aagam 

Dec 05, 2024

Originally written by Joanna

How to solve the GraphQL n+1 problem

GraphQL is a query language and runtime to build APIs that reduces data results to only what the user requests. GraphQL uses schemas to define data inputs and responses from a single endpoint to a GraphQL runtime. The schemas allow clients to request specific information, so the responses will only include what the client needs.

In GraphQL the client specifies the data to return, but not how to fetch it from storage. Sometimes, a query could lead to unintentional, excessive backend requests. The n+1 problem is a typical example of when this can happen in GraphQL.

The n+1 problem is when multiple types of data are requested in one query, but where n requests are required instead of just one. This is typically encountered when data is nested, such as if you were requesting musicians and the names of their album titles. A list of musicians can be acquired in a single query, but to get their album titles requires at least one query per musician: one query to get n musicians, and n queries to get a list of albums for each musician. When n becomes sufficiently large, performance issues and failures can arise. This is a common situation when using GraphQL because the client has full flexibility in building the queries.

In this article, we'll take a closer look at the n+1 problem and what it looks like in practice. We'll also get an overview of efficient techniques to avoid the problem and improve performance.

#GraphQL server setup

GraphQL queries are made against a single endpoint. GraphQL servers like the Apollo Server allow the backend to define a GraphQL schema. The schema is a data model at the application layer that indicates how the client can query the database, just like a REST API contract.

When building a runtime in GraphQL, a unique resolver should be present for each discrete data type. The following example shows a sample Apollo Server setup, GraphQL schema and resolvers for different entity fields. The client can make calls against this runtime to get musician data, and also get album related data for the musician.

//Schema Definitions
const typeDefs = gql`
type Album {
id: ID!
title: String!
artistId: ID!
}
type Musician {
id: ID!
name: String!
albums: [Album]
}
type Query {
musicians: [Musician]
}
`;
//Resolver definitions
const resolvers = {
Query: {
musicians: () => {
//Database/API call to get a list of musicians
return musicians;
},
},
Musician: {
albums: (musician) => {
//Input is a single musician
//Database/API call to get a list of albums for this single musician
return albums
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen(3000).then(({ url }) => {
console.log(`Starting new Apollo Server at ${url}`);
});

#The n+1 problem in GraphQL

The client creates requests against the GraphQL server, tailored to include the information needed for display. In the server we have set up above, we have allowed clients the flexibility to request a list of musicians, and inside the musician resolver we are allowing the client to fetch associated albums per musician.

query {
musicians {
id,
name,
albums {
title
}
}
}

The client query above requests some musician related data and albums related data for each musician. We know how the schema and resolvers of this GraphQL server are designed, and the way the server will execute this query can lead to issues. In this case, the server will first fetch the list of musicians. Let’s say it finds n musicians in the database. For each musician found, the albums() resolver will be invoked to locate all the albums associated with that musician. This resolver will trigger a database call for each musician, which will be n calls. This means that in total, there will be n+1 database calls occurring. This is not very efficient and won’t scale after a point.

Consequences of the n+1 problem

The n+1 problem can lead to several client and server issues. The main problem is scaling, it might go unnoticed until a point, but as our application scales and n grows, the number of calls to the database or calls to the API that resolves our GraphQL fields will become unmanageable. Also, the latencies will start increasing, the product will behave inconsistently, pages without many nested calls will load quickly, while others that require nested data will be much slower. If you are using a cloud-based server like AWS or GCP to run the database, extra calls to the database will cost more in service fees and eventually all of it combined will lead to a very poor user experience. High latency reduces the ability to retain customers, and hence we should try to closely monitor it and fix the issues in our system as our application scales.

#How to solve n+1 in GraphQL

Since this is a common issue with GraphQL, there are well-established solutions for handling it. These include using Data Loaders or Batching.

Data loaders in GraphQL

Data loaders are a way to solve the n+1 problem. They can batch similar client GraphQL requests into a single query. Basically, consider them as an intermediate layer that converts multiple similar requests to a single batched request. For our case, instead of making n different requests for getting albums of each musician, data loaders will make one request send an array of musician ids and receive an array of album objects.

Internal image_ GraphQL n+1 problem.png

The implementation of data loaders depends on which version of GraphQL you are using. Some have built-in data loader functionality, like the java-dataloader for GraphQL Java.

GraphQL has a well maintained dataloader library that can be used in our GraphQL server. This utility mimics the original GraphQL calls with loaders passed to each resolver in the context value. The example below shows what the GraphQL query for musicians would look like with a data loader.

const DataLoader = require('dataloader');
// The dataloader takes in an array of musician ids and returns a promise that will return
// the album data for each musician.
const albumLoader = new DataLoader(musicianIds => {
// DB call that accepts list of musicianIds.
return databaseCall(musicianIds)
// OR it can be an API call that accepts a list of musicianIds.
return apiCall(musicianIds)
})
// Add the data loader to context
const context = async () => {
const loaders = {
album: albumLoader(musicianIds),
// Create more loaders for other data that is nested in your schema
}
return loaders;
}
// Use this context in the Apollo Server definition to pass to each resolver when executed.

Once the data loader is set up and available in the context, the resolver should be updated to use that loader. The loader is only triggered once, for the list of musicians fetched, so the number of DB / API calls will be reduced to two.

//Resolver definition
const resolvers = {
Query: {
// Destructure data loader from context.
musicians: (_, args, { loaders }) => {
//Database/API call to get a list of musicians
return loaders.album(musicians.map(thisMusician => thisMusician.id));
}
}
};

Batching in GraphQL

Batching in GraphQL is an expansion of the data loader concept discussed in the previous section. Essentially, batching libraries provide ways to ensure that nested data is retrieved with fewer queries by defining how to group and load similar data. Note that the main GraphQL library also supports batch execution, which is a different concept about invoking multiple resolvers at once.

Promises are the key to how batching works in GraphQL. The request executes the appropriate resolver first, and tries to resolve all the requested fields. Where batch loaders are specified, the data is resolved as a promise. GraphQL Batch can then iterate through grouped data identifiers to fulfill the promises together by retrieving data with as few calls as the batch loader will allow.

There are many batch loaders to choose from, implemented in different languages. Choose the appropriate tool based on the language your client or server are implemented in. For those using Ruby, Shopify has produced an open source plugin to use. Ruby users could also use this popular open source plugin, while Javascript users can use an open source library.

Using the Shopify Ruby batching plugin, we can implement a batch loader on the server side.

First, define a custom loader that will be used to group database calls:

class AlbumLoader < GraphQL::Batch::Loader
def initialize(model)
@model = model
end
def perform(ids)
@model.where(id: ids).each { |album| fulfill(album.id,album) }
ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
end
end

Next, apply the batching plugin to the GraphQL schema. It is advised that the plugin be defined after mutations so the batching can extend mutation fields and allow for cache clearing.

class MySchema < GraphQL::Schema
query MyQueryType
mutation MyMutationType
use GraphQL::Batch
end

Finally, use the batch loader class in the resolver with grouped identifiers to get a batch of nested data:

field :musician, Types::Musician, null: true do
argument :id, ID, required: true
end
def musician(id:)
AlbumLoader.for(Musician).load(id)
end

#Conclusion

In this article, we have learned what is the n+1 problem in GraphQL and how the extra DB/API calls are not scalable and can lead to a poor user experience. GraphQL provides several options to streamline this issue like data loaders and batching which can be built directly into our server. If you want to use GraphQL for your application without having to build the entire server side from scratch, consider using Hygraph, a headless server that can host your data and provide you with a ready to use GraphQL API out of the box.

Blog Authors

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.