tRPC vs REST
tRPC (RPC con tipado seguro, TypeScript full-stack) frente a REST API (agnóstico de lenguaje, estándar): comparación de diseño de APIs. Type safety, ecosistema, escalabilidad.
Cero generación de código, seguridad de tipos TypeScript de extremo a extremo
Esquema primero, lenguaje de consulta universal para múltiples clientes
Decide según el contexto — la 'seguridad de tipos' por sí sola no es una razón para elegir GraphQL. Si usas un único monorepo TypeScript con un único cliente web, tRPC casi siempre reduce más el trabajo: cero codegen, y un cambio en el servidor se convierte al instante en un error de TS en el cliente. Si tienes una app móvil, una API pública abierta a desarrolladores externos o necesitas federación multi-equipo, el contrato de esquema independiente del lenguaje de GraphQL y su ecosistema Apollo Federation ofrecen una ventaja estructural.
| Categoría | tRPC | GraphQL |
|---|---|---|
| Rendimiento | 7/10 | 6/10 |
| Facilidad de aprendizaje | 8/10 | 5/10 |
| Ecosistema | 6/10 | 9/10 |
| Comunidad | 7/10 | 8/10 |
| Mercado laboral | 5/10 | 8/10 |
| A prueba de futuro | 7/10 | 8/10 |
// tRPC — definición de router (servidor)
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
// db = cliente Prisma/ORM (importado desde un archivo aparte)
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;
// Cliente — el tipo del servidor se infiere automáticamente, sin 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; ... } — seguridad de tipos completa en tiempo de compilación// graphql-js + @apollo/server — esquema, resolver y servidor en un solo archivo
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// db = cliente Prisma/ORM (importado desde un archivo aparte)
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(`Servidor listo: ${url}`);
// Consulta del cliente — solo se seleccionan los campos necesarios:
// query { user(id: "1") { name posts { title } } }Decide según el contexto — la 'seguridad de tipos' por sí sola no es una razón para elegir GraphQL. Si usas un único monorepo TypeScript con un único cliente web, tRPC casi siempre reduce más el trabajo: cero codegen, y un cambio en el servidor se convierte al instante en un error de TS en el cliente. Si tienes una app móvil, una API pública abierta a desarrolladores externos o necesitas federación multi-equipo, el contrato de esquema independiente del lenguaje de GraphQL y su ecosistema Apollo Federation ofrecen una ventaja estructural.
Solicita una consultoría gratuitaSi trabajas en un único monorepo TypeScript con un único cliente web, tRPC requiere menos código y configuración (cero codegen, inferencia de TS de extremo a extremo — trpc.io). Si tienes una app móvil, una API pública abierta a desarrolladores externos o varios servicios independientes, el contrato de esquema de GraphQL y su ecosistema de federación (Apollo Federation) ofrecen una abstracción más adecuada.