DEV Community

Cover image for RPC Systems: JSON-RPC vs XML-RPC vs SOAP vs gRPC vs Apache Thrift vs Connect vs tRPC
Shiv Rai (S_RAI)
Shiv Rai (S_RAI)

Posted on AI-assisted

RPC Systems: JSON-RPC vs XML-RPC vs SOAP vs gRPC vs Apache Thrift vs Connect vs tRPC

What are RPCs?

RPC (Remote Procedure Call) systems allow software running in one process, machine, or service to invoke functionality located somewhere else as if it were a local function call.

The core idea behind RPC is abstraction. Instead of thinking in terms of resources, endpoints, or data representations, developers think in terms of calling procedures, methods, or functions. The networking details are handled by the RPC framework.

In RPC interaction:

  1. A client calls a remote method.
  2. The request is serialized and transmitted over the network.
  3. The remote service executes the procedure.
  4. The result is returned to the caller.
  5. The framework deserializes the response into native language objects.

RPC systems exist because many distributed systems are fundamentally action-oriented rather than resource-oriented. They provide a natural way to model service-to-service communication, business operations, workflows, and internal platform APIs.

Common use cases include:

  • Microservice communication
  • Internal platform APIs
  • Backend-to-backend communication
  • Distributed systems
  • Enterprise integrations
  • High-performance service meshes
  • Full-stack TypeScript applications

This article includes: XML-RPC, SOAP, JSON-RPC, gRPC, Apache Thrift, Connect, tRPC


How to Choose ?

  1. Full-stack TypeScript development -> tRPC
  2. Modern microservices, HTTP/2, and streaming -> gRPC
  3. gRPC-style APIs needing broad HTTP compatibility (browser and backend) -> Connect
  4. Existing Thrift ecosystems or cross-language protocol/transport flexibility -> Apache Thrift
  5. Enterprise and standards-driven integrations -> SOAP
  6. Lightweight RPC over JSON -> JSON-RPC
  7. Legacy XML-RPC interoperability -> XML-RPC
flowchart TD

A[Need an RPC System] --> B{Entire stack uses TypeScript?}

B -->|Yes| C{Need end-to-end<br/>TypeScript inference?}
C -->|Yes| TRPC[tRPC]
C -->|No| D

B -->|No| D{Need broad HTTP compatibility<br/>across browser and backend clients?}

D -->|Yes| CONNECT[Connect]
D -->|No| E

E{Building internal<br/>microservices?}

E -->|Yes| F{Already using Thrift, or need<br/>flexible protocols/transports<br/>across many languages?}

F -->|Yes| THRIFT[Apache Thrift]
F -->|No| GRPC[gRPC]

E -->|No| G

G{Enterprise integration<br/>or WS-* requirements?}

G -->|Yes| SOAP[SOAP]
G -->|No| H

H{Must integrate with<br/>legacy XML-RPC systems?}

H -->|Yes| XMLRPC[XML-RPC]
H -->|No| JSONRPC[JSON-RPC]

Comparison

Aspect JSON-RPC XML-RPC SOAP Apache Thrift gRPC Connect tRPC
Mental Model Remote method calls Remote method calls Service operations and contracts Shared contracts across languages Fast, contract-driven function calls Service methods Type-safe function calls
Transport Protocol Usually HTTP, WebSocket, TCP Usually HTTP Usually HTTP Multiple transports HTTP/2 HTTP/1.1 and HTTP/2 HTTP
Serialization Format JSON XML XML Binary protocols Protocol Buffers Protocol Buffers or JSON Native TypeScript types over JSON
Performance Medium Low Low High Very High High Medium
Type Safety Low Low Medium High High High Very High
Browser Support Excellent Good Good Limited Limited without proxies Excellent Excellent
Language Support Broad Broad Broad Broad Broad Broad TypeScript-focused
Complexity Low Low High Medium Medium Medium Low
Typical Use Cases Lightweight APIs, protocol integrations Legacy systems Enterprise integrations Polyglot backend systems Microservices, platform infrastructure Browser-friendly RPC, modern APIs Full-stack TypeScript applications
Strengths Simplicity, easy tooling, human-readable Simplicity and legacy compatibility Standardization, enterprise features Efficient cross-language communication Performance, streaming, ecosystem Interoperability and browser support Outstanding developer experience
Weaknesses Weak contracts and typing Verbose XML and limited capabilities Complexity and operational overhead Smaller ecosystem than gRPC Browser constraints and operational complexity Newer ecosystem Limited outside TypeScript

Evolution View

Era Common Technologies Primary Goal
Early Web Services XML-RPC, SOAP Standardized remote communication over HTTP
Distributed Service Platforms Apache Thrift Efficient cross-language RPC
Cloud-Native Systems gRPC High-performance service communication
Modern Web-Friendly RPC Connect Better HTTP and browser interoperability
TypeScript-First Development tRPC End-to-end type safety and developer productivity

XML-RPC

In the late 1990s, distributed systems were difficult to integrate. Common approaches included:

CORBA
DCOM
RMI
Custom TCP Protocols
Enter fullscreen mode Exit fullscreen mode

These were often:

  • Vendor-specific
  • Complex
  • Difficult to integrate across platforms

Developers wanted something that worked over HTTP using XML. XML-RPC was created in 1998 and provided a simple way to:

  • Call a function
  • Across a network
  • Using HTTP

It was one of the first widely adopted web-service protocols.

XML-RPC thinks in remote function calls

XML-RPC assumes: Services expose methods, and clients call those methods remotely. Instead of:

GET /users/123
POST /orders
Enter fullscreen mode Exit fullscreen mode

XML-RPC says:

getUser(123)
createOrder(...)
Enter fullscreen mode Exit fullscreen mode

Core assumption: Network services should look like callable functions.

Example

Request

<?xml version="1.0"?>
<methodCall>
  <methodName>getUser</methodName>
  <params>
    <param>
      <value>
        <int>123</int>
      </value>
    </param>
  </params>
</methodCall>
Enter fullscreen mode Exit fullscreen mode

Response

<?xml version="1.0"?>
<methodResponse>
  <params>
    <param>
      <value>
        <struct>
          <member>
            <name>id</name>
            <value><int>123</int></value>
          </member>
          <member>
            <name>name</name>
            <value>Alice</value>
          </member>
        </struct>
      </value>
    </param>
  </params>
</methodResponse>
Enter fullscreen mode Exit fullscreen mode

This is effectively getUser(123) over HTTP.

Pros and Cons

Pros Cons
Simple RPC model Very verbose XML payloads
Cross-platform interoperability Weak typing and contracts
Human-readable messages Slow parsing compared to JSON/Protobuf
Uses standard HTTP transport Large message sizes
Easy firewall traversal Limited modern tooling
Historically important Rarely used in new systems
Influenced later web-service designs Mostly replaced by newer technologies

SOAP

As businesses started integrating systems across organizations, they needed more than simple remote procedure calls. Companies wanted:

  • Security
  • Reliability
  • Transactions
  • Formal Contracts
  • Interoperability

SOAP (Simple Object Access Protocol) was introduced in 1998 and became a W3C standard in the early 2000s. SOAP attempted to standardize enterprise communication across platforms and vendors.

SOAP thinks in contracts and messages

Core assumption: Distributed systems need formal agreements about communication.

A SOAP service is:

Contract (WSDL)
      +
Message Format
      +
Enterprise Standards
Enter fullscreen mode Exit fullscreen mode

Example

SOAP Request

<soap:Envelope>
  <soap:Body>
    <GetUser>
      <Id>123</Id>
    </GetUser>
  </soap:Body>
</soap:Envelope>
Enter fullscreen mode Exit fullscreen mode

SOAP Response

<soap:Envelope>
  <soap:Body>
    <GetUserResponse>
      <User>
        <Id>123</Id>
        <Name>Alice</Name>
      </User>
    </GetUserResponse>
  </soap:Body>
</soap:Envelope>
Enter fullscreen mode Exit fullscreen mode

WS-* Standards

SOAP is commonly paired with a family of enterprise standards known as WS-* ("WS-star"), including:

  • WS-Security – message-level encryption, signing, and authentication
  • WS-ReliableMessaging – guaranteed, ordered message delivery even over unreliable networks
  • WS-AtomicTransaction – coordinating distributed transactions across multiple services

These standards are why SOAP remained the go-to choice for banking, insurance, and government systems that needed guarantees plain HTTP alone couldn't provide.

Pros and Cons

Pros Cons
Strong formal contracts (WSDL) Extremely verbose XML
Enterprise-grade security High complexity
Reliable messaging support Large payload sizes
Distributed transaction support Slower than modern alternatives
Mature enterprise tooling Difficult developer experience
Strong interoperability guarantees Heavyweight for simple APIs
Common in regulated industries Rarely chosen for new projects

JSON-RPC

JSON-RPC first appeared around 2005, emerging as a lightweight alternative to XML-RPC and SOAP.

Why was it created?

At the time, many RPC systems used XML-RPC and SOAP which were powerful but verbose and cumbersome.

Developers wanted:

  • Simpler payloads
  • Easier parsing
  • Better JavaScript compatibility
  • Less bandwidth usage

JSON-RPC replaced XML with JSON while keeping the RPC model. JSON-RPC provided a standard way to represent:

Method Name
Parameters
Result
Error
Enter fullscreen mode Exit fullscreen mode

using JSON.

JSON-RPC thinks in remote function calls

Instead of:

POST /users
GET /users/123
Enter fullscreen mode Exit fullscreen mode

JSON-RPC says:

createUser(...)
getUser(123)
Enter fullscreen mode Exit fullscreen mode

The server exposes a set of methods. The client invokes them. Core assumption: APIs are collections of operations, not collections of resources.

Example

Request:

{
  "jsonrpc": "2.0",
  "method": "getUser",
  "params": {
    "id": 123
  },
  "id": 1
}
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "jsonrpc": "2.0",
  "result": {
    "id": 123,
    "name": "Alice"
  },
  "id": 1
}
Enter fullscreen mode Exit fullscreen mode

The API feels like getUser(123) even though it is happening across the network.

Where JSON-RPC shows up today

JSON-RPC quietly powers several widely-used systems, including Ethereum and other blockchain node APIs, Bitcoin Core's RPC interface, and the Language Server Protocol (LSP) used by code editors like VS Code.

Pros and Cons

Pros Cons
Very simple protocol Not resource-oriented
Lightweight JSON payloads Limited ecosystem
Transport agnostic Weak standardization outside core spec
Natural fit for command-style APIs Loses many HTTP benefits
Supports batch requests Can become method-heavy over time
Easy to implement Less tooling than gRPC or GraphQL
Works well over WebSockets No built-in typing or schema system

gRPC

gRPC, open-sourced by Google in 2015, evolved from Stubby, Google's internal RPC framework. Google operated thousands of services communicating with each other across data centers. gRPC was designed to make service-to-service communication:

  • Faster
  • Strongly typed
  • Easier to maintain
  • Easier to generate clients for

gRPC thinks in fast, contract-driven function calls over HTTP/2

Local function:

getUser(123)
Enter fullscreen mode Exit fullscreen mode

gRPC function:

userService.GetUser(123)
Enter fullscreen mode Exit fullscreen mode

The client behaves as if it's calling a local function, but the execution happens on another machine.

Core assumption: "Modern service-to-service communication should feel like calling a local function, while running on HTTP/2 with strong typing, low latency, and native streaming." This is what separates gRPC from earlier RPC systems. It isn't just "remote functions," it's remote functions built for high-performance, cloud-native microservices.

Example

Service Definition

syntax = "proto3";

service UserService {
  rpc GetUser(GetUserRequest) returns (User);
}

message GetUserRequest {
  int32 id = 1;
}

message User {
  int32 id = 1;
  string name = 2;
}
Enter fullscreen mode Exit fullscreen mode

Client call:

const user = await client.getUser({
  id: 123
});
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "id": 123,
  "name": "Alice"
}
Enter fullscreen mode Exit fullscreen mode

Because gRPC uses Protocol Buffers with numbered fields, services can add new fields over time without breaking existing clients which is a key reason contract-first systems like gRPC and Thrift age well in large codebases.

Streaming in gRPC

Unlike JSON-RPC, XML-RPC, or SOAP, gRPC supports more than simple request/response calls. It defines four call patterns:

  • Unary RPC – one request, one response (a normal function call).
  • Server Streaming – one request, a stream of responses (e.g., live price updates).
  • Client Streaming – a stream of requests, one final response (e.g., uploading data in chunks).
  • Bidirectional Streaming – both sides stream independently at the same time (e.g., chat, live collaboration).

Example of a server-streaming method:

service UserService {
  rpc WatchUserUpdates(GetUserRequest) returns (stream User);
}
Enter fullscreen mode Exit fullscreen mode

This built-in streaming is one of the main reasons teams pick gRPC over JSON-RPC or REST when they need continuous or real-time data flow, not just one-off calls.

Pros and Cons

Pros Cons
Extremely fast and efficient Poor native browser support
Strongly typed contracts Binary protocol is harder to inspect
Automatic client/server code generation Requires Protobuf tooling
Built-in streaming support Higher learning curve
Excellent for microservices More tightly coupled contracts
Multi-language support Often unnecessary for simple CRUD APIs
HTTP/2 performance benefits Public APIs usually favor REST

Apache Thrift

Apache Thrift was created at Facebook in 2007 and later donated to the Apache Software Foundation in 2008.

Facebook's infrastructure was growing rapidly and services were being written in different languages (PHP, Java, C++, Python). Each service needed to communicate with others. Without a common framework, teams had to manually create:

  • Serialization formats
  • Network protocols
  • Client SDKs
  • Server SDKs for every language combination.

Facebook wanted: "Define a service once, generate clients and servers everywhere." Thrift unified data serialization, RPC framework, and code generation into a single system.

Thrift thinks in shared contracts across languages

Core assumption: "A single Interface Definition Language (IDL) contract should let completely different languages, protocols, and transports interoperate without hand-written glue code for every combination."

Where Thrift distinguishes itself is flexibility: it doesn't lock a system into one protocol or one transport the way many RPC systems do.

Contract
   ↓
Generated Code (any language)
   ↓
Network Communication (any supported protocol/transport)
Enter fullscreen mode Exit fullscreen mode

Instead of:

GET /users/123
Enter fullscreen mode Exit fullscreen mode

Thrift says:

service UserService {
  User getUser(1:id)
}
Enter fullscreen mode Exit fullscreen mode

Core assumption: "Cross-language communication in large, heterogeneous systems should be generated from a shared contract, with the freedom to choose the protocol and transport that fits each situation."

Example

Thrift IDL

struct User {
  1: i32 id
  2: string name
}

service UserService {
  User getUser(1:i32 id)
}
Enter fullscreen mode Exit fullscreen mode

Generate code:

thrift --gen java user.thrift
thrift --gen go user.thrift
thrift --gen py user.thrift
Enter fullscreen mode Exit fullscreen mode

Client:

user = client.getUser(123)
Enter fullscreen mode Exit fullscreen mode

Response:

User(
  id=123,
  name="Alice"
)
Enter fullscreen mode Exit fullscreen mode

Pros and Cons

Pros Cons
Strong contract-first design More complex than REST
Excellent multi-language support Weak browser support
High-performance binary serialization Smaller ecosystem than gRPC
Automatic code generation Additional operational complexity
Flexible protocols and transports Steeper learning curve
Mature RPC framework Overkill for simple applications
Good fit for polyglot systems More moving parts than REST

Connect

Connect was created by Buf Technologies and publicly introduced around 2021–2022.

Native gRPC works well between servers but struggles in browsers because browsers do not expose the full HTTP/2 capabilities that gRPC relies on. Developers had to build extra components for browser support.

Connect keeps the good parts of gRPC while making APIs work across browsers, mobile apps, backend services, and CLI tools, without requiring specialized infrastructure. Importantly, Connect isn't just "gRPC for browsers". Many teams adopt it purely for backend-to-backend communication, because it works over standard HTTP/1.1 and HTTP/2 without the operational overhead (proxies, specialized load balancers) that plain gRPC often requires.

Connect thinks in RPCs over standard HTTP

Core assumption: RPC contracts should work everywhere HTTP works, for browser and backend clients alike. Instead of choosing between:

REST for browsers
gRPC for services
Enter fullscreen mode Exit fullscreen mode

Connect tries to provide:

One Contract
One API
Every Client
Enter fullscreen mode Exit fullscreen mode

Example

Service Definition

Same .proto file as gRPC:

syntax = "proto3";

service UserService {
  rpc GetUser(GetUserRequest)
      returns (User);
}
Enter fullscreen mode Exit fullscreen mode

Generate client/server code.

Client:

const response =
  await client.getUser({
    id: 123,
  });

console.log(response.name);
Enter fullscreen mode Exit fullscreen mode

The difference is largely in transport and compatibility. Connect defines a protocol that works over ordinary HTTP. Unlike gRPC, it does not require specialized HTTP/2 behavior for basic usage.

Pros and Cons

Pros Cons
Browser-friendly RPC Smaller ecosystem
Reuses existing Protobuf contracts Less industry adoption
Strong typing and code generation Primarily useful for gRPC-style architectures
Works with standard HTTP infrastructure Fewer learning resources
Supports Connect, gRPC, and gRPC-Web Additional technology choice
Easier deployment than gRPC-Web stacks Not as universally recognized as REST
Good full-stack developer experience Can be overkill for simple APIs

tRPC

Modern TypeScript applications often looked like this:

Frontend
    |
 REST/GraphQL
    |
Backend
Enter fullscreen mode Exit fullscreen mode

Even though both sides were written in TypeScript, developers still had to:

  • Define API routes
  • Create schemas
  • Generate types
  • Synchronize contracts This often felt redundant. Example:
type User = {
  id: number;
  name: string;
}
Enter fullscreen mode Exit fullscreen mode

might need to be defined multiple times across frontend and backend. tRPC was created by Alex Johansson around 2021. It uses TypeScript itself as the contract.

tRPC thinks in TypeScript functions

Core assumption: The frontend and backend belong to the same codebase and can share types directly. tRPC uses TypeScript types as the source of truth.

Example

Server

const appRouter = router({
  getUser: publicProcedure
    .input(z.number())
    .query(({ input }) => {
      return {
        id: input,
        name: "Alice",
      };
    }),
});
Enter fullscreen mode Exit fullscreen mode

Client

const user =
  await trpc.getUser.query(123);

console.log(user.name);
Enter fullscreen mode Exit fullscreen mode

TypeScript automatically knows user.id and user.name without code generation.

Pros and Cons

Pros Cons
End-to-end type safety TypeScript-only ecosystem
No code generation required Weak cross-language support
Excellent developer experience Tight frontend/backend coupling
Fast development speed Not ideal for public APIs
Great autocomplete and inference Smaller ecosystem
Perfect for monorepos Less suitable for large microservice environments
Minimal boilerplate Harder to integrate with non-TypeScript systems

Key Takeaways

  • JSON-RPC – Choose it for lightweight, transport-agnostic method calls, especially when you already have a JSON-friendly client and don't need strong typing or contracts.
  • XML-RPC – Only relevant when integrating with legacy systems that already speak it. Avoid for new projects.
  • SOAP – Choose it when you need formal contracts (WSDL) and enterprise-grade guarantees like security, reliable messaging, or distributed transactions (WS-*) like banking, insurance, and government systems.
  • Apache Thrift – Choose it for large, polyglot backend systems, especially if you need protocol/transport flexibility or already have Thrift infrastructure in place.
  • gRPC – Choose it for modern, performance-sensitive microservices that benefit from HTTP/2, strong typing, and native streaming. Avoid for public browser-facing APIs without a proxy layer.
  • Connect – Choose it when you want gRPC-style contracts with simpler HTTP compatibility across browsers, backends, and mobile clients, without the operational overhead of plain gRPC.
  • tRPC – Choose it for full-stack TypeScript applications, especially monorepos, where end-to-end type safety and developer speed matter more than cross-language support.

Top comments (0)