← Semua picks

Format Compare Conditional

REST vs GraphQL vs tRPC: SaaS 2026

Tiga format API saya jalankan paralel 22 bulan di SaaS B2B Jakarta. REST untuk public API + integrasi partner. GraphQL untuk dashboard internal kompleks. tRPC untuk product TypeScript-first end-to-end. Verdict per audience + use case.

3 Juli 2026 · 11 menit ·Use case: Format API untuk SaaS B2B multi-channel Indonesia
RESTGraphQLtRPCgRPC

TL;DR

  • REST: web standard, OpenAPI matur, ideal untuk public API + integrasi partner.
  • GraphQL: query fleksibel, mengurangi over/under-fetching, ideal untuk dashboard kompleks + mobile.
  • tRPC: TypeScript end-to-end type safety, DX terbaik untuk product TS-first.
  • Verdict: Conditional — pilih per audience + use case. SaaS modern Indonesia: campur ketiga dengan boundary jelas.

Konteks

Saya jalankan ketiga format ini paralel 22 bulan di SaaS B2B fintech-adjacent Jakarta (Agustus 2024 - Mei 2026). 18 microservice + 6 frontend channel. Pattern:

  • REST API publik untuk partner integration (8 endpoint group, ~120 endpoint total)
  • GraphQL untuk dashboard internal product (1 schema unified, ~280 type)
  • tRPC untuk product web (Next.js frontend + Node backend, ~340 procedure)

Sebelumnya di BUMN Jakarta 2022-2024 saya pakai REST + SOAP (legacy). Pengalaman GraphQL 3 tahun (di SaaS klien 2022-2025), tRPC 2 tahun.

Pricing + cost model

API format sendiri gratis (semua open spec). Cost real = infra + ops + tooling.

REST tooling

  • OpenAPI spec generation: gratis (library)
  • Documentation portal Mintlify: USD 350-1.500/bulan (Rp 5,6-24 juta)
  • Atau Redoc self-host: gratis
  • Atau Stoplight: USD 39-1.299/bulan tergantung tier
  • API gateway (Kong, Tyk, Cloudflare API Shield): USD 25-500/bulan
  • Saya pakai Cloudflare API Shield: USD 25/bulan = Rp 400 ribu/bulan

GraphQL tooling

  • Apollo Server: gratis open source
  • GraphQL Federation (Apollo Gateway atau Hive): self-host gratis, managed USD 99-2.500/bulan
  • Hasura Cloud: USD 0-99/bulan
  • Saya pakai Apollo Server + GraphQL Codegen self-host: gratis + Rp 300 ribu/bulan compute

tRPC tooling

  • tRPC: gratis (library MIT)
  • No external tooling needed (type-sync via TypeScript langsung)
  • Cost: gratis

Total format API cost

KomponenCost/bulan
Cloudflare API Shield (REST publik)Rp 400 ribu
Apollo Server compute (GraphQL)Rp 300 ribu
Mintlify documentation portalRp 5,6 juta
OpenAPI spec generation (built-in)Rp 0
TotalRp 6,3 juta/bulan

Bandingkan all-managed (Apollo Studio Pro + Stoplight + Kong Konnect): bisa Rp 15-25 juta/bulan untuk equivalent feature. Self-host + Mintlify dokumentasi = sweet spot cost/feature.

Performance comparison

Setup: 1 pod GKE Jakarta (e2-medium 2 vCPU 4GB), Postgres regional, workload campuran.

Query simple (1 entity, GET by ID)

Formatp50p99p99.9
REST GET /user/:id18ms95ms220ms
GraphQL query { user(id) { … } }24ms125ms280ms
tRPC user.byId.query()19ms105ms240ms

GraphQL ~25-30% overhead untuk parsing + validation di query simple. tRPC overhead minimal.

Query kompleks (3-entity join)

Formatp50p99p99.9
REST (3 endpoint sequential)95ms380ms850ms
REST (1 custom endpoint dengan join)35ms180ms420ms
GraphQL (1 query dengan DataLoader)42ms195ms480ms
tRPC (1 procedure dengan join manual)38ms185ms440ms

REST sequential round-trip kalah jauh. REST custom endpoint, GraphQL, tRPC comparable. Trade-off: REST custom endpoint = banyak endpoint custom (endpoint explosion); GraphQL = 1 endpoint fleksibel; tRPC = procedure per use case.

Throughput

FormatRPS max per podp99 di max RPS
REST (Fastify)1.250220ms
GraphQL (Apollo Server)850380ms
tRPC (Fastify adapter)1.180235ms

GraphQL throughput lebih rendah 30-35% karena parsing overhead. Untuk hot path 5k+ RPS, REST atau tRPC lebih cocok.

Capability comparison

CapabilityRESTGraphQLtRPC
Type safety end-to-enddengan OpenAPI gendengan codegennative (TS)
Schema as codeOpenAPI / RAMLSDLTypeScript
Client SDK auto-genya (openapi-typescript, dll)ya (graphql-codegen)tidak perlu (type langsung)
Field selectiontidak (full payload)yatidak
Batchingtidakya (DataLoader)tidak
Real-time subscriptiontidak (WebSocket terpisah)yaya
File uploadyadengan multipartya
Caching HTTP standardyasulit (POST default)sulit
VersioningURL/headerfield deprecationTypeScript versioning
Documentation auto-genOpenAPI + Mintlifyintrospection + GraphiQLTypeScript type comment
Audit + rate limit per endpointmudahper-resolver customper-procedure custom
Public API friendlyyamediumtidak
Mobile client (Kotlin, Swift)yayabutuh OpenAPI export
Webhook + event patternnaturaladaada

Trade-off arsitektural

Pilih REST kalau:

  • API target audience external (partner integration, public API)
  • Tooling enterprise standard wajib (Postman collection, OpenAPI portal, API gateway)
  • Client variety tinggi (mobile native, web, server-to-server, third-party)
  • Cache-ability via HTTP cache penting
  • Tim familiar standard pattern (REST + HTTP semantics)

Pilih GraphQL kalau:

  • Dashboard kompleks dengan query bervariasi per user role
  • Mobile client butuh minimize payload size (field selection)
  • Federation antar service (Apollo Federation, Hive)
  • Subscription real-time native
  • Team frontend punya autonomy ngambil data sesuai kebutuhan tanpa nunggu backend tambah endpoint

Pilih tRPC kalau:

  • Stack TypeScript end-to-end (Next.js + Node, atau SvelteKit + Node)
  • Internal product API (bukan public API)
  • DX iteration speed prioritas (zero codegen step)
  • Tim full-stack TypeScript
  • Tidak butuh client non-TS

Pattern hybrid yang saya jalankan

Internet

   ├── Public REST API (/api/v1/*)
   │   └── Cloudflare API Shield → Gateway → REST service
   │       (untuk partner integration, OAuth, rate limit)

   ├── Product web (Next.js)
   │   └── tRPC procedure (/trpc/*)
   │       (untuk internal product, TS end-to-end)

   ├── Dashboard analitik (React + Apollo)
   │   └── GraphQL endpoint (/graphql)
   │       (untuk BI query kompleks)

   └── Mobile (Android Kotlin, iOS Swift)
       └── REST endpoint (/mobile/v1/*)
           (OpenAPI codegen ke Kotlin/Swift)

Per-channel pakai format yang cocok. Engineering cost upfront lebih tinggi (3 format = 3 tooling chain), tapi long-term DX + performance per-channel optimal.

Trade-off pattern hybrid

Pro:

  • Per-audience optimization (publik = REST standar, internal TS = tRPC native, dashboard = GraphQL fleksibel)
  • Tidak compromise

Con:

  • 3 tooling chain (OpenAPI, GraphQL codegen, tRPC) butuh maintenance
  • Engineer harus familiar dengan 3 pattern
  • Boundary antar format harus jelas — siapa pakai mana?

Bandingkan pure REST: lebih sederhana, 1 tool chain. Tapi DX internal product turun + dashboard query kompleks butuh banyak custom endpoint.

Bandingkan pure GraphQL: 1 endpoint universal. Tapi public API GraphQL = friction tinggi untuk partner integration (mereka biasa REST).

SLO target per format

FormatLatency p99 targetThroughput targetError rate target
REST publik (partner)< 250ms500 RPS sustained< 0,1% 5xx
GraphQL dashboard< 600ms (complex query OK)200 RPS< 0,5%
tRPC product internal< 300ms1k RPS< 0,1%

Untuk fintech, public REST API SLO ketat — partner punya kontrak SLA. Internal GraphQL lebih longgar karena query bisa kompleks. tRPC product hot path ketat (frontend user-facing).

Migration risk

REST → GraphQL

Saya jalankan di SaaS klien 2023: 60 REST endpoint → 1 GraphQL schema (110 type).

  • Effort: 8-12 minggu untuk dual-run + cutover
  • Pain point: caching strategy harus redesign (HTTP cache → resolver-level cache + DataLoader)
  • Outcome: client request volume turun 35% (field selection), p99 dashboard turun 40%
  • Trade-off: throughput service drop 30% untuk endpoint sederhana

REST → tRPC

Untuk product TS-first, smoother:

  • Effort: 4-6 minggu untuk 40 endpoint
  • Pain point: tRPC tidak ada HTTP method semantik (semua POST) — middleware yang depend GET/POST butuh refactor
  • Outcome: DX naik signifikan, codegen step hilang
  • Trade-off: hilang HTTP caching native — lakukan caching di tRPC middleware atau layer di atas

GraphQL → tRPC

Tidak biasa, tapi mungkin untuk internal-only product TS. Pengalaman teman saya: 8-12 minggu, gain DX, lose flexibility query custom.

Common pitfall

  1. GraphQL N+1. Resolver default = 1 DB call per field. Tanpa DataLoader, query 1 list × 5 field nested = 5 + 25 = 30 query. Pakai DataLoader dari hari pertama.
  2. REST over-fetching. Endpoint return full object termasuk field besar (logs, history) yang client tidak butuh. Implement sparse fieldset (?fields=id,name) atau bikin variant endpoint.
  3. tRPC accidental public exposure. tRPC procedure mudah expose. Implement auth middleware mandatory di tRPC router root, audit per-procedure permission.
  4. GraphQL query complexity attack. Client kirim query nested deep = bunuh server. Implement query complexity analysis (graphql-cost-analysis), max depth, max alias.
  5. Versioning REST tanpa kontrak test. Breaking change accidental ke client integrasi partner = trust kerusakan. Wajib contract test (Pact, Dredd) di CI sebelum release.

OpenAPI workflow untuk REST

Pattern saya:

  1. Source of truth: TypeScript type di backend (Hono RPC, NestJS, FastAPI)
  2. Auto-generate OpenAPI spec di build step
  3. Spec di-commit ke api/openapi.yaml di repo (versioned)
  4. Mintlify watch repo, auto-deploy doc portal
  5. Client SDK auto-generate dari spec (openapi-typescript, openapi-generator)

Setup awal 1 minggu. Setelah itu maintenance < 1 jam/minggu.

GraphQL Federation pattern

Untuk 18 microservice fintech, saya tidak pakai Federation full (overhead tinggi). Pattern saya:

  • 1 GraphQL gateway service (Apollo Gateway atau Hive)
  • 3-4 subgraph (user domain, payment domain, notification domain, analytics)
  • Sisanya service expose REST internal, gateway tarik via resolver

Federation full worth kalau service domain 10+ dengan team berbeda per domain. Saya skala 4 domain, hybrid pattern cukup.

Indonesia specific

Partner integration

Partner bank Indonesia (BCA, BNI, Mandiri) tooling-nya REST + SOAP legacy. Public API SaaS fintech Indonesia wajib REST untuk mengakomodasi.

Documentation Bahasa

Mintlify support multi-language. Saya provide doc portal dalam Bahasa Indonesia + English. Partner Indonesia prefer Bahasa, partner regional prefer English. Cost translation: 1x effort initial, sync via Mintlify export.

Public API rate limit untuk partner

Cloudflare API Shield rate limit per-customer (via API key). Pattern saya: 10 RPS sustained + 100 burst untuk tier basic, 100 RPS sustained + 1k burst untuk tier premium. Audit log via Cloudflare R2 + Splunk.

Yang surprising

Saya kira GraphQL akan jadi primary format di SaaS modern. Realita 22 bulan: tRPC menggantikan banyak use case yang dulu saya assume GraphQL only (internal product API). GraphQL tetap valuable, tapi scope-nya menyempit ke dashboard analitik kompleks + mobile field selection.

Surprise lain: REST tetap dominan untuk public API + partner integration. OpenAPI 3.1 ekosistem maturity nyata — partner Indonesia mengirim integration team yang familiar Postman + OpenAPI, tidak familiar GraphiQL.

Conclusion: tidak ada “winner” format. Pilih per-audience. Pure single-format adalah optimization yang salah arah untuk SaaS dengan multi-audience.

Verdict

Conditional dengan rule konkret per audience:

  • Public API + partner integration: REST + OpenAPI 3.1. Non-negotiable untuk Indonesia.
  • Internal product TS end-to-end: tRPC. DX + type safety unmatched.
  • Dashboard analitik kompleks + mobile field selection: GraphQL. Worth overhead untuk query flexibility.
  • Mobile native (Kotlin, Swift): REST dengan OpenAPI codegen ke Kotlin/Swift.
  • Skip pattern hybrid kalau tim engineering < 5 dev. Pakai REST saja, tambah tRPC kalau stack TS-first. GraphQL terlalu ops overhead untuk small team.

Threshold konkret untuk add GraphQL ke stack: dashboard memiliki > 8 query distinct per user role atau mobile client butuh field selection untuk > 50% endpoint. Di bawah ini, REST + GraphQL = over-engineering.

Ditulis oleh Asti Larasati

// Pick Format Compare lain


← Semua picks RSS feed