What are GraphQL queries and how do they differ from REST API requests?
GraphQL queries are entry points on a GraphQL server that provide read access to your data sources. Unlike REST APIs, which return fixed data structures from predefined endpoints, GraphQL queries allow clients to specify exactly which fields and data structures they want in the response. This flexibility enables more efficient data fetching and reduces over-fetching or under-fetching of data. Note: The exact syntax and available fields depend on the server-side implementation and schema documentation. For more, see the Hygraph Getting Started guide.
How can I test and debug GraphQL queries in Hygraph?
Hygraph provides an API playground directly in the dashboard, allowing you to create schemas, define relations, and test queries interactively. The playground supports IntelliSense for easier query writing and debugging, and you can view both the schema and available queries. This tool is useful for both frontend and backend teams before integrating queries into applications. Note: For advanced debugging, always refer to the schema documentation and use named queries for better server-side logging. See the API Playground documentation for details.
What are best practices for writing GraphQL queries in Hygraph?
Best practices include using named queries and variables instead of hardcoded arguments, leveraging fragments to avoid code duplication, and using aliases when querying the same field with different conditions. Named queries help with debugging and server-side logging, while fragments make queries more modular and maintainable. For example, use variables for dynamic arguments and fragments to reuse field selections. Note: Always consult the schema documentation for available fields and argument formats. See the GraphQL variables guide for more details.
How do filters work in GraphQL queries with Hygraph?
Filters in GraphQL queries allow you to retrieve specific data based on criteria, similar to SQL WHERE clauses. In Hygraph, you can apply filters at both the top-level and nested query levels to fetch only the records you need. The available filters depend on your schema and server implementation. For example, you can filter users by email or retrieve contacts whose names start with a specific letter. Note: The exact filter syntax is determined by your schema; always check the API playground for supported filters.
Features & Capabilities
What APIs does Hygraph provide for content management?
Hygraph offers several APIs: the GraphQL Content API for querying and manipulating content, the Management API for handling project structure (accessible via the Management SDK), the Asset Upload API for uploading files, and the MCP Server API for secure communication between AI assistants and Hygraph. Each API is optimized for specific use cases, such as high performance and low latency for content delivery. Note: Some advanced features may require specific project configurations. See the API Reference documentation for details.
What integrations are available with Hygraph?
Hygraph supports integrations with Digital Asset Management (DAM) systems like Aprimo, AWS S3, Bynder, Cloudinary, Imgix, Mux, and Scaleflex Filerobot; hosting and deployment platforms such as Netlify and Vercel; Product Information Management (PIM) like Akeneo; commerce solutions like BigCommerce; and translation/localization tools such as EasyTranslate. For a full list, visit the Hygraph Marketplace. Note: Integration availability may depend on your plan and project setup.
What performance optimizations does Hygraph offer for content delivery?
Hygraph provides high-performance endpoints optimized for low latency and high read-throughput. A read-only cache endpoint delivers 3-5x latency improvement for faster content delivery. The platform also actively measures GraphQL API performance and offers practical advice for developers. For more, see the High-Performance Endpoint blog post and the GraphQL Report 2024. Note: Performance may vary based on project complexity and usage patterns.
Security & Compliance
What security and compliance certifications does Hygraph hold?
Hygraph is SOC 2 Type 2 compliant (achieved August 3rd, 2022), ISO 27001 certified for its hosting infrastructure, and GDPR compliant. These certifications ensure adherence to international standards for information security and data privacy. For more, visit the Secure Features page. Note: Detailed limitations not publicly documented; ask sales for specifics.
What security features are available in Hygraph?
Hygraph offers granular permissions, SSO integrations (OIDC/LDAP/SAML), audit logs, encryption in transit and at rest, regular backups with one-click recovery, and secure API policies including custom origin policies and IP firewalls. All endpoints have SSL certificates. Note: Some features may require enterprise plans or specific configurations. See the Secure Features page for details.
Use Cases & Implementation
Who can benefit from using Hygraph?
Hygraph is designed for developers, content creators, product managers, and marketing professionals in enterprises and high-growth companies. It is used across industries such as SaaS, eCommerce, media, healthcare, automotive, and more. Its flexibility and scalability make it suitable for teams needing advanced content management, localization, and integration capabilities. Note: Teams with highly specialized legacy systems may require additional migration planning.
What business impact can customers expect from using Hygraph?
Customers have reported faster time-to-market (e.g., Komax achieved 3X faster launches), improved customer engagement (Samsung saw a 15% increase), cost reduction, and enhanced content consistency. Hygraph supports scaling content across multiple channels and markets, with proven ROI in case studies such as AutoWeb (20% increase in website monetization) and Voi (multilingual content across 12 countries). Note: Results may vary based on implementation scope and team adoption. See case studies for details.
How long does it take to implement Hygraph and how easy is it to start?
Implementation timelines vary: Top Villas launched in 2 months, Voi migrated from WordPress in 1-2 months, and Si Vale met aggressive deadlines in the initial phase. Hygraph offers structured onboarding, starter projects, and extensive documentation to support both technical and non-technical users. Sign up for a free account at app.hygraph.com/signup. Note: Complex migrations may require additional planning and support. See Getting Started for more.
Customer Proof & Success Stories
What feedback have customers given about Hygraph's ease of use?
Customers praise Hygraph for its intuitive interface and accessibility for both technical and non-technical users. For example, Sigurður G. (CTO) noted the UI is intuitive, Anastasija S. (Product Content Coordinator) highlighted instant front-end updates, and Charissa K. (Senior CMS Specialist) emphasized the clear setup and localization features. Note: Some advanced features may require technical onboarding for full utilization. See more reviews at Hygraph's trial page.
Can you share specific case studies or success stories of customers using Hygraph?
Yes. Notable examples include Samsung (15% improved engagement), Komax (3X faster time to market), AutoWeb (20% increase in monetization), Voi (scaled content in 12 countries), and Dr. Oetker (enhanced digital experience with MACH architecture). For more, see the case studies page. Note: Outcomes depend on project scope and team adoption.
Technical Documentation & Support
What technical documentation and resources are available for Hygraph users?
Hygraph provides extensive documentation, including API references, schema guides, integration tutorials (e.g., Mux, Akeneo, Auth0), AI feature docs, and getting started guides. Classic documentation is available for legacy users. Training resources include webinars, live streams, and community support via Slack. See Hygraph Documentation for details. Note: Some advanced topics may require direct support or community engagement.
Queries are entry points on a GraphQL server that provides read access to your data sources.
What are GraphQL Queries?
Queries are entry points on a GraphQL server that provides read access to your data sources. GraphQL queries are a powerful tool for clients as they can dictate the fields they want and the response structure. With a REST API, you will be hitting an API endpoint and getting some fixed data structure according to an API contract agreed upon earlier, but a GraphQL query is very much flexible and dynamic the client is free to fetch whatever it wants. In this article, we will cover the fundamentals of GraphQL queries.
GraphQL Playground
A GraphQL server provides you with a playground, where you can see the GraphQL schema, all the available types, and the queries that you can perform. A GraphQL playground comes in very handy when you do not have a frontend application ready and want to test out your server, also it gives you IntelliSense and simplifies writing operations. It is a place where you can test out your queries and mutations, and see what data they respond with before integrating your queries with a front-end application. A GraphQL playground can be used by both frontend and backend teams as per their own needs.
Hygraph provides an API playground in the dashboard itself, you can create your schema, and relations and then test out your queries using this API playground. Your query would go to the section on the left-hand side and you would get results on the right-hand side.
Basic Query
To better understand GraphQL queries, let us take a look at the basic structure of a very simple query.
For example:
# Query
query{
user(id:1){
name
email
}
}
# Response
{
"data":{
"user":{
"name":"John Doe",
"email":"johndoe@hygraph.com"
}
}
}
This is a very simple query let us break it down further:
An operation type can be either query, mutation, or subscription. Here the keyword query tells us that this operation type is a GraphQL query
The field user is the entry point, it is the root field that informs the server that we want to query the user entity.
The id is an argument passed with the query to resolve the appropriate data for the user we want.
name and email are the fields that we want the server to get from the data source.
One important thing to note is that the query syntax is not set in stone. The root level query exposed by the server could be named getUserById instead of user, and the format to pass arguments could be (where: { id: 1 }) instead of (id: 1).
For example:
query{
getUserById(where:{id:1}){
name
email
}
}
The query above is also equivalent to the query we saw earlier. The exact syntax is dependent on the server-side implementation and it will determine how exactly your GraphQL query will look. Information on the exact syntax will be available in the schema documentation in the API playground and you can also use IntelliSense in any GraphQL playground to see what options are available at each step.
Try Hygraph, the GraphQL native headless CMS
Build limitless solutions rapidly with our GraphQL-native API-first approach
In real-world scenarios, relations between entities often exist and you need to extract data from more than one database table. We can say that a user can have many addresses probably in different countries. So in this case there is a one-to-many relationship between the user and address entities and a one-to-one relationship between the address and country entity.
In order to see all the addresses that belong to a user and the country details for each address, we will need to construct a client-side GraphQL nested query that would get all the user details, details of all his addresses, and for each address the corresponding country details.
Here is how a nested query for the same will look like
# Query
query{
user(id:1){
name
email
address{
street
city
country{
name
capital
}
}
}
}
# Response
{
"data":{
"user":{
"name":"John Doe",
"email":"johndoe@hygraph.com",
"address":[{
"street":"123 Main St",
"city":"Berlin",
"country":{
"name":"Germany",
"capital":"Berlin"
}
},
{
"street":"456 Second Ave",
"city":"Mumbai",
"country":{
"name":"India",
"capital":"New Delhi"
}
}]
}
}
}
Querying with Filters
GraphQL queries can be made more powerful and efficient by using filters. Filters are used to retrieve specific data based on a set of criteria, you can consider filters as a where clause in a SQL query. The filters exposed to the client for querying will depend on the GraphQL server implementation. You can use filters on queries and even nested queries to get the exact records that you want to retrieve. For example, If you want to retrieve users whose email has hygraph.com in it and also want to get all contacts for each user that start with the letter A, here is what the query will look like:
# Query
querygetUserContacts{
users(where:{email_contains:"hygraph.com"}){
email
contacts(where:{name_starts_with:"A"}){
name
}
}
}
# Response
{
"data":{
"users":[
{
"email":"johndoe@hygraph.com",
"contacts":[
{
"name":"Alice",
"phone":"789654123"
},
{
"name":"Andrew",
"phone":"123654878"
}
]
},
{
"email":"janedoe@hygraph.com",
"contacts":[
{
"name":"Ashley",
"phone":"8522123659"
}
]
}
]
}
}
Best Practices For GraphQL Queries
Named Queries & Variables
So far we have only written raw queries that take the raw arguments directly and have no names. In production applications, there can be hundreds of queries and it might get very difficult to manage them if you are not using named queries. Also, you do not have raw argument values like 1 or John Doe, you have variables that store this value and you need to pass these variables to your queries.
Here is our previous example of a query for getting a user:
query{
user(id:1){
name
email
}
}
This is an equivalent named query version for the same example:
querygetUserById($userId:ID!){
user(id:$userId){
name
email
}
}
We saw the operation type earlier (query, mutation, subscription). Here we are also adding an Operation Name - getUserById. The operation name is an explicit and meaningful name given to a GraphQL operation. Although not mandatory, it is recommended to use them as they can greatly aid in debugging and server-side logging. When there is an error either in the network logs or the GraphQL server logs, it is easier to identify the problematic query by name rather than decoding its contents. If you are from a Javascript background, it is similar to giving a name to an anonymous function - it can be worked with without a name, but naming it makes it easier to debug and track down in your codebase. Similarly, GraphQL operation names can help identify different GraphQL requests on the server side, making it a useful tool for debugging.
Instead of hardcoding the arguments to GraphQL queries, we should be using variables. If you notice the code just after the operation name that is - ($userId: ID!). This signifies that the operation accepts a variable named userId which is of the type ID!, this variable is then passed on to the actual root field query i.e. user where it is supplied as value for the argument id. We will learn more about GraphQL variables in this article.
As a best practice, all queries coming from clients should be named queries and should use variables instead of hardcoded arguments in a production application.
Using Fragments
Suppose you're building a social media app that allows users to create and share posts, as well as comment on and like other users' posts. You want to display a list of posts in the user's feed, with information about the post's author, content, and any comments or likes associated with the post.
To retrieve this information, you might use a GraphQL query that looks something like this:
query{
feed{
id
author{
name
profilePictureUrl
}
content
comments{
author{
name
profilePictureUrl
}
text
}
likes{
author{
name
profilePictureUrl
}
}
}
}
This query retrieves the id, author, content, comments, and likes fields for each post in the user's feed. However, notice that the author field is repeated multiple times - once for each of the author fields nested under comments and likes. This can result in a lot of duplicated code and make the query harder to read and maintain.
To simplify the query and make it more modular, you might use a fragment to define the author field once, and then reference it multiple times throughout the query. Here's what that might look like
query{
feed{
id
author{
...authorFields
}
content
comments{
author{
...authorFields
}
text
}
likes{
author{
...authorFields
}
}
}
}
fragmentauthorFieldsonUser{
name
profilePictureUrl
}
In this updated query, we've defined a fragment called authorFields that includes the name and profilePictureUrl fields for a user. We then reference this fragment multiple times throughout the query, both in the author field at the top level of the query and in the author fields nested under comments and likes.
Using fragments in this way allows us to define common pieces of a query once and reuse them throughout the query. This can make the query more modular, easier to read, and easier to maintain. Additionally, if we ever need to update the fields we're retrieving for a user, we can simply update the author fields fragment, rather than having to update every instance of the author field throughout the query.
Using Aliases
At times it is possible that you might be querying the same field twice in a query with different conditions. For instance, you want to get addresses for a user and you also want to bifurcate the primary and secondary address in the query itself, so in this use case you will write a query as shown below
querygetUserAddressDetails($userId:ID!){
user(id:$userId){
address(type:"primary"){
...addressFields
}
address(type:"secondary"){
...addressFields
}
}
}
However, this query would not work as there are two fields with the same name - address, the server would simply give out a validation error for your query. In such cases you need to use aliases in your query this is how the correct query would look like
# Query
querygetUserAddressDetails($userId:ID!){
user(id:$userId){
primaryAddress:address(type:"primary"){
...addressFields
}
secondaryAddress:address(type:"secondary"){
...addressFields
}
}
}
# Response
{
"data":{
"user":{
"name":"John Doe",
"primaryAddress":{
"street":"123 Main St",
"city":"Berlin"
},
"secondaryAddress":{
"street":"456 Second Ave",
"city":"Mumbai"
}
}
}
}
Conclusion
In this article, we explored how to GraphQL queries and how powerful they are for clients as they support declarative data fetching. We saw the anatomy of a GraphQL query, checked out basic queries, and explored further depth with nested queries and filtering capabilities. In addition to this, we explored best practices and available tools like the GraphQL playground, fragments, aliases, named queries, and variables, that can help developers optimize their GraphQL queries and build more efficient applications.
Queries are entry points on a GraphQL server that provides read access to your data sources.
What are GraphQL Queries?
Queries are entry points on a GraphQL server that provides read access to your data sources. GraphQL queries are a powerful tool for clients as they can dictate the fields they want and the response structure. With a REST API, you will be hitting an API endpoint and getting some fixed data structure according to an API contract agreed upon earlier, but a GraphQL query is very much flexible and dynamic the client is free to fetch whatever it wants. In this article, we will cover the fundamentals of GraphQL queries.
GraphQL Playground
A GraphQL server provides you with a playground, where you can see the GraphQL schema, all the available types, and the queries that you can perform. A GraphQL playground comes in very handy when you do not have a frontend application ready and want to test out your server, also it gives you IntelliSense and simplifies writing operations. It is a place where you can test out your queries and mutations, and see what data they respond with before integrating your queries with a front-end application. A GraphQL playground can be used by both frontend and backend teams as per their own needs.
Hygraph provides an API playground in the dashboard itself, you can create your schema, and relations and then test out your queries using this API playground. Your query would go to the section on the left-hand side and you would get results on the right-hand side.
Basic Query
To better understand GraphQL queries, let us take a look at the basic structure of a very simple query.
For example:
# Query
query{
user(id:1){
name
email
}
}
# Response
{
"data":{
"user":{
"name":"John Doe",
"email":"johndoe@hygraph.com"
}
}
}
This is a very simple query let us break it down further:
An operation type can be either query, mutation, or subscription. Here the keyword query tells us that this operation type is a GraphQL query
The field user is the entry point, it is the root field that informs the server that we want to query the user entity.
The id is an argument passed with the query to resolve the appropriate data for the user we want.
name and email are the fields that we want the server to get from the data source.
One important thing to note is that the query syntax is not set in stone. The root level query exposed by the server could be named getUserById instead of user, and the format to pass arguments could be (where: { id: 1 }) instead of (id: 1).
For example:
query{
getUserById(where:{id:1}){
name
email
}
}
The query above is also equivalent to the query we saw earlier. The exact syntax is dependent on the server-side implementation and it will determine how exactly your GraphQL query will look. Information on the exact syntax will be available in the schema documentation in the API playground and you can also use IntelliSense in any GraphQL playground to see what options are available at each step.
Try Hygraph, the GraphQL native headless CMS
Build limitless solutions rapidly with our GraphQL-native API-first approach
In real-world scenarios, relations between entities often exist and you need to extract data from more than one database table. We can say that a user can have many addresses probably in different countries. So in this case there is a one-to-many relationship between the user and address entities and a one-to-one relationship between the address and country entity.
In order to see all the addresses that belong to a user and the country details for each address, we will need to construct a client-side GraphQL nested query that would get all the user details, details of all his addresses, and for each address the corresponding country details.
Here is how a nested query for the same will look like
# Query
query{
user(id:1){
name
email
address{
street
city
country{
name
capital
}
}
}
}
# Response
{
"data":{
"user":{
"name":"John Doe",
"email":"johndoe@hygraph.com",
"address":[{
"street":"123 Main St",
"city":"Berlin",
"country":{
"name":"Germany",
"capital":"Berlin"
}
},
{
"street":"456 Second Ave",
"city":"Mumbai",
"country":{
"name":"India",
"capital":"New Delhi"
}
}]
}
}
}
Querying with Filters
GraphQL queries can be made more powerful and efficient by using filters. Filters are used to retrieve specific data based on a set of criteria, you can consider filters as a where clause in a SQL query. The filters exposed to the client for querying will depend on the GraphQL server implementation. You can use filters on queries and even nested queries to get the exact records that you want to retrieve. For example, If you want to retrieve users whose email has hygraph.com in it and also want to get all contacts for each user that start with the letter A, here is what the query will look like:
# Query
querygetUserContacts{
users(where:{email_contains:"hygraph.com"}){
email
contacts(where:{name_starts_with:"A"}){
name
}
}
}
# Response
{
"data":{
"users":[
{
"email":"johndoe@hygraph.com",
"contacts":[
{
"name":"Alice",
"phone":"789654123"
},
{
"name":"Andrew",
"phone":"123654878"
}
]
},
{
"email":"janedoe@hygraph.com",
"contacts":[
{
"name":"Ashley",
"phone":"8522123659"
}
]
}
]
}
}
Best Practices For GraphQL Queries
Named Queries & Variables
So far we have only written raw queries that take the raw arguments directly and have no names. In production applications, there can be hundreds of queries and it might get very difficult to manage them if you are not using named queries. Also, you do not have raw argument values like 1 or John Doe, you have variables that store this value and you need to pass these variables to your queries.
Here is our previous example of a query for getting a user:
query{
user(id:1){
name
email
}
}
This is an equivalent named query version for the same example:
querygetUserById($userId:ID!){
user(id:$userId){
name
email
}
}
We saw the operation type earlier (query, mutation, subscription). Here we are also adding an Operation Name - getUserById. The operation name is an explicit and meaningful name given to a GraphQL operation. Although not mandatory, it is recommended to use them as they can greatly aid in debugging and server-side logging. When there is an error either in the network logs or the GraphQL server logs, it is easier to identify the problematic query by name rather than decoding its contents. If you are from a Javascript background, it is similar to giving a name to an anonymous function - it can be worked with without a name, but naming it makes it easier to debug and track down in your codebase. Similarly, GraphQL operation names can help identify different GraphQL requests on the server side, making it a useful tool for debugging.
Instead of hardcoding the arguments to GraphQL queries, we should be using variables. If you notice the code just after the operation name that is - ($userId: ID!). This signifies that the operation accepts a variable named userId which is of the type ID!, this variable is then passed on to the actual root field query i.e. user where it is supplied as value for the argument id. We will learn more about GraphQL variables in this article.
As a best practice, all queries coming from clients should be named queries and should use variables instead of hardcoded arguments in a production application.
Using Fragments
Suppose you're building a social media app that allows users to create and share posts, as well as comment on and like other users' posts. You want to display a list of posts in the user's feed, with information about the post's author, content, and any comments or likes associated with the post.
To retrieve this information, you might use a GraphQL query that looks something like this:
query{
feed{
id
author{
name
profilePictureUrl
}
content
comments{
author{
name
profilePictureUrl
}
text
}
likes{
author{
name
profilePictureUrl
}
}
}
}
This query retrieves the id, author, content, comments, and likes fields for each post in the user's feed. However, notice that the author field is repeated multiple times - once for each of the author fields nested under comments and likes. This can result in a lot of duplicated code and make the query harder to read and maintain.
To simplify the query and make it more modular, you might use a fragment to define the author field once, and then reference it multiple times throughout the query. Here's what that might look like
query{
feed{
id
author{
...authorFields
}
content
comments{
author{
...authorFields
}
text
}
likes{
author{
...authorFields
}
}
}
}
fragmentauthorFieldsonUser{
name
profilePictureUrl
}
In this updated query, we've defined a fragment called authorFields that includes the name and profilePictureUrl fields for a user. We then reference this fragment multiple times throughout the query, both in the author field at the top level of the query and in the author fields nested under comments and likes.
Using fragments in this way allows us to define common pieces of a query once and reuse them throughout the query. This can make the query more modular, easier to read, and easier to maintain. Additionally, if we ever need to update the fields we're retrieving for a user, we can simply update the author fields fragment, rather than having to update every instance of the author field throughout the query.
Using Aliases
At times it is possible that you might be querying the same field twice in a query with different conditions. For instance, you want to get addresses for a user and you also want to bifurcate the primary and secondary address in the query itself, so in this use case you will write a query as shown below
querygetUserAddressDetails($userId:ID!){
user(id:$userId){
address(type:"primary"){
...addressFields
}
address(type:"secondary"){
...addressFields
}
}
}
However, this query would not work as there are two fields with the same name - address, the server would simply give out a validation error for your query. In such cases you need to use aliases in your query this is how the correct query would look like
# Query
querygetUserAddressDetails($userId:ID!){
user(id:$userId){
primaryAddress:address(type:"primary"){
...addressFields
}
secondaryAddress:address(type:"secondary"){
...addressFields
}
}
}
# Response
{
"data":{
"user":{
"name":"John Doe",
"primaryAddress":{
"street":"123 Main St",
"city":"Berlin"
},
"secondaryAddress":{
"street":"456 Second Ave",
"city":"Mumbai"
}
}
}
}
Conclusion
In this article, we explored how to GraphQL queries and how powerful they are for clients as they support declarative data fetching. We saw the anatomy of a GraphQL query, checked out basic queries, and explored further depth with nested queries and filtering capabilities. In addition to this, we explored best practices and available tools like the GraphQL playground, fragments, aliases, named queries, and variables, that can help developers optimize their GraphQL queries and build more efficient applications.