GraphQL vs trpc: Key Differences and When to Use Each
GraphQL is a query language for APIs that lets clients request exactly the data they need, while trpc is a TypeScript-first RPC framework that enables type-safe API calls without schemas. GraphQL requires defining schemas and resolvers, whereas trpc uses TypeScript types directly for end-to-end type safety and simpler setup.Quick Comparison
Here is a quick side-by-side comparison of GraphQL and trpc based on key factors.
| Factor | GraphQL | trpc |
|---|---|---|
| Type System | Schema-based with SDL (Schema Definition Language) | TypeScript types directly used for API contracts |
| Setup Complexity | Requires schema and resolver definitions | Minimal setup, no separate schema files |
| Type Safety | Type safety via code generation or manual typing | End-to-end type safety with TypeScript inference |
| Data Fetching | Flexible queries with nested fields | RPC style calls with function-like endpoints |
| Tooling | Rich ecosystem with clients like Apollo | Lightweight, integrates tightly with TypeScript |
| Use Case | Complex APIs with flexible queries | Type-safe APIs in TypeScript projects with simple RPC calls |
Key Differences
GraphQL uses a schema language to define the shape of data and requires resolvers to fetch data for each field. This allows clients to request exactly what they need in a single query, making it very flexible for complex data structures. However, it involves more setup and learning to define schemas and manage resolvers.
trpc, on the other hand, leverages TypeScript's type system directly, eliminating the need for separate schema files. It provides automatic type inference from server to client, ensuring type safety without code generation. trpc uses a remote procedure call (RPC) style, where API endpoints are called like functions, which is simpler but less flexible than GraphQL's query language.
In summary, GraphQL excels in flexibility and client-driven queries, suitable for complex APIs, while trpc offers a streamlined developer experience with strong TypeScript integration, ideal for TypeScript-heavy projects needing quick and type-safe API calls.
Code Comparison
Here is how you define a simple API to get a user by ID using GraphQL:
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type User { id: ID! name: String! } type Query { user(id: ID!): User } `; const users = [{ id: '1', name: 'Alice' }, { id: '2', name: 'Bob' }]; const resolvers = { Query: { user: (_, { id }) => users.find(user => user.id === id), }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
trpc Equivalent
Here is the equivalent API using trpc with TypeScript:
import { initTRPC } from '@trpc/server'; const t = initTRPC.create(); const users = [{ id: '1', name: 'Alice' }, { id: '2', name: 'Bob' }]; const appRouter = t.router({ user: t.procedure.input((id: string) => id).query(({ input }) => { return users.find(user => user.id === input) || null; }), }); export type AppRouter = typeof appRouter;
When to Use Which
Choose GraphQL when you need flexible, client-driven queries that can fetch complex nested data in a single request, especially if your API serves diverse clients with varying data needs.
Choose trpc when you work in a TypeScript environment and want a simple, type-safe API without the overhead of schema definitions, ideal for rapid development and tightly coupled front-end and back-end projects.