RPC or REST

CodeDrill now has two APIs. Nadia’s browser sends requests to the application over REST. The application calls the runner over JSON-RPC.

We could use RPC for the browser too, with procedures such as getProblem and submit on one endpoint. But Nadia’s client works with resources: problems and submissions. Each has its own URL. A response to GET /problems/14 can be cached by the browser and by shared caches between the browser and the application. We did this with Cache-Control for the Public Courses API. With our RPC design, every call would be a POST to /rpc, so we would lose this straightforward use of HTTP caching.

For the runner, we tried REST with POST /runs. The application saves the results of a run with the submission. So we do not need to expose each run as a separate resource. runSubmission is an action with arguments and a result.

So two questions decide which one to use:

  • What does the API offer? If it offers resources that clients read, create, and change, use REST. If it offers actions with arguments and results, use RPC.
  • Who writes the clients? Most developers already know RESTful HTTP APIs, including what GET, 404, and Location mean. So if we want other developers to pick up our API, REST makes that easier. Between our own services, we write both sides, so it matters less that REST is easier to learn.

GraphQL, which we saw earlier, is a third choice. It is for clients that need to choose which fields of related data they read.

JSON-RPC in tools you use

  • The Language Server Protocol (LSP) connects an editor, such as VS Code, to a language server, a program that understands one programming language. When you hover over a method name, the editor calls textDocument/hover on the language server. The editor shows the text in the result. The calls are JSON-RPC.
  • The Model Context Protocol (MCP) connects an AI application, such as Claude Code or the Claude app, to servers that give it tools. When the model uses a tool, the application calls tools/call on that tool’s server. MCP’s messages are JSON-RPC 2.0.

In both, the two sides are often processes on the same machine. They keep one connection open between them. Either side can call the other. In LSP, for example, the language server calls workspace/applyEdit on the editor to change a file. REST does not offer this, because in REST only the client sends requests.