There has been a lot of buzz in the GraphQL community around code-first or SDL-first schema development as of late. The purpose of this blog is to shed some light on the current state of the ecosystem and help teams make a decision on which approach would be best for them.
To understand where we are today, it helps to take a look at how we got here.
Code-first: the original way to build a graphql schema
Facebook originally released graphql-js as a reference implementation for the GraphQL specification. The schema is defined as a plain javascript object:
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
args: {
name: { type: GraphQLString },
},
resolve: (_, args) => `Hello ${args.name || 'World!'}`,
},
},
}),
})
Many people in the community felt that writing a schema in this way was very verbose, and it was challenging to have a mental model of the schema while implementing it.
Enter SDL
The Apollo team released graphql-tools, which popularized the Schema Definition Language (SDL). Here is what the same schema from above looks like defined in SDL:
type Query {
hello(name: String): String
}
It was much easier to understand the structure of the schema with SDL and, ultimately made the schema design process much more intuitive. The Apollo team also came up with schema directives to accompany the SDL.
One significant tradeoff for the SDL-first approach is that resolvers need to be implemented separately from the schema definition. Consequently, various new challenges came about. Directives are also not a part of the core GraphQL specification.
The pendulum swings back to code-first
Tools like TypeGraphQL and GraphQL Nexus were released to reduce the verbosity of graphql-js and provide a much simpler way to develop schemas than the SDL approach. These tools are built with graphql-js at their core, so they do not have support for schema directives — here are issues requesting support for them in TypeGraphQL and GraphQL Nexus.
Federated schemas…
The Apollo team recently introduced the Schema Federation specification for building distributed graphs. It significantly improved on a lot of the pitfalls of schema stitching and enabled a truly distributed architecture. The specification utilizes schema directives, so individual schemas can provide hints to the gateway server on how they are related to one another.
The major problem here is that the code-first libraries are unable to support schema federation because they do not support directives. There have been issues submitted for TypeGraphQL and GraphQL Nexus requesting support, but there hasn’t been much progress as of yet.
So, code-first or SDL-first?
Innovation will come with its fair share of disruption, and the GraphQL ecosystem is no exception. There are risks and tradeoffs when selecting any toolset, and teams must carefully look at their circumstances to understand which approach suits their needs.
Here are a couple of suggestions:
- If your team needs schema federation or directives, then it is best to go with the SDL-first approach until the ecosystem catches up.
- If your team doesn’t need schema federation or directives, then it is best to go with code-first — especially if you have a large schema. It will help your team keep your codebases organized and moving quickly.
What if you made the wrong choice?
The silver lining here is that you are not necessarily stuck with the decision your team makes now. Because both approaches are fundamentally the same (you define a schema and resolvers), it is not difficult to reuse most if not all of the business logic when switching from one approach to the other. One thing to note is that it is currently much easier to start with code-first and then switch to SDL-first because of the lack of schema directive support in code-first.
I hope this proved helpful for teams struggling to stay on top of everything that is happening in the GraphQL ecosystem. You can always reach out to us at Novvum for help!
Top comments (1)
You may try
graphql-compose
to unlock directives forTypeGraphQL
andGraphQL Nexus
.So with such approach you may pick only what you want and expose via apollo federation.