Top Related Projects
Quick Overview
ORPC (Object Remote Procedure Call) is a lightweight RPC framework for Rust. It allows for seamless communication between Rust applications across networks, enabling remote method invocation and object-oriented programming paradigms in distributed systems.
Pros
- Type-safe and efficient remote procedure calls in Rust
- Supports both synchronous and asynchronous communication
- Integrates well with Rust's ownership and borrowing system
- Minimal runtime overhead compared to other RPC frameworks
Cons
- Limited documentation and examples available
- Relatively new project, which may lead to potential instability or breaking changes
- Smaller community compared to more established RPC frameworks
- May have a steeper learning curve for developers new to Rust or RPC concepts
Code Examples
- Defining a remote service:
#[orpc::service]
trait MyService {
async fn hello(&self, name: String) -> String;
}
- Implementing the service:
struct MyServiceImpl;
#[orpc::async_trait]
impl MyService for MyServiceImpl {
async fn hello(&self, name: String) -> String {
format!("Hello, {}!", name)
}
}
- Creating a client and making a remote call:
let client = MyServiceClient::connect("127.0.0.1:8080").await?;
let result = client.hello("Alice".to_string()).await?;
println!("Server response: {}", result);
Getting Started
To use ORPC in your Rust project, add the following to your Cargo.toml
:
[dependencies]
orpc = "0.1"
Then, in your Rust code:
use orpc::prelude::*;
#[orpc::service]
trait MyService {
async fn greet(&self, name: String) -> String;
}
// Implement the service and use it in your application
For more detailed usage instructions and examples, refer to the project's documentation and examples in the repository.
Competitor Comparisons
C++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
Pros of gRPC
- Mature and widely adopted, with extensive documentation and community support
- High performance due to Protocol Buffers serialization and HTTP/2 transport
- Built-in support for multiple programming languages and platforms
Cons of gRPC
- Steeper learning curve, especially for developers new to Protocol Buffers
- More complex setup and configuration compared to simpler RPC frameworks
- Limited browser support without additional proxies or workarounds
Code Comparison
gRPC (Protocol Buffers definition):
syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
ORPC (JavaScript definition):
const greeter = {
sayHello: async (name) => {
return { message: `Hello, ${name}!` };
}
};
While gRPC requires a separate Protocol Buffers definition, ORPC allows for simpler, language-native definitions. gRPC offers more structured and typed interfaces, whereas ORPC provides a more flexible and lightweight approach to RPC.
Apache Thrift
Pros of Thrift
- Mature and widely adopted, with extensive language support
- Robust ecosystem and community backing from Apache
- Efficient binary serialization for high-performance RPC
Cons of Thrift
- Steeper learning curve due to complex IDL and generated code
- Less flexibility in protocol customization
- Heavier implementation compared to lightweight alternatives
Code Comparison
Thrift IDL example:
service Calculator {
i32 add(1: i32 num1, 2: i32 num2)
}
ORPC IDL example:
#[orpc::service]
trait Calculator {
async fn add(&self, num1: i32, num2: i32) -> i32;
}
The ORPC approach uses Rust-native syntax and attributes, making it more intuitive for Rust developers. Thrift's IDL is language-agnostic but requires learning a separate syntax.
Thrift generates language-specific code from the IDL, while ORPC leverages Rust's type system and async features directly. This results in a more seamless integration with Rust codebases for ORPC, but Thrift offers broader language support.
Both frameworks aim to simplify RPC implementations, but they cater to different use cases and developer preferences. Thrift is better suited for polyglot environments, while ORPC provides a more Rust-centric experience.
ZeroMQ core engine in C++, implements ZMTP/3.1
Pros of libzmq
- Mature and widely-used messaging library with extensive documentation
- Supports multiple programming languages and platforms
- High-performance and scalable for distributed systems
Cons of libzmq
- Steeper learning curve due to its complexity and feature-rich nature
- Requires more setup and configuration for basic use cases
- Larger codebase and potential overhead for simpler projects
Code Comparison
libzmq:
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.connect("tcp://localhost:5555");
zmq::message_t request(5);
memcpy(request.data(), "Hello", 5);
socket.send(request);
orpc:
let mut client = Client::connect("localhost:8080")?;
let response: String = client.call("echo", &"Hello".to_string())?;
println!("Response: {}", response);
Summary
libzmq is a powerful and versatile messaging library suitable for complex distributed systems, while orpc appears to be a simpler RPC framework focused on ease of use. libzmq offers more features and language support but may be overkill for basic RPC needs. orpc seems to provide a more straightforward API for simple remote procedure calls, potentially making it easier to implement for smaller projects or those primarily using Rust.
The java implementation of Apache Dubbo. An RPC and microservice framework.
Pros of Dubbo
- Mature and widely adopted in enterprise environments
- Extensive feature set including load balancing, service governance, and monitoring
- Strong community support and regular updates
Cons of Dubbo
- Steeper learning curve due to its comprehensive nature
- Heavier footprint, which may be overkill for smaller projects
- Primarily Java-focused, with limited support for other languages
Code Comparison
ORPC (Python):
@orpc.service
class MyService:
def hello(self, name: str) -> str:
return f"Hello, {name}!"
Dubbo (Java):
@Service
public class MyServiceImpl implements MyService {
public String hello(String name) {
return "Hello, " + name + "!";
}
}
Key Differences
- ORPC is more lightweight and focused on simplicity, while Dubbo offers a more comprehensive ecosystem
- ORPC is primarily designed for Python, whereas Dubbo is Java-centric with some multi-language support
- Dubbo provides more built-in features for service discovery and load balancing, while ORPC relies on external tools for these functionalities
Use Cases
- Choose ORPC for smaller Python projects prioritizing simplicity and ease of use
- Opt for Dubbo in large-scale Java enterprise applications requiring robust service governance and scalability
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME

Typesafe APIs Made Simple ðª
oRPC is a powerful combination of RPC and OpenAPI, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards
Highlights
- ð End-to-End Type Safety: Ensure type-safe inputs, outputs, and errors from client to server.
- ð First-Class OpenAPI: Built-in support that fully adheres to the OpenAPI standard.
- ð Contract-First Development: Optionally define your API contract before implementation.
- âï¸ Framework Integrations: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), Pinia Colada, and more.
- ð Server Actions: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
- ð Standard Schema Support: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
- ðï¸ Native Types: Supports native types like Date, File, Blob, BigInt, URL, and more.
- â±ï¸ Lazy Router: Enhance cold start times with our lazy routing feature.
- ð¡ SSE & Streaming: Enjoy full type-safe support for SSE and streaming.
- ð Multi-Runtime Support: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond.
- ð Extendability: Easily extend functionality with plugins, middleware, and interceptors.
- ð¡ï¸ Reliability: Well-tested, TypeScript-based, production-ready, and MIT licensed.
Documentation
You can find the full documentation here.
Packages
- @orpc/contract: Build your API contract.
- @orpc/server: Build your API or implement API contract.
- @orpc/client: Consume your API on the client with type-safety.
- @orpc/openapi: Generate OpenAPI specs and handle OpenAPI requests.
- @orpc/nest: Deeply integrate oRPC with NestJS.
- @orpc/react: Utilities for integrating oRPC with React and React Server Actions.
- @orpc/tanstack-query: TanStack Query integration.
- @orpc/vue-colada: Integration with Pinia Colada.
- @orpc/hey-api: Hey API integration.
- @orpc/zod: More schemas that Zod doesn't support yet.
- @orpc/valibot: OpenAPI spec generation from Valibot.
- @orpc/arktype: OpenAPI spec generation from ArkType.
Overview
This is a quick overview of how to use oRPC. For more details, please refer to the documentation.
-
Define your router:
import type { IncomingHttpHeaders } from 'node:http' import { ORPCError, os } from '@orpc/server' import { z } from 'zod' const PlanetSchema = z.object({ id: z.number().int().min(1), name: z.string(), description: z.string().optional(), }) export const listPlanet = os .input( z.object({ limit: z.number().int().min(1).max(100).optional(), cursor: z.number().int().min(0).default(0), }), ) .handler(async ({ input }) => { // your list code here return [{ id: 1, name: 'name' }] }) export const findPlanet = os .input(PlanetSchema.pick({ id: true })) .handler(async ({ input }) => { // your find code here return { id: 1, name: 'name' } }) export const createPlanet = os .$context<{ headers: IncomingHttpHeaders }>() .use(({ context, next }) => { const user = parseJWT(context.headers.authorization?.split(' ')[1]) if (user) { return next({ context: { user } }) } throw new ORPCError('UNAUTHORIZED') }) .input(PlanetSchema.omit({ id: true })) .handler(async ({ input, context }) => { // your create code here return { id: 1, name: 'name' } }) export const router = { planet: { list: listPlanet, find: findPlanet, create: createPlanet } }
-
Create your server:
import { createServer } from 'node:http' import { RPCHandler } from '@orpc/server/node' import { CORSPlugin } from '@orpc/server/plugins' const handler = new RPCHandler(router, { plugins: [new CORSPlugin()] }) const server = createServer(async (req, res) => { const result = await handler.handle(req, res, { context: { headers: req.headers } }) if (!result.matched) { res.statusCode = 404 res.end('No procedure matched') } }) server.listen( 3000, '127.0.0.1', () => console.log('Listening on 127.0.0.1:3000') )
-
Create your client:
import type { RouterClient } from '@orpc/server' import { createORPCClient } from '@orpc/client' import { RPCLink } from '@orpc/client/fetch' const link = new RPCLink({ url: 'http://127.0.0.1:3000', headers: { Authorization: 'Bearer token' }, }) export const orpc: RouterClient<typeof router> = createORPCClient(link)
-
Consume your API:
import { orpc } from './client' const planets = await orpc.planet.list({ limit: 10 })
-
Generate OpenAPI Spec:
import { OpenAPIGenerator } from '@orpc/openapi' import { ZodToJsonSchemaConverter } from '@orpc/zod' const generator = new OpenAPIGenerator({ schemaConverters: [new ZodToJsonSchemaConverter()] }) const spec = await generator.generate(router, { info: { title: 'Planet API', version: '1.0.0' } }) console.log(spec)
Sponsors
References
oRPC is inspired by existing solutions that prioritize type safety and developer experience. Special acknowledgments to:
- tRPC: For pioneering the concept of end-to-end type-safe RPC and influencing the development of type-safe APIs.
- ts-rest: For its emphasis on contract-first development and OpenAPI integration, which have greatly inspired oRPCâs feature set.
License
Distributed under the MIT License. See LICENSE for more information.
Top Related Projects
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot