GraphQL for Beginners: Schema-first vs Code-first
Let's take a look at the 2 ways we can build a GraphQL API. How they are different and their pros and cons.
GraphQL has become a revolutionary scheme in the API world. As a solution to data fetching more efficiently, the first question you will need to ask yourself when building a GraphQL API is: schema-first or code-first?
In this article, let's take a look at the 2 different approaches to implementing a GraphQL API and discuss when is best to use them.
This post is inspired by Dhruva Srinivas, who asked a question around this topic. Shoutout to him!
Note: If you need a refresher on GraphQL APIs, feel free to read my Introduction to GraphQL article.
What is Schema-first?
There has been a lot of debate about which type of implementation is better. When GraphQL was first launched in 2016, only the schema-first approach exists. Therefore, developers who adopted GraphQL early might be more familiar with this approach.
The schema-first approach focuses on the designing and defining the GraphQL Schema first, then adding the resolver functions. From my GraphQL for Beginners article, recall that a schema is the blueprint of a GraphQL API.
It looks something like this:
type User {
_id: ID!
username: String
name: String
tagline: String
dateJoined: String
numFollowing: Int
numFollowers: Int
}
It defines the data types and relationships of these data that makes up the API. To define a schema, you need to know the Schema Definition Language (SDL). Hence, the schema-first is sometimes called the SDL-first approach too.
Here's a brief look at how SDL defines the schema of a GraphQL API.
In a development work environment, the SDL way is readable for both technical and nontechnical team members. Once the API design is complete and the schema is finalized, both front and back-end teams can work on the API simultaneously.
However, the downside to a schema-first approach is that the resolver functions must match the schema exactly. Since developers need to write the schema and resolvers separately, this becomes a challenge for very large APIs with thousands of lines.
To this day, this approach does work, but it requires a lot of workarounds and tools to help keep the code clean and inconsistencies to a minimum.
What is Code-first?
The code-first approach was introduced to tackle some aforementioned common issues with the schema-first approach.
This approach focuses on writing resolver functions and defining types via code, and a schema would be generated from them. You can imagine how this would speed up development time and eliminate the need to match resolvers to the schema like in the previous approach.
A typical example of a code-first approach using Nexus:
const Account = objectType({
name: 'Account',
isTypeOf(source) {
return 'email' in source
},
definition(t) {
t.implements(Node)
t.string('username')
t.string('email')
},
})
The biggest advantage to implementing via the code-first approach is that it is much more manageable to maintain. To make changes to the API, simply change the functions, there is no need to care whether the schema definition will fit or not since it is dynamically generated.
The drawback of the code-first approach is that it may lead to being too tunnel-visioned on implementation rather than what the API actually needs. On the other hand, since a schema-first approach focuses on the design of the API first, it does generally lead to a well-designed API.
Conclusion
There are always pros and cons to everything. Ultimately, my personal opinion believes in the code-first approach, as it is more scalable and maintainable in the long run.
At the same time, I do believe that learning the schema-first approach is essential and more intuitive for GraphQL beginners. Therefore, if you are interested to learn about to build a GraphQL API via a schema-first approach, do check out my Introduction to GraphQL for Beginners series.
Below is a table I found from this website, which is useful if you would like to learn what tools you can use to build your own GraphQL API using the language and approach of your choice.
Language | Schema-first implementation | Code-first implementation |
JavaScript/TypeScript | Apollo server | Nexus |
PHP (Laravel) | Lighthouse | laravel-graphql |
PHP (WP) | x | WPGraphQL |
Python | Ariadne | Graphene |
.NET | GraphQL for .NET | GraphQL for .NET |
Rust | x | Juniper |
Thanks for reading! I hope it has been a helpful read. Please like and share if it is. Cheers!