What is a GraphQL schema and how does it work in Hygraph?
A GraphQL schema is a collection of types that defines the structure, relationships, and operations available for your data. In Hygraph, you define your schema in the dashboard, which then scaffolds instant GraphQL APIs for querying and mutating data. The schema validates requests and ensures only defined operations are possible. Note: Hygraph's schema system is flexible but requires understanding of GraphQL concepts for advanced use cases. Source
What are GraphQL types and how are they used in Hygraph?
GraphQL types define entities and their fields in your schema. In Hygraph, you use types such as Scalar, Object, Input, Enumeration, Union, and Interface to model your data. For example, a User type might have fields like name and email. Types ensure data consistency and enable structured queries and mutations. Note: Complex relationships and advanced type features may require additional configuration. Source
What are the main GraphQL type categories supported?
The main GraphQL type categories are Scalar, Object, Input, Enumeration, Union, and Interface types. Scalars represent primitive values (e.g., String, Int), Objects group fields, Inputs define argument shapes, Enums restrict values to a set, Unions allow multiple possible types, and Interfaces define shared fields. Hygraph supports all these categories for schema modeling. Note: Some advanced GraphQL features may require manual schema adjustments. Source
How does Hygraph handle queries and mutations in GraphQL schemas?
Hygraph's GraphQL schemas define Query types for reading data and Mutation types for writing data. For example, a Query might fetch all users, while a Mutation could add a new user. These operations are exposed via the GraphQL API, allowing clients to interact with your data as defined by the schema. Note: Subscription support and advanced mutation logic may require custom implementation. Source
What are input types in GraphQL and how are they used in Hygraph?
Input types in GraphQL define the structure of arguments for queries and mutations. In Hygraph, input types are used to pass complex objects as arguments, such as when creating or updating records. Input types are similar to object types but are only used for arguments, not for returned data. Note: Input and output types cannot be mixed; each serves a distinct purpose. Source
How does Hygraph support enumeration, union, and interface types in GraphQL?
Hygraph supports enumeration types for restricting fields to a set of values, union types for fields that can return multiple object types, and interface types for defining shared fields across types. These features enable flexible and expressive schema design. Note: Union types can only include object types, and interface implementation requires all interface fields to be present in implementing types. Source
What are the modifiers in GraphQL types and how do they affect schema design?
GraphQL provides modifiers such as Non-Null (!) and List ([]) to control field requirements and array structures. For example, String! means the field cannot be null, while [String] means an array of strings. These modifiers help enforce data integrity in Hygraph schemas. Note: Incorrect use of modifiers can lead to execution errors if data does not match the schema. Source
Features & Capabilities
What features does Hygraph offer for GraphQL schema management?
Hygraph provides instant GraphQL APIs based on your defined schema, supports schema evolution, and enables integration of multiple data sources through content federation. It offers a user-friendly interface for schema design, advanced caching for performance, and extensive API documentation. Note: Some advanced schema customizations may require developer expertise. Documentation
Does Hygraph provide an API for working with schemas and content?
Yes, Hygraph offers multiple APIs: the GraphQL Content API for querying and manipulating content, the Management API for handling project structure, and the Asset Upload API for managing files. These APIs are optimized for performance and security. Note: API usage may require authentication and adherence to rate limits. API Reference
What integrations are available for Hygraph?
Hygraph integrates with platforms such as Aprimo, AWS S3, Bynder, Cloudinary, Imgix, Mux, Scaleflex Filerobot, Netlify, Vercel, Akeneo, Adminix, Plasmic, BigCommerce, and EasyTranslate. These integrations enhance asset management, deployment, commerce, and localization workflows. Note: Integration setup may require additional configuration. Marketplace
Performance & Security
How does Hygraph ensure high performance for GraphQL APIs?
Hygraph optimizes for low latency and high read-throughput with high-performance endpoints and a read-only cache endpoint that delivers 3-5x latency improvement. Performance is actively measured and documented, with practical advice for developers available in the GraphQL Report 2024. Note: Performance may vary based on query complexity and infrastructure. Performance Blog
What security and compliance certifications does Hygraph have?
Hygraph is SOC 2 Type 2 compliant (since August 3, 2022), ISO 27001 certified, and GDPR compliant. It offers granular permissions, SSO integrations, audit logs, encryption in transit and at rest, regular backups, and secure APIs. Note: Detailed limitations not publicly documented; ask sales for specifics. Security Features
Implementation & Use Cases
How long does it take to implement Hygraph for GraphQL projects?
Implementation time varies by project complexity. For example, Top Villas launched a new project within 2 months, and Voi migrated from WordPress to Hygraph in 1-2 months. Starter projects and structured onboarding are available to accelerate setup. Note: Large-scale migrations may require additional planning. Case Study
Who can benefit from using Hygraph for GraphQL schema management?
Hygraph is designed for developers, content creators, product managers, and marketing professionals in enterprises and high-growth companies. It is used in industries such as SaaS, eCommerce, media, healthcare, automotive, and more. Note: Teams with highly specialized CMS needs may require custom solutions. Case Studies
Customer Success & Recognition
What business impact have customers seen using Hygraph?
Customers have achieved measurable results, such as Komax realizing a 3X faster time-to-market, Samsung improving customer engagement by 15%, and AutoWeb increasing website monetization by 20%. These outcomes are documented in public case studies. Note: Results may vary based on implementation and use case. Case Studies
What feedback have customers given about Hygraph's ease of use?
Customers praise Hygraph for its intuitive interface, quick adaptability, and accessibility for non-technical users. For example, Sigurður G. (CTO) noted the UI is intuitive, and Anastasija S. (Product Content Coordinator) highlighted instant front-end updates. Note: Some advanced features may require technical expertise. Customer Reviews
Documentation & Support
What technical documentation is available for working with GraphQL schemas in Hygraph?
Hygraph provides extensive documentation, including API references, schema guides, integration tutorials, and getting started resources. Dedicated guides cover schema components, references, and AI features. Note: Documentation for legacy (Classic) projects is also available. Documentation
Let's take a look into what GraphQL Schemas and Types are.
We learned about “What is GraphQL” in the previous article of this series. Hygraph is a data platform that provides you with Instant GraphQL APIs; all you have to do is define your schema in the Hygraph dashboard and you’re good to go to use the instant GraphQL APIs. However, many other things happen under the hood, which eventually scaffolds those APIs for you like defining the GraphQL schema, creating resolvers for your queries, mutations, and subscriptions, etc.
In this article, we will be covering the basics of GraphQL Schemas and Types.
What is a GraphQL Schema?
A GraphQL server acts as a bridge between the client and the underlying data sources, providing a flexible and efficient way to query and manipulate data in a structured manner. When a client sends a GraphQL request to a server, the server receives the request and uses the GraphQL Schema to validate and execute the request. The server then sends back a response to the client which contains the requested data or errors, depending on the nature of the request. In order to serve these requests, and expose what operations are available to query or mutate the data, a GraphQL Server relies heavily on its Schema.
A GraphQL Type defines your entities with their fields and definitions.
For example:
typeUser{
name:String
email:String
}
This is a User Type, which defines two fields name and email, both are of the type String. Just like programming concepts both String and User are Types. String is a scalar type, whereas User is an object type created by us.
A GraphQL Schema is composed of various GraphQL types that define all your data entities, what are the relationships between these entities, and what operations are available to query and mutate your data. In order to support this GraphQL defines a human-readable Schema Definition Language (SDL).
For example:
typeUser{
name:String
email:String
posts:[Post]
}
typePost{
title:String
description:String
user:User
}
The above GraphQL schema gives us an exact picture of how User and Post entities are connected. We can clearly see a One-To-Many relationship between User-Post (one user can have many posts ) from the schema definition language itself.
Try Hygraph, the GraphQL native headless CMS
Build limitless solutions rapidly with our GraphQL-native API-first approach
As discussed above, GraphQL defines various types that we can utilize to build our schema.
Here are the different available types.
Scalar Type
Object Type
Input Types
Enumeration Type
Union and Interface Type
Lists and Non-Null
Scalar Type
Scalar types represent primitive data types for fields like Strings, Integers, etc. These types cannot have further nested sub-fields. Scalar types are automatically serialized and deserialized by GraphQL according to their respective types in the programming language.
Here are the Scalar types supported by GraphQL:
Int: A signed 32‐bit integer.
Float: A signed double-precision floating-point value.
String: A UTF‐8 character sequence.
Boolean: true or false.
ID: The ID scalar type represents a unique identifier and is serialized as a string.
Object Type
The majority of types that we define in a GraphQL schema are Object Types. Object types contain various fields and each field has its own type.
For example:
typeUser{
name:String
email:String
}
In this example:
User is a GraphQL Object Type, meaning it's a type with some fields. Object types will make up most of your schema.
name and email are fields on the User type. This also means that one cannot query anything beyond - - name and email under a User type.
name and email fields are of the Scalar Type: String
Query & Mutation Type
GraphQL provides a Query type that can be used whenever you want to query data from your data source.
For example:
typeQuery{
getAllUsers:[User]
}
This GraphQL schema defines a Query type that has a single field named getAllUsers. The getAllUsers query outputs an array of User objects. This means that when a client sends a query of getAllUsers to the server, they will receive a list of all the users in the system. With a REST-based API, this would look something like GET /api/users.
The Query type defines all entry points for read operations, similarly, there is a Mutation type that defines entry points for write operations on your GraphQLl server.
For example:
typeMutation{
addUser(name:String,email:String):User
}
This GraphQL schema defines a Mutation type that has a single field named addUser. The addUser field takes two arguments: name and email, both of which are of the String type. When a client calls this mutation field with valid name and email values, a new User object is created with the provided data and added to the system. The addUser mutation returns the newly created User object.
We have only explored how queries and mutations are defined in the GraphQL schema, we shall be exploring more details of using queries and mutations in applications in the upcoming articles.
Input Type
Input types are types that will define the data type of arguments in your queries and mutations. Input types are the same as Object types, the only difference is that to define an input type we use the keyword input instead of type.
Input types are very useful when you want to pass objects as arguments to your query or mutation instead of scalars. For instance in the addUser mutation above if you want to pass a user object as an argument, then you can define your input type and mutation like this:
inputUserInput{
name:String
email:String
}
typeMutation{
addUser(newUser:UserInput):User
}
One important thing to note is you cannot mix your input and output types. So if you have a query that outputs a user, you cannot reuse the above input type over there.
The example below is invalid:
typeQuery{
getUserById(id:ID):UserInput
}
The example below is the correct way:
inputUserInput{
name:String
email:String
}
typeUser{
name:String
email:String
}
typeMutation{
addUser(newUser:UserInput):User
}
typeQuery{
getUserById(id:ID):User
}
Enumeration Type
An enum is similar to a scalar type, but all its valid values are defined in the schema itself. Enums are most useful in situations where the user must pick from a prescribed list of options.
For example:
enumGENDER{
MALE
FEMALE
OTHER
}
Lists and Non-Null
You will be using the object, scalar, input, and enum types to define your schema. GraphQL also provides us with modifiers that can help us to do quick validations. These modifiers can be used in type definitions inside the schema and also in the arguments of queries and mutations. The modifiers are listed below
Exclamation Mark ! - Non-Null
Square Brackets [ ] - List
For example:
typeUser{
email:String!
city:String
hobbies:[String]
}
Here, we are saying that a User type will have fields email, city, and posts; an email should always exist for a user (as there is an exclamation mark in its declaration), but the city field is optional so it may or may not exist. This means that our server always expects to return a non-null value for email, If somehow, our server ends up getting a null value for the email field, it will trigger a GraphQL execution error, and let the client know that something has gone wrong.
If you take a look at the hobbies field its output is String wrapped with square brackets - [String], meaning that this field will output an array of Strings.
You can also combine the ! and [] modifiers as per your needs, here are some tricky examples:
typeUser{
...
hobbies:[String!]
# This means that the hobbies field can be null but it cannot have any null values
# hobbies: null // valid
# hobbies: [] // valid
# hobbies: ['cricket', 'movies'] // valid
# hobbies: ['cricket', null, 'movies'] // error
}
typeUser{
...
hobbies:[String]!
# This means that the hobbies field cannot be null but it can have null values
# hobbies: null // error
# hobbies: [] // valid
# hobbies: ['cricket', 'movies'] // valid
# hobbies: ['cricket', null, 'movies'] // valid
}
typeUser{
...
hobbies:[String!]!
# This means that the hobbies field cannot be null and cannot have any null values
# hobbies: null // error
# hobbies: [] // valid
# hobbies: ['cricket', 'movies'] // valid
# hobbies: ['cricket', null, 'movies'] // error
}
The __typename field
Each object type in your GraphQL schema has a field named __typename by default. We do not need to define it. This field returns the object type's name as a String (e.g., User or Post).
You can get the __typename field in a query or mutation response
For example:
# QUERY
querygetUserById{
getUserById(id:"1"){
__typename
name
email
}
}
# RESPONSE
{
"data":{
"getUserById":{
"__typename":"User",
"name":"John Doe",
"email":"johndoe@hygraph.com"
}
}
}
Union and Interface Type
Just like the programming concept we have an Interface type in GraphQL types too. An Interface defines a set of fields that can be implemented by several other Object types; when an object type implements an interface it must include all the fields of the interface and can also include additional fields.
For example
interfaceProduct{
id:ID!
name:String!
}
typeBookimplementsProduct{
id:ID!
name:String!
author:String!
isbn:String!
}
typeClothingimplementsProduct{
id:ID!
name:String!
size:String!
color:String!
}
Here we have an interface Product, which is implemented by types Book and Clothing. Type Book and Clothing need to have the fields id and name since they are defined in the interface Product.
Union types are used when you want to define a field that can output into more than one type.
For example
unionSearchResult=Movie|Music
The union type SearchResult here denotes that it can either be an Object type of Movie or Music. One important thing to note about union type is that we can only use Object types while defining a union.
The example below is invalid:
unionPostalCode=String|Int
Conclusion
In summary, understanding GraphQL schemas and types is crucial for building GraphQL APIs. A GraphQL schema is a collection of types that define the layout and shape of data. The GraphQL type system is composed of scalar types, object types, input types, enumeration types, union types, interface types, and type modifiers. We can use the GraphQL type system to define the GraphQL schema as per our use case and then proceed on building powerful APIs that can acquire data from various sources.
Let's take a look into what GraphQL Schemas and Types are.
We learned about “What is GraphQL” in the previous article of this series. Hygraph is a data platform that provides you with Instant GraphQL APIs; all you have to do is define your schema in the Hygraph dashboard and you’re good to go to use the instant GraphQL APIs. However, many other things happen under the hood, which eventually scaffolds those APIs for you like defining the GraphQL schema, creating resolvers for your queries, mutations, and subscriptions, etc.
In this article, we will be covering the basics of GraphQL Schemas and Types.
What is a GraphQL Schema?
A GraphQL server acts as a bridge between the client and the underlying data sources, providing a flexible and efficient way to query and manipulate data in a structured manner. When a client sends a GraphQL request to a server, the server receives the request and uses the GraphQL Schema to validate and execute the request. The server then sends back a response to the client which contains the requested data or errors, depending on the nature of the request. In order to serve these requests, and expose what operations are available to query or mutate the data, a GraphQL Server relies heavily on its Schema.
A GraphQL Type defines your entities with their fields and definitions.
For example:
typeUser{
name:String
email:String
}
This is a User Type, which defines two fields name and email, both are of the type String. Just like programming concepts both String and User are Types. String is a scalar type, whereas User is an object type created by us.
A GraphQL Schema is composed of various GraphQL types that define all your data entities, what are the relationships between these entities, and what operations are available to query and mutate your data. In order to support this GraphQL defines a human-readable Schema Definition Language (SDL).
For example:
typeUser{
name:String
email:String
posts:[Post]
}
typePost{
title:String
description:String
user:User
}
The above GraphQL schema gives us an exact picture of how User and Post entities are connected. We can clearly see a One-To-Many relationship between User-Post (one user can have many posts ) from the schema definition language itself.
Try Hygraph, the GraphQL native headless CMS
Build limitless solutions rapidly with our GraphQL-native API-first approach
As discussed above, GraphQL defines various types that we can utilize to build our schema.
Here are the different available types.
Scalar Type
Object Type
Input Types
Enumeration Type
Union and Interface Type
Lists and Non-Null
Scalar Type
Scalar types represent primitive data types for fields like Strings, Integers, etc. These types cannot have further nested sub-fields. Scalar types are automatically serialized and deserialized by GraphQL according to their respective types in the programming language.
Here are the Scalar types supported by GraphQL:
Int: A signed 32‐bit integer.
Float: A signed double-precision floating-point value.
String: A UTF‐8 character sequence.
Boolean: true or false.
ID: The ID scalar type represents a unique identifier and is serialized as a string.
Object Type
The majority of types that we define in a GraphQL schema are Object Types. Object types contain various fields and each field has its own type.
For example:
typeUser{
name:String
email:String
}
In this example:
User is a GraphQL Object Type, meaning it's a type with some fields. Object types will make up most of your schema.
name and email are fields on the User type. This also means that one cannot query anything beyond - - name and email under a User type.
name and email fields are of the Scalar Type: String
Query & Mutation Type
GraphQL provides a Query type that can be used whenever you want to query data from your data source.
For example:
typeQuery{
getAllUsers:[User]
}
This GraphQL schema defines a Query type that has a single field named getAllUsers. The getAllUsers query outputs an array of User objects. This means that when a client sends a query of getAllUsers to the server, they will receive a list of all the users in the system. With a REST-based API, this would look something like GET /api/users.
The Query type defines all entry points for read operations, similarly, there is a Mutation type that defines entry points for write operations on your GraphQLl server.
For example:
typeMutation{
addUser(name:String,email:String):User
}
This GraphQL schema defines a Mutation type that has a single field named addUser. The addUser field takes two arguments: name and email, both of which are of the String type. When a client calls this mutation field with valid name and email values, a new User object is created with the provided data and added to the system. The addUser mutation returns the newly created User object.
We have only explored how queries and mutations are defined in the GraphQL schema, we shall be exploring more details of using queries and mutations in applications in the upcoming articles.
Input Type
Input types are types that will define the data type of arguments in your queries and mutations. Input types are the same as Object types, the only difference is that to define an input type we use the keyword input instead of type.
Input types are very useful when you want to pass objects as arguments to your query or mutation instead of scalars. For instance in the addUser mutation above if you want to pass a user object as an argument, then you can define your input type and mutation like this:
inputUserInput{
name:String
email:String
}
typeMutation{
addUser(newUser:UserInput):User
}
One important thing to note is you cannot mix your input and output types. So if you have a query that outputs a user, you cannot reuse the above input type over there.
The example below is invalid:
typeQuery{
getUserById(id:ID):UserInput
}
The example below is the correct way:
inputUserInput{
name:String
email:String
}
typeUser{
name:String
email:String
}
typeMutation{
addUser(newUser:UserInput):User
}
typeQuery{
getUserById(id:ID):User
}
Enumeration Type
An enum is similar to a scalar type, but all its valid values are defined in the schema itself. Enums are most useful in situations where the user must pick from a prescribed list of options.
For example:
enumGENDER{
MALE
FEMALE
OTHER
}
Lists and Non-Null
You will be using the object, scalar, input, and enum types to define your schema. GraphQL also provides us with modifiers that can help us to do quick validations. These modifiers can be used in type definitions inside the schema and also in the arguments of queries and mutations. The modifiers are listed below
Exclamation Mark ! - Non-Null
Square Brackets [ ] - List
For example:
typeUser{
email:String!
city:String
hobbies:[String]
}
Here, we are saying that a User type will have fields email, city, and posts; an email should always exist for a user (as there is an exclamation mark in its declaration), but the city field is optional so it may or may not exist. This means that our server always expects to return a non-null value for email, If somehow, our server ends up getting a null value for the email field, it will trigger a GraphQL execution error, and let the client know that something has gone wrong.
If you take a look at the hobbies field its output is String wrapped with square brackets - [String], meaning that this field will output an array of Strings.
You can also combine the ! and [] modifiers as per your needs, here are some tricky examples:
typeUser{
...
hobbies:[String!]
# This means that the hobbies field can be null but it cannot have any null values
# hobbies: null // valid
# hobbies: [] // valid
# hobbies: ['cricket', 'movies'] // valid
# hobbies: ['cricket', null, 'movies'] // error
}
typeUser{
...
hobbies:[String]!
# This means that the hobbies field cannot be null but it can have null values
# hobbies: null // error
# hobbies: [] // valid
# hobbies: ['cricket', 'movies'] // valid
# hobbies: ['cricket', null, 'movies'] // valid
}
typeUser{
...
hobbies:[String!]!
# This means that the hobbies field cannot be null and cannot have any null values
# hobbies: null // error
# hobbies: [] // valid
# hobbies: ['cricket', 'movies'] // valid
# hobbies: ['cricket', null, 'movies'] // error
}
The __typename field
Each object type in your GraphQL schema has a field named __typename by default. We do not need to define it. This field returns the object type's name as a String (e.g., User or Post).
You can get the __typename field in a query or mutation response
For example:
# QUERY
querygetUserById{
getUserById(id:"1"){
__typename
name
email
}
}
# RESPONSE
{
"data":{
"getUserById":{
"__typename":"User",
"name":"John Doe",
"email":"johndoe@hygraph.com"
}
}
}
Union and Interface Type
Just like the programming concept we have an Interface type in GraphQL types too. An Interface defines a set of fields that can be implemented by several other Object types; when an object type implements an interface it must include all the fields of the interface and can also include additional fields.
For example
interfaceProduct{
id:ID!
name:String!
}
typeBookimplementsProduct{
id:ID!
name:String!
author:String!
isbn:String!
}
typeClothingimplementsProduct{
id:ID!
name:String!
size:String!
color:String!
}
Here we have an interface Product, which is implemented by types Book and Clothing. Type Book and Clothing need to have the fields id and name since they are defined in the interface Product.
Union types are used when you want to define a field that can output into more than one type.
For example
unionSearchResult=Movie|Music
The union type SearchResult here denotes that it can either be an Object type of Movie or Music. One important thing to note about union type is that we can only use Object types while defining a union.
The example below is invalid:
unionPostalCode=String|Int
Conclusion
In summary, understanding GraphQL schemas and types is crucial for building GraphQL APIs. A GraphQL schema is a collection of types that define the layout and shape of data. The GraphQL type system is composed of scalar types, object types, input types, enumeration types, union types, interface types, and type modifiers. We can use the GraphQL type system to define the GraphQL schema as per our use case and then proceed on building powerful APIs that can acquire data from various sources.