Blog
Can you compare GraphQL and tRPC?
November 27, 2022 - Roy Derks
There have been many discussions on Twitter around "GraphQL versus tRPC" for building a modern backend for your application. GraphQL has become popular in recent years as the defacto successor to REST, while tRPC solves the problem of end-to-end safety in fullstack applications. It's like comparing apples to oranges.
TLDR; GraphQL is a query language, and tRPC is a library.
As a developer working with GraphQL in the past years, this triggered me to compare the two and see what they are both excellent at (and what they are not).
Click the image below to watch the YouTube video version of this blog post:
But first; You might have been using GraphQL wrong
GraphQL is a query language for your API, and it's not a one-to-one replacement for REST. It's a way to query your API in a way that is more flexible than REST, giving you control over the response of the requests. In many of the Twitter conversations, I found that people were comparing GraphQL to REST, and that's different from what GraphQL is. Also, the GraphQL type system is not meant to be used for end-to-end type safety, at least not in a first way. But instead, as a way to document your API and ensure the runtime types of your API are correct.
Can we compare GraphQL to tRPC?
GraphQL is a query language for your API, while tRPC is a set of libraries for building end-to-end typesafe APIs. As mentioned earlier, this is like comparing apples to oranges. But let's break down both of them and learn about their characteristics.
GraphQL is a query language
GraphQL APIs typically use HTTP as a transport layer, and the GraphQL query is sent as a POST request to the API. The API then processes the query and returns the result as a JSON response. This is the same way that REST APIs work, but GraphQL is a query language, not a protocol. This means that you can use GraphQL over any transport layer and any protocol you want. This is also why you can use GraphQL in your frontend application because it's just a query language.
GraphQL itself is nothing more than a query language, and it's up to the GraphQL implementation libraries and frameworks to implement this query language according to its specification. This means that there are many different ways to implement GraphQL, and there are many different ways to use GraphQL. This is also why there are many different ways to use GraphQL in your front end application.
tRPC is a library
tRPC is a set of libraries that uses TypeScript to ensure type safety throughout the entire application. Its primary purpose is to make it easy to build end-to-end typesafe applications in a single codebase. The basis is a tRPC server in which you define the endpoints (or routes), the type definition for these endpoints, and handle any connection to a data source - like a database.
You can consume a tRPC API in your frontend application, using the tRPC client library. You're not directly sending an HTTP request to get your data, but let the tRPC client handle this for you, almost like an ORM for APIs. This client can make strongly typed API calls without relying on code generation. You can import TypeScript types from the server directly into your frontend application without generating any code.
What differentiates GraphQL and tRPC?
This is a very subjective question, but I think it's important to know what differentiates GraphQL and tRPC. This way, you can decide for yourself what you want to use in your application.
GraphQL is great for querying multiple data sources
GraphQL excels in combining multiple data sources into a single query. GraphQL is often used for data modeling and architecture, and it's great for this. For example, if you want to query data from one service (like a Headless CMS) and data from another (let's say a database), you can do this in a single query with GraphQL. You can even combine this data on field or type level. It is one of the major reasons companies like Facebook and GitHub are using GraphQL.
Whereas tRPC is not really meant for this. It's meant for building end-to-end typesafe APIs, and it's not really meant for combining multiple data sources. You can do this, but it's not the purpose of tRPC.
tRPC is great for end-to-end type safety
tRPC is great for end-to-end type safety, and it allows you to use the same types in your frontend application as you use in your backend application. GraphQL has no built-in way to share type definitions between a frontend and backend, but you can use the GraphQL schema to generate TypeScript type definitions. But this is different from end-to-end type safety. Every time you update your GraphQL schema, you have to regenerate the types.
When using tRPC, you're building everything using TypeScript. This means that you can import the types from the server directly into your frontend application. The tRPC client can access the TypeScript types from your tRPC server directly. You don't need external libraries when querying tRPC in your frontend application because it's all built-in the tRPC libraries.
GraphQL allows for decoupled services; tRPC for a single codebase
GraphQL is great for decoupled services as it's programming language and transport layer agnostic. This means that you can use any programming language and any transport layer you want. Services that expose a GraphQL API can be implemented in any programming language, for example TypeScript and Go, and still be able to communicate with each other. For teams and companies that are technologicallyy diverse this is a great way to scale and limit the amount of dependencies between teams.
tRPC is not really meant for this. It's meant for building end-to-end typesafe APIs in a single codebase, in TypeScript! It brings your frontend and backend closely together, for example in a monorepo. You can use the same types in your frontend and backend application, which allows you to rapidly iterate on your application. What's not to love if you're building a fullstack TypeScript project?
tRPC is easier to use than GraphQL
"tRPC is easier to use than GraphQL" is a recurring statement people make when comparing GraphQL and tRPC. But as tRPC is a library and GraphQL is a query language, it's impossible to compare. For GraphQL, it's up to the developer to build a GraphQL using one of the many available implementations, while tRPC is a set of libraries you can use out of the box. This makes it not a fair comparison, but let's break it down anyway.
For example, you could build a GraphQL API using a schema-first GraphQL server library. You have to define a GraphQL schema, write the resolvers to collect the data from a data source, and then generate the types from the schema. Going this path is a lot of work and comes with many choices you need to make as a developer.
But you can also build a GraphQL API using a code-first GraphQL server library. This means you can write the resolvers and then generate the schema from the resolvers. Code-first libraries are much closer to tRPC in terms of Developer Experience but still more challenging than using a GraphQL-as-a-service like StepZen.
Then you also have a wide choice of various GraphQL client libraries. You can use GraphQL client library like Apollo Client or urql that helps you with caching and state management, or use a library that only handles the HTTP requests. There are many choices, which could be unclear when you're new to GraphQL.
Conclusion
In this blog post, I explained the differences between GraphQL and tRPC. I hope this blog post helped you understand the differences between the two and that you can now make a better decision on which one to use for your next project. The main questions to ask yourself when choosing between GraphQL and tRPC are:
- Do you want to query multiple data sources in a single query and keep your services decoupled? If so, GraphQL is a perfect choice. If you want end-to-end type safety and don't care about decoupling your frontend and backend, tRPC is a better fit.
- Are you planning to work with multiple programming languages? Go for GraphQL, as it's programming language agnostic. If you want to use TypeScript throughout your entire application, tRPC might be a better fit.
There are many other things to consider when choosing between GraphQL and tRPC, but these are the main ones in my opinion. I'd love to hear your thoughts on this, so please let me know via X or Bluesky.