tRPC vs GraphQL vs REST: Chọn API Layer nào cho TypeScript Fullstack

Khi xây dựng fullstack TypeScript application, bạn cần chọn API layer giữa frontend và backend. Ba lựa chọn phổ biến nhất hiện nay là tRPC, GraphQL, và REST. Mỗi cái có trade-off riêng về type safety, flexibility, learning curve, và performance.

tRPC: Type-safe end-to-end

tRPC cho phép bạn gọi function từ frontend sang backend mà không cần generate schema, không cần HTTP client boilerplate. Backend define router với input/output type, frontend auto-complete kiểu trực tiếp từ backend types — cùng TypeScript project, cùng type inference.

// backend (server/router.ts)
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();

export const appRouter = t.router({
  getUser: t.procedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input }) => {
      return await db.user.findUnique({ where: { id: input.id } });
    })
});

export type AppRouter = typeof appRouter;

// frontend (client/users.tsx)
import { api } from '@/utils/api';
const { data } = api.user.getUser.useQuery({ id: '123' });
// data là User — full type safety, auto-complete

tRPC phù hợp khi:

  • Fullstack TypeScript monorepo (Next.js + tRPC là combo phổ biến).
  • Bạn cần tốc độ development, ít boilerplate.
  • API đơn giản, không cần over-fetching hoặc phức tạp query language.

Điểm yếu: phụ thuộc TypeScript, khó dùng với client không phải TypeScript (mobile native), mỗi client phải dùng tRPC client hoặc fetch raw.

Sơ đồ kiến trúc tRPC end-to-end type safety giữa React client và Node server
tRPC: type safety trực tiếp từ backend sang frontend

GraphQL: Flexible query language

GraphQL để client quyết định cần gì — gửi query, server trả về đúng field requested. Không over-fetching, không under-fetching, introspection API tự động document schema.

# Query example
query {
  user(id: "123") {
    name
    posts {
      title
      createdAt
    }
  }
}

# Server response chỉ chứa field được request
{
  "data": {
    "user": {
      "name": "Hung",
      "posts": [{"title": "Post 1", "createdAt": "2026-08-01"}]
    }
  }
}

GraphQL phù hợp khi:

  • Nhiều client khác nhau (web, mobile, IoT) cần data subset khác nhau.
  • Schema phức tạp, nested relationships (social network, e-commerce).
  • Bạn cần introspection, playground để test API.

Điểm yếu: learning curve cao, N+1 query problem cần DataLoader, caching phức tạp hơn REST, server-side complexity lớn.

GraphQL query và response so sánh với REST endpoint trả về full object
GraphQL: client quyết định data shape

REST: Simple, standard, battle-tested

REST dùng HTTP method chuẩn (GET, POST, PUT, DELETE), resource-based URL, JSON response. Đơn giản, dễ debug, dễ cache, có tooling phong phú.

GET /api/users/123
GET /api/users/123?fields=name,email

# Response
{
  "id": "123",
  "name": "Hung",
  "email": "[email protected]"
}

REST phù hợp khi:

  • API đơn giản, ít thay đổi schema.
  • Cần cache HTTP/CDN native.
  • Team đa ngôn ngữ (không phải toàn TypeScript).

Điểm yếu: over-fetching/under-fetching, không có type safety tự động giữa client/server, cần maintain OpenAPI spec hoặc dùng TypeScript generator như openapi-typescript.

So sánh chi tiết

Tiêu chí tRPC GraphQL REST
Type safety End-to-end tự nhiên Cần codegen (TypeScript) Cần OpenAPI/types generator
Over-fetching Không Không (client chọn field)
Learning curve Thấp (nếu biết TypeScript) Cao Thấp
Tooling Trung bình Phong phú (Apollo, Relay) Rất phong phú
Caching HTTP cache Cần Apollo Client cache HTTP/CDN native
N+1 problem Không có Có (cần DataLoader) Không có
Client diversity Chủ yếu TypeScript Mọi ngôn ngữ Mọi ngôn ngữ
File size bundle Nhỏ Apollo ~40KB Nhỏ (fetch native)

Khi nào chọn cái nào?

Chọn tRPC nếu bạn làm fullstack TypeScript monorepo (Next.js + Node/Prisma). Type safety end-to-end giúp refactor nhanh, ít bug runtime. Đây là lựa chọn tối ưu cho team nhỏ/một người.

Chọn GraphQL nếu bạn có nhiều client khác nhau cần data subset khác nhau, hoặc schema phức tạp với nested relationships. Apollo Client + Relay giải quyết tốt caching và pagination.

Chọn REST nếu bạn cần đơn giản, độ tương thích rộng, hoặc team đa ngôn ngữ. Dùng OpenAPI + TypeScript codegen để có type safety mà không cần GraphQL complexity.

Kết luận

Không có “best” API layer — chỉ có “best fit”. tRPC thắng về developer experience trong TypeScript monorepo. GraphQL thắng về flexibility và client diversity. REST thắng về simplicity và ubiquity. Nhiều production system kết hợp cả ba: GraphQL cho public API, tRPC cho internal admin, REST cho third-party integration.

Nguồn tham khảo:
1. tRPC Documentation — end-to-end type safety
2. GraphQL Foundation — query language specification
3. RESTful API Design — architectural style
4. MDN REST Guide — HTTP methods và status codes

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Biome.js: Công cụ Linter và Formatter JavaScript/TypeScript Nhanh Như Rust Thay Thế ESLint và Prettier

Biome là một web toolchain (formatter + linter + LSP) được viết bằng Rust, hỗ trợ JavaScript, TypeScript, JSX, TSX, JSON, HTML, CSS, và GraphQL. Được ra mắt năm 2023,…

Xem thêm

Supabase: Open-source Firebase Alternative với PostgreSQL

Supabase là gì: Firebase Alternative mã nguồn mở dựa trên PostgreSQL Supabase là nền tảng phát triển ứng dụng mã nguồn mở (Apache 2.0, hơn 108K ⭐ trên GitHub) dựa…

Xem thêm

Drizzle ORM: TypeScript ORM hiện đại cho PostgreSQL và MySQL

Drizzle ORM là một ORM hiện đại dành cho TypeScript, hỗ trợ PostgreSQL, MySQL, SQLite và các database serverless như Turso, Neon, Cloudflare D1. Với kích thước chỉ ~7.4KB gzipped,…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất