tRPC vs REST
tRPC (typsicheres RPC, TypeScript-Full-Stack) vs REST API (sprachunabhängig, Standard) – Vergleich von API-Designs. Typsicherheit, Ökosystem, Skalierbarkeit.
Null Codegen, durchgängige TypeScript-Typsicherheit
Schema-first, universelle Abfragesprache für mehrere Clients
Entscheide je nach Situation – 'Typsicherheit' allein ist kein Argument für GraphQL. Wenn du ein einziges TypeScript-Monorepo mit einem einzigen Web-Client nutzt, verursacht tRPC fast immer weniger Aufwand – kein Codegen, eine Serveränderung erzeugt sofort einen TS-Fehler im Client. Hast du eine mobile App, eine öffentliche API für externe Entwickler oder benötigst du eine teamübergreifende Föderation, verschafft GraphQLs sprachunabhängiger Schema-Vertrag und das Apollo-Federation-Ökosystem einen strukturellen Vorteil.
| Kategorie | tRPC | GraphQL |
|---|---|---|
| Performance | 7/10 | 6/10 |
| Erlernbarkeit | 8/10 | 5/10 |
| Ökosystem | 6/10 | 9/10 |
| Community | 7/10 | 8/10 |
| Arbeitsmarkt | 5/10 | 8/10 |
| Zukunftssicherheit | 7/10 | 8/10 |
// tRPC — Router-Definition (Server)
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
// db = Prisma/ORM-Client (aus einer separaten Datei importiert)
const t = initTRPC.create();
export const appRouter = t.router({
getUser: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return db.user.findUnique({ where: { id: input.id } });
}),
});
export type AppRouter = typeof appRouter;
// Client — Server-Typ wird automatisch abgeleitet, kein Codegen
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './server';
const client = createTRPCClient<AppRouter>({
links: [httpBatchLink({ url: 'http://localhost:3000/trpc' })],
});
const user = await client.getUser.query({ id: '1' });
// user: { id: string; name: string; ... } — vollständige Typsicherheit zur Kompilierzeit// graphql-js + @apollo/server — Schema, Resolver und Server in einer Datei
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// db = Prisma/ORM-Client (aus einer separaten Datei importiert)
const typeDefs = `#graphql
type Post {
id: ID!
title: String!
}
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: (_parent, { id }, { db }) => db.user.findUnique({ where: { id } }),
},
User: {
posts: (user, _args, { db }) =>
db.post.findMany({ where: { authorId: user.id } }),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
context: async () => ({ db }),
listen: { port: 4000 },
});
console.log(`Server bereit: ${url}`);
// Client-Abfrage — es werden nur die benötigten Felder ausgewählt:
// query { user(id: "1") { name posts { title } } }Entscheide je nach Situation – 'Typsicherheit' allein ist kein Argument für GraphQL. Wenn du ein einziges TypeScript-Monorepo mit einem einzigen Web-Client nutzt, verursacht tRPC fast immer weniger Aufwand – kein Codegen, eine Serveränderung erzeugt sofort einen TS-Fehler im Client. Hast du eine mobile App, eine öffentliche API für externe Entwickler oder benötigst du eine teamübergreifende Föderation, verschafft GraphQLs sprachunabhängiger Schema-Vertrag und das Apollo-Federation-Ökosystem einen strukturellen Vorteil.
Kostenlose Beratung erhaltenArbeitest du in einem einzigen TypeScript-Monorepo mit einem einzigen Web-Client, benötigt tRPC weniger Code und Konfiguration (kein Codegen, durchgängige TS-Inferenz — trpc.io). Hast du eine mobile App, eine öffentliche API für externe Entwickler oder mehrere unabhängige Services, bietet GraphQLs Schema-Vertrag und das Föderations-Ökosystem (Apollo Federation) eine passendere Abstraktion.