RPC vs GraphQL/REST

You don't know what RPC is? The Telefunc Tour explains what it is.

TL;DR

A GraphQL/RESTful API is only needed if:

  • We want to give third parties access to our database.
  • We are a very large company with highly complex databases.

Otherwise, we can use RPC for a significant increase in development speed.

Contrary to common belief, we can use RPC while having a decoupled frontend-backend development.

Third Parties

The most eminent use case for REST and GraphQL is giving third parties access to our database.

For example, Facebook's API is used by ~200k third parties. It makes sense that Facebook uses (and invented) GraphQL, as GraphQL enables any third-party developer to extensively access Facebook's database, thus enabling all kinds of applications to be built on top of Facebook's data.

GraphQL/RESTful APIs are generic: they are meant to serve frontends without knowing the frontends' data query/mutation requirements.

In contrast, as we discussed in Overview > Tour > Inversion of control, telefunctions (RPC endpoints) are tailored to our frontend's UI components. This means that our telefunctions are only useful for our frontend and third parties cannot use them to build third-party frontends.

⚗️

Research Area. It is theoretically possible to also use RPC for giving third parties access to our database, but this has not been done so far. Reach out to the Telefunc maintainers if you are interested in exploring this topic.

Decoupled frontend-backend

A common misbelief is that GraphQL/REST is required to decouple the frontend development from the backend development.

It is true that GraphQL/REST induces a decoupling: as we have seen in the last section, a GraphQL/RESTful API is generic which means that the frontend team can develop independently of the backend team.

But we can as well achieve a decoupled frontend-backend development with RPC by using what we call a Telefunc Server.

Telefunc Server

We usually install Telefunc as a Node.js server middleware. This induces a tight coupling between our frontend and our Node.js server.

For example, let's consider this telefunction:

// TodoList.telefunc.js
// Environment: Node.js

import { getContext } from 'telefunc'

// This telefunction is tightly coupled to the frontend: it returns exactly and
// only what the <TodoList /> component needs.

export async function getInitialData() {
  const { user } = getContext()
  if (!user) {
    return { isNotLoggedIn: true }
  }
  const todoItems = await database.query(
    'SELECT id, text FROM todos WHERE authorId = :authorId',
    { authorId: user.id }
  )
  const { firstName } = user
  return {
    user: { firstName },
    todoItems
  }
}

If we change our <TodoList> component to also show the to-do items' creation date, then we need to change the SQL query of our getInitialData() telefunction from SELECT id, text to SELECT id, text, created_at.

This means that the frontend developers need to make changes to the Node.js server and re-deploy it.

If we are a small team of full-stack developers, then such frontend-backend coupling is not a problem. But, as we grow, we may want to have a frontend team that develops independently of a backend team.

We can achieve a decoupling by using a Telefunc Server: a dedicated Node.js server with sole purpose of serving telefunctions.

The frontend and the Telefunc server are developed & deployed hand-in-hand, while the backend (another Node.js server, Ruby on Rails, ...) can be developed & deployed independently.

Multiple Frontends

Another common misbelief is that GraphQL/REST is required to develop several frontends.

We can develop multiple frontends as well with RPC by having one Telefunc Server per frontend.

The rise of edge computing, such as Cloudflare Workers, makes Telefunc Servers highly performant, cheap (with generous free tiers), and easy to set up.

Complex Databases

A less common but nonetheless widespread use case is the usage of GraphQL in very large companies.

The databases of large companies can become too complex for the frontend team.

Instead of the frontend team directly accessing the databases with Telefunc & SQL/ORM queries, we create a GraphQL API that is simpler to use. We essentially use GraphQL to abstract away the complexities of our databases.

For performance-critical apps deployed at large scale, such as Twitter or Facebook, it is common to use several database technologies at once. We can then even use GraphQL to simplify the life of not only the frontend developers but also the backend developers: the backend developers then also use the GraphQL API instead of directly accessing our databases.

A GraphQL API enables an independent database development which can become crucial strategy at scale.

GraphQL is the state-of-the-art for this use case; a RESTful API would be too limiting.

Which one to choose?

RPC enables our frontend to directly use ORM/SQL queries which is not only a fundamentally simpler approach, but also more powerful (we can achieve more with ORM/SQL queries than with GraphQL/RESTful queries). So we should use RPC whenever we can for a significant increase in development speed.

Also, RPC is a natural fit for the increasingly ubiquitous practice of full-stack development with frameworks such as Next.js.

On the other hand, we need GraphQL/REST if we need to give third parties access to our database.

Also, using a GraphQL API can be crucial strategy for very large companies with highly complex databases.

In general, a sensible default is to start with RPC and use GraphQL/REST only when the need arises.