|
| 1 | +--- |
| 2 | +title: oRPC v1 Announcement - Typesafe APIs Made Simple πͺ |
| 3 | +description: oRPC v1 is now available - tRPC, ts-rest, next-safe-action, and more alternatives! |
| 4 | +titleTemplate: ':title' |
| 5 | +--- |
| 6 | + |
| 7 | +# oRPC v1 Announcement - Typesafe APIs Made Simple πͺ |
| 8 | + |
| 9 | +oRPC is a thing help you build type-safe APIs with TypeScript. It's has own goal but can fairly be compared to other libraries like tRPC, ts-rest, next-safe-action, etc. or even serve as an alternative to them. |
| 10 | + |
| 11 | +## My Story |
| 12 | + |
| 13 | +My oRPC journey started in early 2024 after I lost my job. Finding a new one was hard, and I realized a standard job wasn't really what I wanted. I had always dreamed of being an "indie hacker" β someone who makes useful things for others. |
| 14 | + |
| 15 | +But looking back at my past work, I noticed something: I often spent more time complaining about the tools I used than focusing on what users needed. Maybe I cared too much about the tools themselves. |
| 16 | + |
| 17 | +Because I was often frustrated with existing tools, I changed my plan. I thought, "What if I make a tool for developers, one that fixes the problems I always had?" I hoped that if I built a tool I liked, other developers would like it too. |
| 18 | + |
| 19 | +That's how oRPC started. I began working hard on it around September 17, 2024. It wasn't easy; I had to rebuild oRPC three times to get the base right. After about three months, I shared an early version on Reddit ([see post](https://www.reddit.com/r/nextjs/comments/1h13upv/new_introducing_orpc_a_dropin_replacement_for/)). |
| 20 | + |
| 21 | +At first, oRPC was just a side project. Then, a turning point came when someone privately offered **$100** to support it. I was surprised and really motivated! A month after that, I decided to stop my other projects and work on oRPC full-time, even though I didn't have another job. My life became: code, eat, sleep, repeat. |
| 22 | + |
| 23 | +I had so many ideas for oRPC. I realized it would take all my focus and time, probably until the end of 2025, to make it happen. |
| 24 | + |
| 25 | +But !!! Today is a **big step** on that journey. I'm happy and proud to announce that the core of oRPC is now stable, and Version 1.0 is officially out! |
| 26 | + |
| 27 | +::: info |
| 28 | +V1 means the public API is stable and ready for production use. |
| 29 | +::: |
| 30 | + |
| 31 | +## The Idea behind oRPC |
| 32 | + |
| 33 | +oRPC philosophy is **powerful simplicity**. Define your API endpoints almost as easily as writing standard functions, yet automatically gain: |
| 34 | + |
| 35 | +- End-to-end type safety (includes **errors**) |
| 36 | +- Server Action compatibility |
| 37 | +- Full OpenAPI specification generation |
| 38 | +- Contract-first workflow support |
| 39 | +- Standard function call compatibility |
| 40 | + |
| 41 | +```ts |
| 42 | +const getting = os |
| 43 | + .use(dbProvider) |
| 44 | + .use(requiredAuth) |
| 45 | + .use(rateLimit) |
| 46 | + .use(analytics) |
| 47 | + .use(sentryMonitoring) |
| 48 | + .use(retry({ times: 3 })) |
| 49 | + .route({ method: 'GET', path: '/getting/{id}' }) |
| 50 | + .input(z.object({ id: z.string() })) |
| 51 | + .use(canGetting, input => input.id) |
| 52 | + .errors({ |
| 53 | + SOME_TYPE_SAFE_ERROR: { |
| 54 | + data: z.object({ something: z.string() }) |
| 55 | + } |
| 56 | + }) |
| 57 | + .handler(async ({ input, errors, context }) => { |
| 58 | + // do something |
| 59 | + }) |
| 60 | + .actionable() // server action compatible |
| 61 | + .callable() // regular function compatible |
| 62 | +``` |
| 63 | + |
| 64 | +Beyond built-in features, oRPC [metadata](https://orpc.unnoq.com/docs/metadata) system allows for community-driven extensions and future possibilities. |
| 65 | + |
| 66 | +## Highlights |
| 67 | + |
| 68 | +- **π End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server. |
| 69 | +- **π First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard. |
| 70 | +- **π Contract-First Development**: Optionally define your API contract before implementation. |
| 71 | +- **βοΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. |
| 72 | +- **π Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms. |
| 73 | +- **π Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators. |
| 74 | +- **ποΈ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more. |
| 75 | +- **β±οΈ Lazy Router**: Enhance cold start times with our lazy routing feature. |
| 76 | +- **π‘ SSE & Streaming**: Enjoy full type-safe support for SSE and streaming. |
| 77 | +- **π Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond. |
| 78 | +- **π Extendability**: Easily extend functionality with plugins, middleware, and interceptors. |
| 79 | +- **π‘οΈ Reliability**: Well-tested, TypeScript-based, production-ready, and MIT licensed. |
| 80 | + |
| 81 | +## tRPC alternative |
| 82 | + |
| 83 | +I used tRPC extensively and really liked it. However, I needed OpenAPI support for my projects. Although I found `trpc-openapi` to add OpenAPI to tRPC, it didn't work with Edge runtimes and has since been deprecated. This was very frustrating, prompting me to look for alternatives. |
| 84 | + |
| 85 | +Also, setting up tRPC sometimes felt too complicated, especially for smaller projects like Cloudflare Durable Objects where I just needed a simple API. Another point is that tRPC mostly supports React Query. That was okay for me, but less helpful if you want to use Vue, Solid, or Svelte. |
| 86 | + |
| 87 | +I did some **simple** benchmarks between oRPC and tRPC, and results show (full report [here](https://github.com/unnoq/orpc-benchmarks)): |
| 88 | + |
| 89 | +- oRPC is **1,6 times typecheck faster** (5.9s vs 9.3s) |
| 90 | +- oRPC is **2,8 times runtime faster** (295k reqs vs 104k reqs / 20 sec) |
| 91 | +- oRPC is **1,26 times less max cpu usage** (102% vs 129%) |
| 92 | +- oRPC is **2,6 times less max ram usage** (103MB vs 268MB) |
| 93 | +- oRPC is **2,6 smaller in bundle size** ([32.5 kB](https://bundlejs.com/?q=%40orpc%2Fserver%2Cnode%3Ahttp%2C%40orpc%2Fclient%2C%40orpc%2Fclient%2Ffetch%2C%40orpc%2Fserver%2C%40orpc%2Fserver%2Fnode&treeshake=%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D&text=%22const+router+%3D+%7B%5Cn++ping%3A+os.handler%28%28%29+%3D%3E+%27pong%27%29%2C%5Cn%7D%5Cn%5Cnconst+handler+%3D+new+RPCHandler%28router%2C+%7B%5Cn++strictGetMethodPluginEnabled%3A+false%2C%5Cn%7D%29%5Cn%5Cnexport+const+server+%3D+createServer%28async+%28req%2C+res%29+%3D%3E+%7B%5Cn++const+%7B+matched+%7D+%3D+await+handler.handle%28req%2C+res%29%5Cn%5Cn++if+%28%21matched%29+%7B%5Cn++++res.statusCode+%3D+404%5Cn++++res.end%28%27Not+Found%27%29%5Cn++%7D%5Cn%7D%29%5Cn%5Cnconst+link+%3D+new+RPCLink%28%7B%5Cn++url%3A+%27https%3A%2F%2Fexample.com%27%2C%5Cn%7D%29%5Cn%5Cnexport+const+orpc%3A+RouterClient%3Ctypeof+router%3E+%3D+createORPCClient%28link%29%22) vs [84.5 kB](https://bundlejs.com/?q=%40trpc%2Fclient%2C%40trpc%2Fserver%2C%40trpc%2Fserver%2Fadapters%2Fstandalone%2Csuperjson&treeshake=%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D&share=MYewdgzgLgBLC8MCWYlQCoCUAKBhAdMAE4CmAhlCQBQDeAUDHEWZAGYhEC2JRAXDBACuABx4ArCOAA0dAL4BKOnVCRYZYcMwhBlIjERR8RbbtoMYwlAHN%2Bh4ceAkAJoNL4AjoJ4BPKlXn6AHwwAOTC4FYh8jIKSiQAHuFEsCrQAjwAbjz6MMTklAAS6OjYAMqZPGaMxjo8-OqaJjwyjHkUJLjglPFQ-jD0jNUkUK5g-bLmsjGKdAlJKeBpUETCwDltlFh4uAA2SCRgUAA8UN6iIKwwDVq1RIFVMHtgANYQ-ADa5owQwntQADIoZ4PQa5cBONBIcD8EDCIIwWH4U6ifTwRAhIQAIwgxCQwigULAIRaoKYXn4AAsoFBhKVBNjcfjCYCXiDSa4dvwQlSaW8APR8hJkTi-EiEECcYlfUnLFgQdhcOoCETiSRgEmghQawasMg7CAkSnU4Qs4EDUmMDlcnnCfmC%2BLC0XiyXa0Gytgcbh8ZWiIgSaTSxha6XBxgAXWmQA)) |
| 94 | + |
| 95 | +:::warning |
| 96 | +Benchmark results can vary across environments and depend heavily on factors like your project's size, complexity, and setup. Many conditions can influence the outcome β so treat these numbers as a helpful reference, not a guarantee. |
| 97 | +::: |
| 98 | + |
| 99 | +::: info |
| 100 | +You can read more about comparion [here](/docs/comparison) |
| 101 | +::: |
| 102 | + |
| 103 | +## ts-rest alternative |
| 104 | + |
| 105 | +After running into the OpenAPI issues with tRPC, I tried ts-rest. While it helped with OpenAPI, I soon found it was missing features I relied on from tRPC, like flexible middleware and easy handling of certain data types (like Dates or Files). After using it for some APIs, I felt it wasn't the complete solution I wanted. This frustration was a key reason I started building oRPC. |
| 106 | + |
| 107 | +::: info |
| 108 | +You can read more about comparion [here](/docs/comparison) |
| 109 | +::: |
| 110 | + |
| 111 | +## next-safe-action alternative |
| 112 | + |
| 113 | +I also experimented with `next-safe-action` to test server actions in Next.js, hoping they might be a good replacement for the tRPC style. However, I found they didn't quite fit my needs. I believe a dedicated RPC library like oRPC still provides a better developer experience for building APIs. |
| 114 | + |
| 115 | +## Sponsors |
| 116 | + |
| 117 | +In this long journey, I specially thank all my sponsors, they help me to keep going. |
| 118 | + |
| 119 | +- [Zuplo - Serverless API Gateway, designed for developers](https://zuplo.link/orpc) |
| 120 | +- [ζδΈγγ](https://github.com/SanMurakami) |
| 121 | +- [γγγγγ¨γΌγ«γ
](https://github.com/u1-liquid) |
| 122 | +- [motopods](https://github.com/motopods) |
| 123 | +- [Maxie](https://github.com/MrMaxie) |
| 124 | +- [Stijn Timmer](https://github.com/Stijn-Timmer) |
| 125 | +- [Robbe95](https://github.com/Robbe95) |
| 126 | +- And my first sponsor (private) to start my story |
| 127 | + |
| 128 | +If you're interesting in sponsoring oRPC, you can do it [here](https://github.com/sponsors/unnoq). |
| 129 | + |
| 130 | +<p align="center"> |
| 131 | + <a href="https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg"> |
| 132 | + <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg'/> |
| 133 | + </a> |
| 134 | +</p> |
0 commit comments