Skip to content
Tech Stack15 July 2026 · 7 min readUpdated 30 September 2026

tRPC vs REST vs GraphQL for B2B SaaS APIs in 2026

tRPC, REST and GraphQL fit different callers: your own TypeScript client, a partner you don't control, or a client that aggregates several backends. Here is the split I'd recommend for B2B SaaS.

tRPC vs REST vs GraphQL for B2B SaaS APIs in 2026

Someone on your team has asked whether the new B2B SaaS API should be tRPC, REST or GraphQL, and the discussion has stalled because each option sounds right. They each fit a different caller. Your first action: list every kind of caller your API will have in the next twelve months (your own dashboard, a mobile app, partner systems, webhooks) and mark which ones you don't control. That list decides most of the answer.

Which API Style Should a B2B SaaS Use: tRPC, REST or GraphQL?

Use tRPC for callers that share your TypeScript code, REST for anything a partner or third party must call, and GraphQL only once one client needs data from several backends in variable shapes.

Isometric illustration of a pipeline forking into three paths, each leading to a differently shaped mechanical assembly

The real difference is who is allowed to call the API, not which one is technically superior. tRPC assumes the caller shares your types, REST assumes it doesn't, and GraphQL assumes the caller's data needs are unpredictable enough that a fixed response shape would be wasteful. Performance and tooling arguments mostly follow from that. The table maps each style to the dimensions that show up in production.

DimensiontRPCRESTGraphQL
Type safetyInferred from your TypeScript, no schema or codegenOnly as good as your OpenAPI spec and generated typesTyped schema; resolver bugs still happen
Who can call itTypeScript clients that share your typesAny HTTP client in any languageAny client that can send a GraphQL request
Best fitAuthenticated dashboard and admin trafficPartner APIs, webhooks, OAuth callbacksAggregating several backends for a variable client
CachingHandled at your data or client layerResource URLs work with standard HTTP cachesGET for queries, persisted documents for long ones
ContractTied to your deployDocumented, versioned resourcesVersionless schema evolution

Popularity data is only a rough signal, but it shows the scale gap. The npm registry's download counts for the week of 22 to 28 September 2026 show about 6.05 million downloads for @trpc/server and about 56.8 million for graphql. Those numbers include CI installs and transitive dependencies, so they don't prove what teams choose for their own APIs. They do suggest GraphQL is far more widely embedded across the ecosystem, while tRPC's audience is narrower and TypeScript-specific.

Is tRPC Only for Internal APIs?

Mostly yes: tRPC is built to keep client and server types in sync inside one TypeScript codebase, so it fits authenticated internal traffic and not partner-facing APIs.

Isometric illustration of a sealed cube-shaped vault connected to internal gear and circuit machinery by a single pipe

The tRPC documentation describes it as a way to build and consume fully typesafe APIs without schemas or code generation, and frames the problem as keeping API contracts in sync between client and server in full-stack TypeScript projects. The npm registry currently lists version 11.19.0 as the latest release. Nothing in that description is about interoperability with other languages, and I couldn't find a non-TypeScript client story on the pages I checked, so treat that as unsupported unless you add another layer.

For a Next.js App Router dashboard, the tRPC App Router setup guide uses the fetch adapter in a route handler and shows server components prefetching queries and passing them to the client through a hydration boundary. That's a clean fit for anything behind login. My recommendation: don't treat tRPC as a stepping stone to a public API. If a partner asks for access from Python or a mobile team ships in Kotlin, you'll want a second surface for them, and building it from an OpenAPI contract written on purpose beats reverse-engineering procedures later.

When Does REST Still Win for Partner APIs?

REST wins wherever a partner, webhook sender or client outside your control needs a documented contract that doesn't assume shared code.

Isometric illustration of a loading dock with shipping containers being loaded from several trucks along a conveyor

The OpenAPI Specification defines a standard, programming language-agnostic interface description for HTTP APIs, which is what lets a partner's engineer generate a client without asking you anything. Webhooks are the clearest example. Stripe's webhook documentation requires a publicly reachable HTTPS endpoint that accepts POST, verifies the Stripe-Signature header against the raw request body, and returns a 2xx quickly. Stripe also retries failed live-mode deliveries for up to three days and advises tracking event IDs to catch duplicates. That's an HTTP contract, and no type-sharing scheme could satisfy it.

BookBed shows the single-writer idea in a Flutter, Firebase and Stripe stack: its case study says webhook writes sync accountType in lockstep with subscription status, so nothing else has to guess billing state. In a Next.js and Postgres app, that writer would be a Route Handler. If you need the mechanics of surviving retries, webhook reliability, idempotency and dead-letter queues goes deeper, and what a REST API is at the wire level clears up the RPC-versus-REST confusion that keeps resurfacing in meetings. A REST surface also needs rate limits from day one, which rate limiting patterns for SaaS APIs covers.

What should a partner-facing REST surface include?

Start from what a partner's engineer needs on day one, and treat everything else as optional. Stripe's webhook documentation is a useful model because it documents both sides of the contract, and the pattern generalizes to your own API:

  1. An OpenAPI document that describes every endpoint, so a partner can generate a client and doesn't need to ask you questions.
  2. Authentication that's separate from your dashboard sessions, so revoking one partner doesn't log out your own users.
  3. Explicit rate limits and a documented response when a limit is hit.
  4. Signed webhooks with the signing scheme, the retry behaviour and the duplicate-handling advice written down, as Stripe does.
  5. A versioning rule you can honour, for example additive changes only inside a version.

Items 2 and 5 are my recommendations, not requirements from a source above. The point is that each item is something tRPC never asked you to write, which is exactly why partner traffic doesn't belong on it.

Is GraphQL Overkill for a B2B SaaS?

Usually, unless you aggregate data from more than one backend for clients whose needs vary; with one database and one app, plain REST endpoints cover the same ground with less machinery.

The GraphQL site describes it as enabling flexible, versionless APIs powered by a strong type system. Its HTTP guide is useful for judging the cost: servers operate on a single endpoint, usually /graphql; POST is required and GET is optional and only for queries; and long queries can exceed URL limits imposed by browsers and CDNs, which is why the guide points to persisted documents or automatic persisted queries. Those are extra pieces you now own. What GraphQL optimizes for is client-driven queries across heterogeneous sources. If your B2B SaaS has one database, one primary app and a few partner webhooks, you don't have that fan-out problem.

Consider a hypothetical team with an admin screen that needs data from four internal services at once. There, GraphQL as an aggregation layer earns its place quickly, because the alternative is four round trips or a bespoke backend-for-frontend. The mistake isn't choosing GraphQL. It's choosing it before you have more than one backend to aggregate.

One detail from the GraphQL HTTP guide affects monitoring. It says a response with a non-null data key can come back with a 2xx status even when it contains errors, while validation errors that prevent execution should return 400 when the server uses the application/graphql-response+json media type. Legacy servers using plain application/json may return 2xx for errors as well. In practice that means status-code dashboards alone can hide failing GraphQL operations, so you'll want to log the errors array. A REST endpoint's status codes carry more of that signal by default.

What if a partner insists on GraphQL?

Wrap your existing API in a thin GraphQL facade for that partner instead of rebuilding your data layer around one client's tooling. Your core stays boring and stable, and the partner gets the query shape they've already built around. If several partners ask for the same thing, treat that as a signal the public API deserves GraphQL as a first-class surface. The Next.js docs also note that you can keep calling existing REST or GraphQL endpoints from Server Components, so adopting the App Router doesn't force the choice either way.

The hybrid split I'd recommend

  1. tRPC for everything behind login: dashboard reads, internal mutations and admin actions.
  2. REST for anything outside your TypeScript boundary: Stripe webhooks, OAuth callbacks, health checks and mobile clients.
  3. A small, versioned REST subset for partners, generated from an OpenAPI contract you write deliberately.
  4. GraphQL only once you have a real aggregation problem.

Callidus is a useful counter-example to all three. Its case study describes a React front end talking to Firebase, with tenant data under tenants/{tenantId} in Firestore and access enforced by Firestore rules, plus Cloud Functions for scheduled work. Sometimes your database's rules layer is the boundary, and none of these API styles is the first decision. If you're still choosing the rest of the stack, the SaaS MVP stack guide and the Next.js and Prisma setup are where I'd check the pieces together, and what B2B SaaS means for API design frames the partner requirements.

Here's a question to answer this week: if you removed GraphQL from your stack and replaced it with two REST endpoints, what would you actually lose?

Free resource

Free SaaS MVP Scope Template

A Notion document with the full feature checklist, MVP vs. nice-to-have table, pre-build questions, and cost signals — so you walk into any developer call knowing exactly what to ask for.

Get the template →
DL

Dusko Licanin

Full-Stack Developer · Banja Luka, Bosnia

Full-stack developer shipping SaaS MVPs, web apps, and mobile apps using AI-augmented workflows — without agency coordination overhead. Live portfolio: BookBed, Callidus, Pizzeria Bestek.

Frequently Asked Questions

Is tRPC a good fit for a Next.js SaaS dashboard?

Yes, for authenticated traffic where the frontend and backend share one TypeScript codebase. tRPC describes itself as a way to build fully typesafe APIs without schemas or code generation, so a changed procedure output shows up as a compile error in the client instead of a production bug. It stops fitting once a mobile client in another language or a partner needs access, because its documentation frames the problem inside full-stack TypeScript projects. In that case add a REST surface for those callers.

How should I design a REST API for a B2B SaaS product?

Design it around resources and a documented contract that a partner can integrate against without reading your source code. Describe it with an OpenAPI document, which the specification defines as a language-agnostic interface description for HTTP APIs, so partners can generate their own clients. Keep the partner-facing surface separate from your internal dashboard API, and add rate limits and versioning from the start. Webhooks you send or receive should follow the same discipline, including signatures and duplicate handling, as Stripe's webhook documentation shows.

What is the real difference between GraphQL and tRPC?

GraphQL lets any client in any language request exactly the fields it needs from a typed schema, while tRPC gives one TypeScript codebase end-to-end type safety with no schema or code generation. GraphQL addresses varied client needs across multiple backends, and tRPC addresses contract drift between a frontend and backend that already share types. They solve different problems, so choosing by which one feels more modern misses the point. The GraphQL HTTP guide also lists costs to plan for, such as a single endpoint and persisted documents for long queries.

What is the biggest mistake teams make designing a B2B SaaS API?

The biggest mistake is picking one API style for the whole product before listing who will call it. A dashboard, a partner integration and a webhook receiver have different needs, and forcing them through one style makes at least one of them worse. My recommendation is to map callers first, then use tRPC behind login, REST for anything outside your TypeScript boundary, and GraphQL only when you have a real multi-backend aggregation problem. Revisit the split when a new caller type appears.

Can I mix tRPC, REST and GraphQL in the same SaaS product?

Yes, and for many B2B SaaS products a mix is the normal end state. A common shape is tRPC for the authenticated dashboard, REST for webhooks and partner access, and GraphQL only as a facade or aggregation layer when a real need appears. The Next.js docs even note you can keep calling existing REST or GraphQL endpoints from Server Components. Keep each surface owned and documented, so you don't end up maintaining three overlapping copies of the same business logic.